Confine the search range in LibreOffice Writer

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.

1 Like

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.