j.kornelsn wrote:By the way, an odd thing with the hack is that calling select() for multiple items loses the first item selected, which is the one where the view cursor ends up. To get around this, I searched for an extra item. So for example if I needed 5 selections, I actually did findAll() for 6 because then it would end up selecting 5 of them. This was not an impossible problem to work around, but still... I would prefer a better solution.
I realize this topic is from over four years ago, but I have repeatedly searched for the exact same solution to working with and manipulating a multiple selection. For years, this was the only post that really addressed using the TextRanges service for multiselection. (There is one more since July 2019.)
I, too, made do with the findAll method while seeking a better, more elegant process. I have ideas about avenues to try, but while doing so, encountered the same bug of losing the first selection. It seems the cursor behavior is counterintuitive. After searching forward with Find All in the UI, the cursor's direction is left, but when searching backward, the cursor's direction is right.
Realizing this strange pattern, I found a solution to re-selecting the original found and/or selected text ranges. It works after searching forward or backward. The following BASIC code is very basic, and should be easily modified as necessary.
Code: Select all
Dim Doc As Object ' I have other declarations. These are the relevant ones.
DocVw As Object, VwCursor As Object, StoreSel As Object, FoundAll As Object
' relevant snippets of code
Doc = ThisComponent
' variable definitions
' This is the text I want to manipulate.
Found = Doc.findAll(TxtSearch) ' TextRanges
DocVw = Doc.CurrentController ' TextView
' Note: Can't use a TextCursor for multiselections.
VwCursor = DocVw.ViewCursor ' TextViewCursor
' This is the current multiselection. It has no relevance to the procedure,
' but after the macro's execution, I want it restored to its current state.
' HERE'S THE TRICK.
' Correct the cursor/selection direction
' so it won't drop the first text range when recalled.
VwCursor.gotoRange(Doc.CurrentSelection(0).Start, True)
' Now save the current multiselection for recall.
StoreSel = DocVw.Selection ' TextRanges
' If needed, follow the same steps for the Found TextRanges. If you step through
' the macro and check the document here, the selection appears to have dropped
' the first text range. There is still a range, but it has collapsed to its end.
DocVw.select(Found)
' Repeat the trick. Now all the full ranges of Found are selected.
VwCursor.gotoRange(Found(0).Start, True) ' success
' Save the multiselection for recall, if needed.
' I renamed these TextRanges because I want to manipulate the Found TextRanges.
FoundAll = DocVw.Selection ' TextRanges
' Restore the selection to its initial state.
DocVw.select(StoreSel)
' The first range is collapsed, so repeat the trick.
VwCursor.gotoRange(StoreSel(0).Start, True) ' success
' multiple lines of irrelevant program code
' Either or both of the saved TextRanges can be recalled for manipulation.
DocVw.select(FoundAll)
VwCursor.gotoRange(FoundAll(0).Start, True) ' success
' For example, the entire FoundAll could be formatted here.
' Restore the initial selection.
DocVw.select(StoreSel)
' Repeat the trick.
VwCursor.gotoRange(StoreSel(0).Start, True) ' success
' final lines of code for error-handling and End macro