With LibreOffice Writer, I would like to confine my text search within a page only, not the whole document. Is there any way to do so?
Mark the text on the page and only search in selection.
My search is to be performed inside a macro. Can I select 1 page only using macro?
Sub select1page
dim oDoc as object, oVCur as object
oDoc=ThisComponent
oVCur=oDoc.CurrentController.ViewCursor 'visible cursor
oVCur.goToStart(false)
oVCur.jumpToEndOfPage(true)
oVCur.goToStart(true) 'select 1st page
End Sub
Searching in the range is in chaper 14.7.1. Searching selected text or a specified range in A. Pitonyak macro book (see documentation Macro Guides | LibreOffice Documentation - LibreOffice User Guides)
I have the search after the 1-page selection. But, the search result still covers all pages. Any suggection for me? Thank you.
Well, since you still haven’t shown us the code that doesn’t work correctly, we should assume that for some reason (shy about the quality of the code, working on a commercial project, etc.) you won’t do it in the future.
In this case, the only suggestion is: sit a rubber duck (or cat) next to you and tell it line by line of your code, what this line does and what result it achieves.
I need to identify the text between two boundary strings. All texts being identified have different contents. And within each page, only the last text being identified will be used for further processing. Here is my code below . As I am new to LibreOffice macro, please kindly give me advice. Thanks.
Sub Main
dim oDoc as object, oVCur as object
oDoc=ThisComponent
oVCur=oDoc.CurrentController.ViewCursor
oVCur.goToStart(false)
oVCur.jumpToEndOfPage(true)
oVCur.goToStart(true)
Dim oSearchZone As Object
Dim oFoundZone As Object
Dim oFoundAfterZone As Object
Dim oCursVisible As Object
oDoc = ThisComponent
oSearchZone = oDoc.createSearchDescriptor()
With oSearchZone
.SearchString = Chr(34)&Chr(35)'search for "#
End With
oFoundZone = oDoc.findFirst(oSearchZone)
If (IsNull(oFoundZone)) Then
MsgBox "start tag was NOT found", MB_ICONINFORMATION, "Text search"
End If
'If Not(IsNull(oFoundZone)) Then
Do Until IsNull(oFoundZone)
With oSearchZone
.SearchString = Chr(32)'search for space
End With
oFoundAfterZone = oDoc.findNext(oFoundZone.End, oSearchZone)
If Not(IsNull(oFoundAfterZone)) Then
oCursVisible = oDoc.currentcontroller.viewCursor
With oCursVisible ' com.sun.star.text.text.XTextViewCursor
.gotoRange(oFoundZone.End, false)
.gotoRange(oFoundAfterZone.Start, True)
MsgBox .String, MB_ICONINFORMATION, "Text in between"
End With
'start next search
With oSearchZone
.SearchString = Chr(34)&Chr(35)'search for "#
End With
oFoundZone = oDoc.findNext(oFoundZone, oSearchZone)
Else
MsgBox "end tag was NOT found", MB_ICONINFORMATION, "Text search"
oFoundZone = NOTHING
End If
Loop
end sub
Thanks for the code, it’s already readable and parsable. Can you also show a test sample of the text on which this code should work?
PS. It’s not entirely clear from the code. The opening tag "# is understandable. And what is the closing tag? The same "#? In other words, for "#aaa bbb"#
are you looking for aaa bbb?
The test sample of text is as below: (opening tag is "# and closing tag is a space).
On page1:
123
“”"""#bb
abc
456
“”"""#bc
def
On page2:
789
“”"""#bd
ghi
The expected result is to get “bc” on page 1 and get “bd” on page 2.
I think I have the search range incorrect.
I mean an empty space. Thanks.
Let’s try to reformulate the task - not “search for the first occurrence on the next page”, but “find all occurrences and report each first on the next page” (poorly worded, hard to read and understand, maybe it will become clearer in the code):
Sub EnumerateEachTag
Const SEARCH_TAG = """#"
Dim oDoc As Variant, oSearchDescriptor As Variant
Dim sFoundString As String, sMsgString As String
Dim oFound As Variant, oViewCursor As Variant
Dim nPage As Integer, nPageFound As Integer
oDoc = ThisComponent
oViewCursor = ThisComponent.getCurrentController().getViewCursor()
oSearchDescriptor = oDoc.createSearchDescriptor()
oSearchDescriptor.SearchRegularExpression = True
oSearchDescriptor.setSearchString(SEARCH_TAG & "([^\W])+")
nPage = 0
oFound = oDoc.findFirst(oSearchDescriptor)
Do While Not IsNull(oFound)
oViewCursor.gotoRange(oFound, False)
nPageFound = oViewCursor.getPage()
If nPageFound <> nPage Then
sFoundString = oFound.getString()
sMsgString = "'" & Right(sFoundString, Len(sFoundString)-Len(SEARCH_TAG)) & "'"
MsgBox(sMsgString, MB_ICONINFORMATION, "Found on Page #" & nPageFound)
nPage = nPageFound
Rem Skip all others oFound on this page
EndIf
oFound = oDoc.findNext(oFound, oSearchDescriptor)
Loop
End Sub
The macro jumps with visible cursor to the end of each page and finds the previous occurence by backward searching. If something is founded, then macro will add the founded range to the array.
There is how to select founded values one by one, or how to replace founded value.
Sub selectLastFoundedValueInPage
dim oDoc as object, oVCur as object, iPage&, oStat(), i&, oDesc as object, j&, oFound as object, s$
oDoc=ThisComponent
oVCur=oDoc.CurrentController.ViewCursor 'visible cursor
rem get count of pages in document
oStat=oDoc.DocumentProperties.DocumentStatistics
for i=lbound(oStat) to ubound(oStat)
if oStat(i).Name="PageCount" then 'value from array of document statistics is PageCount
iPage=oStat(i).Value 'count of pages
exit for
end if
next i
dim p(iPage-1) 'array for founded values
oDesc=oDoc.createSearchDescriptor 'search descriptor
with oDesc
.SearchBackwards=true 'search backwards
.SearchRegularExpression=true
.SearchString="""#.+? "
end with
for i=1 to iPage 'traverse page by page
oVCur.jumpToPage(i) 'visible cursor to start of page
oVCur.jumpToEndOfPage() 'visible cursor to end of page
oFound=oDoc.findNext(oVCur.End, oDesc) 'find previous occurence of value from end of page
if NOT isNull(oFound) then 'something is founded
oVCur.goToRange(oFound.End, false) 'set visible cursor to end of founded value
if oVCur.Page=i then 'visible cursor is in same page like before finding
p(j)=oFound 'add founded value to output array
s=oFound.string 'string from founded value
s=mid(s, 3, len(s)-2) 'text from founded value without "# & finalSpace ('"#bc ' -> 'bc')
'msgbox s
rem you can replace founded string like:
'oFound.String="NEW" & s
j=j+1 'index of output array
end if
end if
next i
if j>0 then redim preserve p(j-1) 'proper size of output array
rem for example select founded values step by step
if NOT isEmpty(p(0)) then 'there is some founded value
for i=lbound(p) to ubound(p)
oDoc.CurrentController.Select(p(i))
msgbox "Value No. " & i+1
next i
end if
End Sub
Thank you @JohnSUN for the coding. It helps me to find the first occurrence within a page. But, I would prefer the last, not the first. It should be my previous typing mistake that confused you. Anyway, thank you for your advice. Thanks.
Thank you @KamilLanda for the coding. It helps me to find the last occurrence within a page. Thanks. And, I will study the macro book that suggested.