Number or string representation of a Writer TextRange

Creating Extension - Shared Libraries
Forum rules
For sharing working examples of macros / scripts. These can be in any script language supported by OpenOffice.org [Basic, Python, Netbean] or as source code files in Java or C# even - but requires the actual source code listing. This forum is not for asking questions about writing your own macros.

Number or string representation of a Writer TextRange

Postby JeJe » Tue Mar 03, 2020 11:00 pm

Posting this as wanted it a while ago but didn't think it was available from Basic.

Every paragraph has an id no so a text paragraph's textrange position will be that ID plus the character offset from the start of the paragraph.

Below example gets the paragraph ID and character positions of the selection (viewcursor), clears that selection, then restores it using that information. Select some text in a document, run main.

Tested on OO only, may not work with something more complicated than just text paragraphs.


Code: Select all   Expand viewCollapse view



Sub Main
   dim paraID1 as string,charNO1 as string,paraID2 as string,charNO2 as string

   'get paraID and charno representation of viewcursor start and end of textranges
   tc =thiscomponent.text.createtextcursorbyrange(thiscomponent.currentcontroller.viewcursor.getstart)
   getTextRangeParaIDAndCharNo(tc,paraID1,charNO1)
   tc =thiscomponent.text.createtextcursorbyrange(thiscomponent.currentcontroller.viewcursor.getend)
   getTextRangeParaIDAndCharNo(tc,paraID2,charNO2)

   thiscomponent.currentcontroller.select(thiscomponent.text.getstart) 'clear selection by moving viewcursor to start


   msgbox paraID1 & "," &  charno1 & chr(10) &  paraID2 & "," &  charno2
   'restore selection from paraIDs and charno
   tc3 = setTextRangeFromParaIDAndCharNo(thiscomponent,paraID1,charno1)
   tc4 = setTextRangeFromParaIDAndCharNo(thiscomponent,paraID2,charno2)
   tc3.gotorange(tc4,true)
   thiscomponent.currentcontroller.select(tc3,false)

end sub

sub getTextRangeParaIDAndCharNo(tc,byref paraID as string,byref charNo as string)
   tc.gotostartofparagraph(true)
   cno= len(tc.string)
   en = tc.createenumeration
   do until en.hasmoreelements = false
      p =en.nextelement
      paraID =endval( p.localname)
      charNo = cno
      exit do
   loop
End sub

function setTextRangeFromParaIDAndCharNo(componentv,paraID as string,charNo as string)
   lenno = len(paraID)
   en = componentv.text.createenumeration
   do until en.hasmoreelements = false
      p =en.nextelement
      if right (p.localname,lenno) = paraID then
         tc =componentV.text.createtextcursorbyrange(p)
         tc.gotoStartOfParagraph(false)
         tc.goright(val(charNO),false)
         setTextRangeFromParaIDAndCharNo=tc
         exit do
      end if
   loop
End function

Function EndVal(st As String) As Long


   Dim i As Long, a As Integer, s As String, res As String
   res = ""
   s = ""
   For i = Len(st) To 1 Step -1
      s = Mid(st, i, 1)
      a = Asc(s)
      If a >= 48 And a <= 57 Then
         res = s & res
      Else
         Exit For
      End If
   Next
   EndVal = Val(res)
End Function




Edit: didn't include the endval function to get the number at the end of a string - added.
Last edited by JeJe on Wed Mar 04, 2020 2:12 am, edited 3 times in total.
Openoffice 4.1.2
Windows 8
JeJe
Volunteer
 
Posts: 789
Joined: Wed Mar 09, 2016 2:40 pm

Re: Number or string representation of a Writer TextRange

Postby musikai » Wed Mar 04, 2020 12:11 am

Didn't know about paragraph Id's.
Usage?
Why not just use cursor.gotorange()?
Win7 Pro, Lubuntu 15.10, LO 4.4.7, OO 4.1.3
Free Project: LibreOffice Songbook Architect (LOSA)
http://struckkai.blogspot.de/2015/04/libreofficesongbookarchitect.html
musikai
Volunteer
 
Posts: 278
Joined: Wed Nov 11, 2015 12:19 am

Re: Number or string representation of a Writer TextRange

Postby JeJe » Wed Mar 04, 2020 1:46 am

The point is its a way of saving the range position... to a text file/property/for later whatever. Otherwise you can only know where a textrange is in relation to another text range and you can't do that.

Para Ids are potentially very useful to me. If you identify a paragraph by number... say the 15th para in the document... then the position may change if the document is edited. Using the para id the correct para can still be found. I could have a note or data for that para (in a property or an external file) without there needing to be a placeholder in the document marking the note.
Openoffice 4.1.2
Windows 8
JeJe
Volunteer
 
Posts: 789
Joined: Wed Mar 09, 2016 2:40 pm

Re: Number or string representation of a Writer TextRange

Postby JeJe » Wed Mar 11, 2020 3:35 pm

With some help from Lupp, a bit more involved version that handles a selection that is in a textframe, texttable, header or footer too.

Code: Select all   Expand viewCollapse view
Sub Main
   on error goto hr
   txt=thiscomponent.currentcontroller.viewcursor.text

   vcstart=getrangestring(true)
   vcend = getrangestring(false)

   thiscomponent.currentcontroller.select(txt.start)
   msgbox vcstart & chr(10) & vcend
   tc3 = getrangefromstring(vcstart)
   tc4 = getrangefromstring(vcend)
   tc3.gotorange(tc4,true)
   thiscomponent.currentcontroller.select(tc3,false)

   hr: 'possibly no text selection
End Sub

function getrangefromstring(st)
   dim found as boolean
   vc= thiscomponent.currentcontroller.viewcursor
   sts = split(st,"|")

   select case sts(0)
   case "SwXBodyText"
      getrangefromstring =setTextRangeFromParaIDAndCharNo(thiscomponent.gettext,sts(1),sts(2),found)
   case "SwXTextFrame" 'text frame
      For Each frame In thiscomponent.textFrames

         getrangefromstring =setTextRangeFromParaIDAndCharNo(frame.gettext,sts(1),sts(2),found)
         if found then exit for
      next frame

   case "SwXCell" 'text table

      doc = ThisComponent
      tts = ThisComponent.TextTables ' this bit pinched from Lupp
      if tts.count > 0 then
      For j = 0 To tts.Count - 1
         j_tt = tts(j)
         cns = j_tt.CellNames
         For k = 0 To Ubound(cns)
            cell = j_tt.getCellByName(cns(k))
            getrangefromstring =setTextRangeFromParaIDAndCharNo( cell.Text,sts(1),sts(2),found)
            if found then goto hr
         Next k
      Next j
   end if
hr:
   case "SwXHeadFootText"


      ps =thiscomponent.StyleFamilies.getByName("PageStyles")
      for i = 0 to ps.count -1
         s = ps.getbyindex(i)
         if s.headerison then
            getrangefromstring =setTextRangeFromParaIDAndCharNo( s.headertext,sts(1),sts(2),found)
            if found then exit for
         end if
         if s.footerison then
            getrangefromstring =setTextRangeFromParaIDAndCharNo(s.footertext,sts(1),sts(2),found)
            if found then exit for
         end if

      next



   case else

      exit function
   end select

end function


function getrangestring(isstart)
   vc= thiscomponent.currentcontroller.viewcursor
   getrangestring =vc.text.implementationname & "|"
   select case vc.text.implementationname
   case "SwXCell"
      tc= vc.cell.gettext.createTextCursorByRange( vc)
   case "SwXTextFrame"
      tc = vc.textframe.gettext.createTextCursorByRange( vc)
   case "SwXBodyText"
      tc = thiscomponent.gettext.createTextCursorByRange(vc)
   case "SwXHeadFootText"
      tc = vc.gettext.createTextCursorByRange(vc)
   case else
      exit function
   end select

   if isstart then TC.collapsetostart else TC.COLLAPSETOEND
   en = tc.createenumeration
   do until en.hasmoreelements = false
      p = en.nextelement
      getrangestring = getrangestring & p.localname
      exit do
   loop

   tc.gotostartofparagraph(true)
   getrangestring = getrangestring & "|" & len(tc.string)

   select case vc.text.implementationname
   case "SwXCell"
      getrangestring = getrangestring & "|" &  vc.texttable.name & "|" & vc.cell.cellname
   case "SwXTextFrame"
      getrangestring = getrangestring & "|" & vc.textframe.name
   case "SwXBodyText"

   end select

end function

function setTextRangeFromParaIDAndCharNo(txt,paraid as string,charno as string,byref found as boolean)
   en = txt.createenumeration
   do until en.hasmoreelements = false
      p =en.nextelement
      if p.supportsService("com.sun.star.text.Paragraph") Then
         if p.localname= paraID then
            found = true
            tc =txt.createtextcursorbyrange(p)
            tc.gotoStartOfParagraph(false)
            tc.goright(val(charNO),false)
            setTextRangeFromParaIDAndCharNo=tc
            exit do
         end if
      end if
   loop
end function



Edit: Added fixes for table
Openoffice 4.1.2
Windows 8
JeJe
Volunteer
 
Posts: 789
Joined: Wed Mar 09, 2016 2:40 pm

Re: Number or string representation of a Writer TextRange

Postby JeJe » Tue Mar 17, 2020 1:52 pm

Final (probably) bit more involved version again that handles footnotes and endnotes as well.

Code: Select all   Expand viewCollapse view

sub testsub
CURRENTSelection
end sub


sub SelectRangeFromString(vcstart,vcend)
   tc3 = getrangefromstring(vcstart)
   tc4 = getrangefromstring(vcend)
   tc3.gotorange(tc4,true)
   thiscomponent.currentcontroller.select(tc3,false)
end sub
function createrangeFromString(vcstart,vcend)
   tc3 = getrangefromstring(vcstart)
   tc4 = getrangefromstring(vcend)
   tc3.gotorange(tc4,true)
   createrangeFromString =tc3
end function


function GetMultipleSelections()
   sel= thiscomponent.currentcontroller.selection

   if sel.count>0 then
      for i =0 to  sel.count-1
         vcstart =getrangestring2(sel.getbyindex(i),true)
         vcend = getrangestring2(sel.getbyindex(i),false)
         if i <>0 then st = st & chr(13)
         st = st & vcstart & "," & vcend
      next
      GetMultipleSelections= st
      msgbox st
   end if
End function


Sub currentSelection
   on error goto hr
   
   vcstart=getrangestring(true)
   if vcstart =nullstring then exit sub
   vcend = getrangestring(false)


   thiscomponent.currentcontroller.select(thiscomponent.gettext.start)


   msgbox vcstart & chr(10) & vcend

   tc3 = getrangefromstring(vcstart)
   tc4 = getrangefromstring(vcend)
   tc3.gotorange(tc4,true)
   thiscomponent.currentcontroller.select(tc3,false)

   hr: 'possibly no text selection
End Sub

function getrangefromstring(st)
   dim found as boolean
   vc= thiscomponent.currentcontroller.viewcursor
   sts = split(st,"|")

   select case sts(0)
   case "SwXBodyText"
      getrangefromstring =setTextRangeFromParaIDAndCharNo(thiscomponent.gettext,sts(1),sts(2),found)
   case "SwXTextFrame" 'text frame
      For Each frame In thiscomponent.textFrames

         getrangefromstring =setTextRangeFromParaIDAndCharNo(frame.gettext,sts(1),sts(2),found)
         if found then exit for
      next frame

   case "SwXCell" 'text table

      'if thiscomponent.texttables.hasbyname( sts(3)) then
      'tbl =thiscomponent.texttables.getbyname( sts(3))
      '      cns = tbl.CellNames
      '         For k = 0 To Ubound(cns)
      '            if cns(k) = sts(4) then
      '            getrangefromstring =setTextRangeFromParaIDAndCharNo( tbl.getcellbyname(sts(4)).Text,sts(1),sts(2),found)
      '            exit for
      '            end if
      '            next
      '            if not found then getrangefromstring =getrangefromstring2(st)
      'end if

      tts = ThisComponent.TextTables ' this bit pinched from Lupp
      if tts.count > 0 then
         For j = 0 To tts.Count - 1
            j_tt = tts(j)
            cns = j_tt.CellNames
            For k = 0 To Ubound(cns)
               cell = j_tt.getCellByName(cns(k))
               getrangefromstring =setTextRangeFromParaIDAndCharNo( cell.Text,sts(1),sts(2),found)
               if found then goto hr
            Next k
         Next j
      end if
hr:
   case "SwXHeadFootText"


      ps =thiscomponent.StyleFamilies.getByName("PageStyles")
      for i = 0 to ps.count -1
         s = ps.getbyindex(i)
         if s.headerison then
            getrangefromstring =setTextRangeFromParaIDAndCharNo( s.headertext,sts(1),sts(2),found)
            if found then exit for
         end if
         if s.footerison then
            getrangefromstring =setTextRangeFromParaIDAndCharNo(s.footertext,sts(1),sts(2),found)
            if found then exit for
         end if

      next


   CASE "SwXFootnote"

      fnotes = thiscomponent.footnotes
      if fnotes.count > 0 then
         for i = 0 to fnotes.count -1
            getrangefromstring =setTextRangeFromParaIDAndCharNo(fnotes.getbyindex(i).gettext,sts(1),sts(2),found)

            if found = true then exit for
         next
      end if
      if found = false then
         enotes = thiscomponent.endnotes
         if enotes.count > 0 then
            for i = 0 to enotes.count -1
               getrangefromstring =setTextRangeFromParaIDAndCharNo(enotes.getbyindex(i).gettext,sts(1),sts(2),found)
               if found = true then exit for
            next
         end if
      end if


   CASE "SwXTextViewCursor"
   end select

end function


function getrangestring(isstart)
   vc= thiscomponent.currentcontroller.viewcursor

   if hastextinterface(vc) = false then exit function

      getrangestring =vc.text.implementationname & "|"

      select case vc.text.implementationname
      case "SwXCell"
         tc= vc.cell.gettext.createTextCursorByRange( vc)
      case "SwXTextFrame"
         tc = vc.textframe.gettext.createTextCursorByRange( vc)
      case "SwXBodyText"
         tc = thiscomponent.gettext.createTextCursorByRange(vc)
      case "SwXHeadFootText"
         tc = vc.gettext.createTextCursorByRange(vc)
      CASE "SwXFootnote"
         tc = vc.gettext.createTextCursorByRange(vc)
      CASE "SwXTextViewCursor"
      case else
         exit function
      end select
   if isstart then TC.collapsetostart else TC.COLLAPSETOEND
   en = tc.createenumeration
   do until en.hasmoreelements = false
      p = en.nextelement
      getrangestring = getrangestring & p.localname
      exit do
   loop

   tc.gotostartofparagraph(true)
   getrangestring = getrangestring & "|" & len(tc.string)

   select case vc.text.implementationname
   case "SwXCell"
      getrangestring = getrangestring & "|" &  vc.texttable.name & "|" & vc.cell.cellname
   case "SwXTextFrame"
      getrangestring = getrangestring & "|" & vc.textframe.name
'   case "SwXBodyText"
'   case "SwXHeadFootText"
   CASE "SwXFootnote"
      getrangestring = getrangestring & "|" &    tc.parastylename
   end select

      'note for comments gettext is empty. The text is found from textfield.textrange.text
      'But may return void for the textfield and the viewcursor does not appear to give information to identify the
      'selected paragraph when void is not returned. So not been implemented
      'if isempty(vc.TEXTFIELD) =false then
      'getrangestring ="SwXTextViewCursor|"
      'getrangestring =getrangestring & vc.textfield.Author
      'tc=vc.textfield.textrange.text.createTextCursorByRange(vc.textfield.textrange) ' .ImplementationName 'SvxUnoTextBase
      'with vc.textfield.datetimevalue
      'tmp =cstr(.Year) & "," & cstr(.Month)  & "," & cstr(.Day) & "," & cstr(.Hours) & "," & cstr(.Minutes) &  "," & cstr(.Seconds) & "," & cstr(.HundredthSeconds) & "|"
      'end with

end function

function setTextRangeFromParaIDAndCharNo(txt,paraid as string,charno as string,byref found as boolean)
   en = txt.createenumeration
   do until en.hasmoreelements = false
      p =en.nextelement
      if p.supportsService("com.sun.star.text.Paragraph") Then
         if p.localname= paraID then
            found = true
            tc =txt.createtextcursorbyrange(p)
            tc.gotoStartOfParagraph(false)
            tc.goright(val(charNO),false)
            setTextRangeFromParaIDAndCharNo=tc
            exit do
         end if
      end if
   loop
end function


function hastextinterface(vc) as boolean
   hastextinterface = false
   on error goto hr
   txt = vc.text
   hastextinterface = true
   exit function
hr:
end function




function getrangefromstring2(st) 'SEARCHES ALL TEXT RANGES
   dim found as boolean
   vc= thiscomponent.currentcontroller.viewcursor
   sts = split(st,"|")

      getrangefromstring2 =setTextRangeFromParaIDAndCharNo(thiscomponent.gettext,sts(1),sts(2),found)


   if (found = false and thiscomponent.textFrames.count > 0) then 'text frames
   For Each frame In thiscomponent.textFrames
      getrangefromstring2 =setTextRangeFromParaIDAndCharNo(frame.gettext,sts(1),sts(2),found)
      if found then exit for
   next frame
   end if


   if (found = false and thiscomponent.texttables.count > 0) then 'text table
      tts = ThisComponent.TextTables ' this bit pinched from Lupp
      if tts.count > 0 then
         For j = 0 To tts.Count - 1
            j_tt = tts(j)
            cns = j_tt.CellNames
            For k = 0 To Ubound(cns)
               cell = j_tt.getCellByName(cns(k))
               getrangefromstring2 =setTextRangeFromParaIDAndCharNo( cell.Text,sts(1),sts(2),found)
               if found then goto hr
            Next k
         Next j
      end if
   end if
   hr:

      if found = false then 'footnote
      fnotes = thiscomponent.footnotes
      if fnotes.count > 0 then
         for i = 0 to fnotes.count -1
            getrangefromstring2 =setTextRangeFromParaIDAndCharNo(fnotes.getbyindex(i).gettext,sts(1),sts(2),found)

            if found = true then exit for
         next
      end if
      end if
      
      if found = false then 'end note
         enotes = thiscomponent.endnotes
         if enotes.count > 0 then
            for i = 0 to enotes.count -1
               getrangefromstring2 =setTextRangeFromParaIDAndCharNo(enotes.getbyindex(i).gettext,sts(1),sts(2),found)
               if found = true then exit for
            next
         end if
      end if

      if found = false then 'header, footer
      ps =thiscomponent.StyleFamilies.getByName("PageStyles")
      for i = 0 to ps.count -1
         s = ps.getbyindex(i)
         if s.headerison then
            getrangefromstring2 =setTextRangeFromParaIDAndCharNo( s.headertext,sts(1),sts(2),found)
            if found then exit for
         end if
         if s.footerison then
            getrangefromstring2 =setTextRangeFromParaIDAndCharNo(s.footertext,sts(1),sts(2),found)
            if found then exit for
         end if

      next
      end if
end function






Edit: spoke too soon...
was also missing getrangestring2
Last edited by JeJe on Fri Mar 20, 2020 6:32 pm, edited 3 times in total.
Openoffice 4.1.2
Windows 8
JeJe
Volunteer
 
Posts: 789
Joined: Wed Mar 09, 2016 2:40 pm

Re: Number or string representation of a Writer TextRange

Postby JeJe » Fri Mar 20, 2020 6:27 pm

Added support for multiple selections as saw Ms Ruth's post on viewtopic.php?f=20&t=79676

And included sub missing in last post

to run testsub - create multiple selections in a document
when the msgbox is shown you can check that the selections are no longer there as the viewcursor is moved to the start of the document
the selections are then restored using the string shown in the msgbox


Code: Select all   Expand viewCollapse view
sub testsub
   st=GetMultipleSelections()
   thiscomponent.currentcontroller.select(thiscomponent.gettext.start)
   msgbox st

   setMultipleSelections(st)
   'CURRENTSelection
end sub


sub SelectRangeFromString(vcstart,vcend)
   tc3 = getrangefromstring(vcstart)
   tc4 = getrangefromstring(vcend)
   tc3.gotorange(tc4,true)
   thiscomponent.currentcontroller.select(tc3,false)
end sub
function createrangeFromString(vcstart,vcend)
   tc3 = getrangefromstring(vcstart)
   tc4 = getrangefromstring(vcend)
   tc3.gotorange(tc4,true)
   createrangeFromString =tc3
end function


function GetMultipleSelections()
   sel= thiscomponent.currentcontroller.selection

   if sel.count>0 then
      for i =0 to  sel.count-1
         vcstart =getrangestring2(sel.getbyindex(i),true)
         vcend = getrangestring2(sel.getbyindex(i),false)
         if i <>0 then st = st & chr(13)
         st = st & vcstart & "," & vcend
      next
      GetMultipleSelections= st

   end if
End function

sub SetMultipleSelections(st)
   on error goto hr
   Dim SrchAttributes(0) As New com.sun.star.beans.PropertyValue
   doc = thiscomponent

   doc.lockcontrollers
   sts = split(st,chr(13))
   for i =0 to ubound(sts)
      startend = split(sts(i),",")
      tc3 = getrangefromstring(startend(0))
      tc4 = getrangefromstring(startend(1))
      tc3.gotorange(tc4,true)
      tc3.CharFlash= true
   next

   vc= doc.currentcontroller.viewcursor
   SrchAttributes(0).Name = "CharFlash": SrchAttributes(0).Value =true
   'SrchAttributes(0).Name = "CharOverline": SrchAttributes(0).Value =1
   txtsearch = doc.createsearchdescriptor
   txtsearch.setSearchAttributes SrchAttributes
   txtsearch.setvaluesearch(false)
   Found = Doc.findAll(TxtSearch)

   ' include the first selection using  Ms Ruth's trick at https://forum.openoffice.org/en/forum/viewtopic.php?f=20&t=79676
   thiscomponent.currentcontroller.select(Found)
   VC.gotoRange(Found(0).Start, True)

   ' undo the property change leaving the selection
   VC.charflash = false

hr:
   doc.unlockcontrollers
end sub


Sub currentSelection
   on error goto hr

   vcstart=getrangestring(true)
   if vcstart =nullstring then exit sub
   vcend = getrangestring(false)


   thiscomponent.currentcontroller.select(thiscomponent.gettext.start)


   msgbox vcstart & chr(10) & vcend

   tc3 = getrangefromstring(vcstart)
   tc4 = getrangefromstring(vcend)
   tc3.gotorange(tc4,true)
   thiscomponent.currentcontroller.select(tc3,false)

   hr: 'possibly no text selection
End Sub

function getrangefromstring(st)
   dim found as boolean
   vc= thiscomponent.currentcontroller.viewcursor
   sts = split(st,"|")

   select case sts(0)
   case "SwXBodyText"
      getrangefromstring =setTextRangeFromParaIDAndCharNo(thiscomponent.gettext,sts(1),sts(2),found)
   case "SwXTextFrame" 'text frame
      For Each frame In thiscomponent.textFrames

         getrangefromstring =setTextRangeFromParaIDAndCharNo(frame.gettext,sts(1),sts(2),found)
         if found then exit for
      next frame

   case "SwXCell" 'text table

      'if thiscomponent.texttables.hasbyname( sts(3)) then
      'tbl =thiscomponent.texttables.getbyname( sts(3))
      '      cns = tbl.CellNames
      '         For k = 0 To Ubound(cns)
      '            if cns(k) = sts(4) then
      '            getrangefromstring =setTextRangeFromParaIDAndCharNo( tbl.getcellbyname(sts(4)).Text,sts(1),sts(2),found)
      '            exit for
      '            end if
      '            next
      '            if not found then getrangefromstring =getrangefromstring2(st)
      'end if

      tts = ThisComponent.TextTables ' this bit pinched from Lupp
      if tts.count > 0 then
         For j = 0 To tts.Count - 1
            j_tt = tts(j)
            cns = j_tt.CellNames
            For k = 0 To Ubound(cns)
               cell = j_tt.getCellByName(cns(k))
               getrangefromstring =setTextRangeFromParaIDAndCharNo( cell.Text,sts(1),sts(2),found)
               if found then goto hr
            Next k
         Next j
      end if
hr:
   case "SwXHeadFootText"


      ps =thiscomponent.StyleFamilies.getByName("PageStyles")
      for i = 0 to ps.count -1
         s = ps.getbyindex(i)
         if s.headerison then
            getrangefromstring =setTextRangeFromParaIDAndCharNo( s.headertext,sts(1),sts(2),found)
            if found then exit for
         end if
         if s.footerison then
            getrangefromstring =setTextRangeFromParaIDAndCharNo(s.footertext,sts(1),sts(2),found)
            if found then exit for
         end if

      next


   CASE "SwXFootnote"

      fnotes = thiscomponent.footnotes
      if fnotes.count > 0 then
         for i = 0 to fnotes.count -1
            getrangefromstring =setTextRangeFromParaIDAndCharNo(fnotes.getbyindex(i).gettext,sts(1),sts(2),found)

            if found = true then exit for
         next
      end if
      if found = false then
         enotes = thiscomponent.endnotes
         if enotes.count > 0 then
            for i = 0 to enotes.count -1
               getrangefromstring =setTextRangeFromParaIDAndCharNo(enotes.getbyindex(i).gettext,sts(1),sts(2),found)
               if found = true then exit for
            next
         end if
      end if


   CASE "SwXTextViewCursor"
   end select

end function


function getrangestring(isstart)
   vc= thiscomponent.currentcontroller.viewcursor

   if hastextinterface(vc) = false then exit function

   getrangestring =vc.text.implementationname & "|"

   select case vc.text.implementationname
   case "SwXCell"
      tc= vc.cell.gettext.createTextCursorByRange( vc)
   case "SwXTextFrame"
      tc = vc.textframe.gettext.createTextCursorByRange( vc)
   case "SwXBodyText"
      tc = thiscomponent.gettext.createTextCursorByRange(vc)
   case "SwXHeadFootText"
      tc = vc.gettext.createTextCursorByRange(vc)
   CASE "SwXFootnote"
      tc = vc.gettext.createTextCursorByRange(vc)
   CASE "SwXTextViewCursor"
   case else
      exit function
   end select
   if isstart then TC.collapsetostart else TC.COLLAPSETOEND
   en = tc.createenumeration
   do until en.hasmoreelements = false
      p = en.nextelement
      getrangestring = getrangestring & p.localname
      exit do
   loop

   tc.gotostartofparagraph(true)
   getrangestring = getrangestring & "|" & len(tc.string)

   select case vc.text.implementationname
   case "SwXCell"
      getrangestring = getrangestring & "|" &  vc.texttable.name & "|" & vc.cell.cellname
   case "SwXTextFrame"
      getrangestring = getrangestring & "|" & vc.textframe.name
      '   case "SwXBodyText"
      '   case "SwXHeadFootText"
   CASE "SwXFootnote"
      getrangestring = getrangestring & "|" &    tc.parastylename
   end select

   'note for comments gettext is empty. The text is found from textfield.textrange.text
   'But may return void for the textfield and the viewcursor does not appear to give information to identify the
   'selected paragraph when void is not returned. So not been implemented
   'if isempty(vc.TEXTFIELD) =false then
   'getrangestring ="SwXTextViewCursor|"
   'getrangestring =getrangestring & vc.textfield.Author
   'tc=vc.textfield.textrange.text.createTextCursorByRange(vc.textfield.textrange) ' .ImplementationName 'SvxUnoTextBase
   'with vc.textfield.datetimevalue
   'tmp =cstr(.Year) & "," & cstr(.Month)  & "," & cstr(.Day) & "," & cstr(.Hours) & "," & cstr(.Minutes) &  "," & cstr(.Seconds) & "," & cstr(.HundredthSeconds) & "|"
   'end with

end function

function setTextRangeFromParaIDAndCharNo(txt,paraid as string,charno as string,byref found as boolean)
   en = txt.createenumeration
   do until en.hasmoreelements = false
      p =en.nextelement
      if p.supportsService("com.sun.star.text.Paragraph") Then
         if p.localname= paraID then
            found = true
            tc =txt.createtextcursorbyrange(p)
            tc.gotoStartOfParagraph(false)
            tc.goright(val(charNO),false)
            setTextRangeFromParaIDAndCharNo=tc
            exit do
         end if
      end if
   loop
end function


function hastextinterface(vc) as boolean
   hastextinterface = false
   on error goto hr
   txt = vc.text
   hastextinterface = true
   exit function
hr:
end function




function getrangefromstring2(st) 'SEARCHES ALL TEXT RANGES
   dim found as boolean
   vc= thiscomponent.currentcontroller.viewcursor
   sts = split(st,"|")

   getrangefromstring2 =setTextRangeFromParaIDAndCharNo(thiscomponent.gettext,sts(1),sts(2),found)


   if (found = false and thiscomponent.textFrames.count > 0) then 'text frames
      For Each frame In thiscomponent.textFrames
         getrangefromstring2 =setTextRangeFromParaIDAndCharNo(frame.gettext,sts(1),sts(2),found)
         if found then exit for
      next frame
   end if


   if (found = false and thiscomponent.texttables.count > 0) then 'text table
      tts = ThisComponent.TextTables ' this bit pinched from Lupp
      if tts.count > 0 then
         For j = 0 To tts.Count - 1
            j_tt = tts(j)
            cns = j_tt.CellNames
            For k = 0 To Ubound(cns)
               cell = j_tt.getCellByName(cns(k))
               getrangefromstring2 =setTextRangeFromParaIDAndCharNo( cell.Text,sts(1),sts(2),found)
               if found then goto hr
            Next k
         Next j
      end if
   end if
hr:

   if found = false then 'footnote
      fnotes = thiscomponent.footnotes
      if fnotes.count > 0 then
         for i = 0 to fnotes.count -1
            getrangefromstring2 =setTextRangeFromParaIDAndCharNo(fnotes.getbyindex(i).gettext,sts(1),sts(2),found)

            if found = true then exit for
         next
      end if
   end if

   if found = false then 'end note
      enotes = thiscomponent.endnotes
      if enotes.count > 0 then
         for i = 0 to enotes.count -1
            getrangefromstring2 =setTextRangeFromParaIDAndCharNo(enotes.getbyindex(i).gettext,sts(1),sts(2),found)
            if found = true then exit for
         next
      end if
   end if

   if found = false then 'header, footer
      ps =thiscomponent.StyleFamilies.getByName("PageStyles")
      for i = 0 to ps.count -1
         s = ps.getbyindex(i)
         if s.headerison then
            getrangefromstring2 =setTextRangeFromParaIDAndCharNo( s.headertext,sts(1),sts(2),found)
            if found then exit for
         end if
         if s.footerison then
            getrangefromstring2 =setTextRangeFromParaIDAndCharNo(s.footertext,sts(1),sts(2),found)
            if found then exit for
         end if

      next
   end if
end function



function getrangestring2(vc,isstart)
   '   vc= thiscomponent.currentcontroller.viewcursor

   if hastextinterface(vc) = false then exit function

   getrangestring2 =vc.text.implementationname & "|"

   select case vc.text.implementationname
   case "SwXCell"
      tc= vc.cell.gettext.createTextCursorByRange( vc)
   case "SwXTextFrame"
      tc = vc.textframe.gettext.createTextCursorByRange( vc)
   case "SwXBodyText"
      tc = thiscomponent.gettext.createTextCursorByRange(vc)
   case "SwXHeadFootText"
      tc = vc.gettext.createTextCursorByRange(vc)
   CASE "SwXFootnote"
      tc = vc.gettext.createTextCursorByRange(vc)
   CASE "SwXTextViewCursor"
   case else
      exit function
   end select
   if isstart then TC.collapsetostart else TC.COLLAPSETOEND
   en = tc.createenumeration
   do until en.hasmoreelements = false
      p = en.nextelement
      getrangestring2 = getrangestring2 & p.localname
      exit do
   loop

   tc.gotostartofparagraph(true)
   getrangestring2 = getrangestring2 & "|" & len(tc.string)

   select case vc.text.implementationname
   case "SwXCell"
      getrangestring2 = getrangestring & "|" &  vc.texttable.name & "|" & vc.cell.cellname
   case "SwXTextFrame"
      getrangestring2 = getrangestring & "|" & vc.textframe.name
      '   case "SwXBodyText"
      '   case "SwXHeadFootText"
   CASE "SwXFootnote"
      getrangestring2 = getrangestring & "|" &    tc.parastylename
   end select

   'note for comments gettext is empty. The text is found from textfield.textrange.text
   'But may return void for the textfield and the viewcursor does not appear to give information to identify the
   'selected paragraph when void is not returned. So not been implemented
   'if isempty(vc.TEXTFIELD) =false then
   'getrangestring ="SwXTextViewCursor|"
   'getrangestring =getrangestring & vc.textfield.Author
   'tc=vc.textfield.textrange.text.createTextCursorByRange(vc.textfield.textrange) ' .ImplementationName 'SvxUnoTextBase
   'with vc.textfield.datetimevalue
   'tmp =cstr(.Year) & "," & cstr(.Month)  & "," & cstr(.Day) & "," & cstr(.Hours) & "," & cstr(.Minutes) &  "," & cstr(.Seconds) & "," & cstr(.HundredthSeconds) & "|"
   'end with

end function


Openoffice 4.1.2
Windows 8
JeJe
Volunteer
 
Posts: 789
Joined: Wed Mar 09, 2016 2:40 pm


Return to Code Snippets

Who is online

Users browsing this forum: No registered users and 1 guest