"Find All" occurrences of selected text or cell data via context menu?

I would like to be able to right click a cell containing data (or be able to select text manually) and click a context menu item that would then “Find All” occurrences of this text\data in the current document. I have checked the Tools:Customize:Context Menus screen but the various “Find” items don’t work this way and there is no way to send selected text (or cell data) to the “Find” field automatically.

Without this, if I want to highlight other occurrences of a bit of text I have to open find (Ctrl-F) and type each bit of data, or copy and paste the contents of a cell into the find field manually… and then use the mouse to click Find All (don’t believe there is a shortcut for Find All). If this process can be automated with one click in the context menu it will save several clicks, and a lot of cursor movement and typing.

If this functionality doesn’t already exist, is there a plugin that can do this?

I just played with recording a macro briefly by starting to record, pressing Ctrl-F, Ctrl-C, Ctrl-V, then clicking Find All. Surprisingly, the Find All part worked, but it doesn’t seem to record the actions of copying the selected data and then pasting it into the find box. It just searches for the exact data that was copied while recording. There is probably a way to make this work, but it may take me hours to decipher this since I have no experience with macros. It seems quite simple to set a macro as a context menu option at least.

Currently using LibreOffice 7.4 on Windows 10.

Thank you for any advice you can offer.

Something like this is a built-in feature in the Base component. You click any value in some column, then a toolbar button and the table is filtered by that value in the same column.

@KamilLanda @JohnSUN
Thank you so much guys! This is almost exactly what I need! KamilLanda, your solution works perfectly for selecting cells, and I also appreciate the additions JohnSUN added for searching selected text and not having an error pop up unnecessarily.

The ONLY issue I have found is that JohnSUN’s code does not work with merged cells. (EDIT: Fixed! See below!) I looked at the code and I just don’t know the language at all so I’m not sure how to fix it, but I would assume it has something to do with the way it avoids either the multiple cell error message or searching for empty cells. I’m sure it’s an easy fix.

If for some reason that isn’t possible to fix, then it would be fine to just go back to having an error pop up, but I would like to keep the text searching part.

There is, of course, also the possibility that I didn’t put the two bits of code together properly, so here is what I am using which is almost perfect but has trouble with merged cells:

Sub FindAll
	Dim oDoc As Object, oSheet As Object, oDesc As Object, s$, oFound As Object
	oDoc=ThisComponent
	If oDoc.getCurrentSelection().supportsService("com.sun.star.sheet.SheetCell") Then
		oSheet=oDoc.CurrentController.getActiveSheet
		uno("Copy") 'copy selection to system clipboard
		uno("Cancel") 'cancel edit mode if needed
		s=getTextFromClipboard 'get text from system clipboard
		If s <> "" Then ' We will not look for empty cells
			oDesc=oSheet.createSearchDescriptor 'search descriptor
			oDesc.setSearchString(s)
			oFound=oSheet.findAll(oDesc) 'Find All
			oDoc.CurrentController.Select(oFound) 'select found items
		EndIf 
	EndIf 
End Sub

Function getTextFromClipboard() as string 'get String from system clipboard
	dim oClip, oConv, oCont, oTyps, i%
	oClip=CreateUNOService("com.sun.star.datatransfer.clipboard.SystemClipboard")
	oConv=CreateUNOService("com.sun.star.script.Converter")
	oCont=oClip.getContents()
	oTyps=oCont.getTransferDataFlavors()
	On Error Resume Next 
	for i=lbound(oTyps) to ubound(oTyps)
		if oTyps(i).MimeType="text/plain;charset=utf-16" then
			getTextFromClipboard=oConv.convertToSimpleType(oCont.getTransferData(oTyps(i)), com.sun.star.uno.TypeClass.STRING)
			exit for
		end if
	next
	On Error GoTo 0
End Function

Sub uno(s$, optional oDoc as object) 'simple UNO command
	if isMissing(oDoc) then oDoc=thisComponent
	dim document, dispatcher
	s=".uno:" & s
	document=oDoc.CurrentController.Frame
	dispatcher=createUnoService("com.sun.star.frame.DispatchHelper")
	dispatcher.executeDispatch(document, s, "", 0, array())	
End Sub

(I’m not sure why the Sub uno section is mostly in bold when I paste it. It isn’t that way when I copy it?)
Thank you all for your time!:slight_smile:

EDIT: OH wow! I think I fixed it… I just changed:

"com.sun.star.sheet.SheetCell")

to

"com.sun.star.sheet.SheetCellRange")

And now it works on merged cells as well! :slight_smile:

Do you guys foresee any problems with this?

The only issues I have noticed are very minor. With any of these macros it will also select cells that contain the search terms and other characters… hard to explain. For example: search for “Bob”, highlights cells that contain “Bob” and cells that contain “Bobby”. This isn’t a huge problem for my specific use case right now, but it may be in other instances as I plan to use this for different types of sheets I work with.

Also, when I did the CellRange search it has slightly odd behavior in that if the cell I’m clicking on to initiate the search is the ONLY cell that contains that data, it will highlight half of the cell. This is very minor and doesn’t really affect anything. It just looks odd. Not a big deal. :slight_smile:

The code for whole words is easy, the same for case-sensitive finding → only next properties in object oDesc.

Sub FindAll
	dim oDoc as object,  oSheet as object,  oDesc as object,  s$,  oFound as object,  oSel as object
	oDoc=ThisComponent
	oSel=oDoc.CurrentSelection()
	if oSel.supportsService("com.sun.star.sheet.SheetCell") then
		oSheet=oDoc.CurrentController.getActiveSheet
		uno("Copy") 'copy selection to system clipboard
		uno("Cancel") 'cancel edit mode if needed
		s=getTextFromClipboard 'get text from system clipboard
		if s <> "" then ' We will not look for empty cells
			oDesc=oSheet.createSearchDescriptor 'search descriptor
			with oDesc
				.SearchString=s 'searched text
				.SearchWords=True 'only whole words
				.SearchCaseSensitive=True 'case sensitive
			end with
			oFound=oSheet.findAll(oDesc) 'Find All
			oDoc.CurrentController.Select(oFound) 'select found items
		end if
	else
		msgbox("This function cannot be used with multiple selection or no-cell selection :-)",  32)
	endif
End Sub

It seems there is bug in 7.5 and probably also in 7.4 because it supports com.sun.star.sheet.SheetCell also for the range. But it is fixed in version 7.6 (I tried some older 7.6. but you can test newest version Index of /daily/master/)




But I don’t know how to detect if only one merged cell is selected and take string from it, or if there is selection with merged cells and other cells.

1 Like

Last Edit: Welp… I’m sorry but the format of this site is so screwy I’m just going to mark this post as the solution because I had no other way to mark multiple posts\users as contributing to the solution, and it’s frankly a nightmare to try to discern the flow of this conversation due to the layout here. Thank you very much to everyone who gave of their time and used their knowledge to help out a stranger on the internet. Especially @KamilLanda and @JohnSUN. Your solution will save me a lot of time in the future. :slight_smile:

Great, thanks for the info! I just tried installing 7.6 dev alpha and it installs but gave no shortcuts and did not replace my old version, so I get the feeling it’s meant for people who want to tinker with things and are okay with there being quirks. I could make shortcuts myself but if there are other quirks due to it being an Alpha version I’d rather not deal with those, as the 7.4 version works fine for me. I’m not really a power user when it comes to spreadsheets and office suites (more of a hardware guy) so I think for the time being I’ll just stick with the current stable version and just keep my macro using SheetCellRange until the stable version includes that fix.
.
And thank you for the whole\partial search differentiation! I have made two macros now. One Partial and one Whole word search and I can use whichever is more convenient for what I’m working on. For “Cell” context I have both listed, for “Cell - Edit” I just have the partial one, since that is more appropriate for doing basic text searches. I also bound the partial search universally in LibreOffice to Alt-F which is going to be reallllly nice for some of the odd projects I end up working on involving huge documents, .ini files or config files for old software.
.
Here is the final code I’m using for Find All - Partial Word

Sub FindAllPartial
	Dim oDoc As Object, oSheet As Object, oDesc As Object, s$, oFound As Object
	oDoc=ThisComponent
	If oDoc.getCurrentSelection().supportsService("com.sun.star.sheet.SheetCellRange") Then
		oSheet=oDoc.CurrentController.getActiveSheet
		uno("Copy") 'copy selection to system clipboard
		uno("Cancel") 'cancel edit mode if needed
		s=getTextFromClipboard 'get text from system clipboard
		If s <> "" Then ' We will not look for empty cells
			oDesc=oSheet.createSearchDescriptor 'search descriptor
			oDesc.setSearchString(s)
			oFound=oSheet.findAll(oDesc) 'Find All
			oDoc.CurrentController.Select(oFound) 'select found items
		EndIf 
	EndIf 
End Sub

Function getTextFromClipboard() as string 'get String from system clipboard
	dim oClip, oConv, oCont, oTyps, i%
	oClip=CreateUNOService("com.sun.star.datatransfer.clipboard.SystemClipboard")
	oConv=CreateUNOService("com.sun.star.script.Converter")
	oCont=oClip.getContents()
	oTyps=oCont.getTransferDataFlavors()
	On Error Resume Next 
	for i=lbound(oTyps) to ubound(oTyps)
		if oTyps(i).MimeType="text/plain;charset=utf-16" then
			getTextFromClipboard=oConv.convertToSimpleType(oCont.getTransferData(oTyps(i)), com.sun.star.uno.TypeClass.STRING)
			exit for
		end if
	next
	On Error GoTo 0
End Function

Sub uno(s$, optional oDoc as object) 'simple UNO command
	if isMissing(oDoc) then oDoc=thisComponent
	dim document, dispatcher
	s=".uno:" & s
	document=oDoc.CurrentController.Frame
	dispatcher=createUnoService("com.sun.star.frame.DispatchHelper")
	dispatcher.executeDispatch(document, s, "", 0, array())	
End Sub

.
And for Find All - Whole Word
.

Sub FindAllWhole
	dim oDoc as object,  oSheet as object,  oDesc as object,  s$,  oFound as object,  oSel as object
	oDoc=ThisComponent
	oSel=oDoc.CurrentSelection()
	if oSel.supportsService("com.sun.star.sheet.SheetCellRange") then
		oSheet=oDoc.CurrentController.getActiveSheet
		uno("Copy") 'copy selection to system clipboard
		uno("Cancel") 'cancel edit mode if needed
		s=getTextFromClipboard 'get text from system clipboard
		if s <> "" then ' We will not look for empty cells
			oDesc=oSheet.createSearchDescriptor 'search descriptor
			with oDesc
				.SearchString=s 'searched text
				.SearchWords=True 'only whole words
				.SearchCaseSensitive=True 'case sensitive
			end with
			oFound=oSheet.findAll(oDesc) 'Find All
			oDoc.CurrentController.Select(oFound) 'select found items
		EndIf 
	EndIf 
End Sub

Function getTextFromClipboard() as string 'get String from system clipboard
	dim oClip, oConv, oCont, oTyps, i%
	oClip=CreateUNOService("com.sun.star.datatransfer.clipboard.SystemClipboard")
	oConv=CreateUNOService("com.sun.star.script.Converter")
	oCont=oClip.getContents()
	oTyps=oCont.getTransferDataFlavors()
	On Error Resume Next 
	for i=lbound(oTyps) to ubound(oTyps)
		if oTyps(i).MimeType="text/plain;charset=utf-16" then
			getTextFromClipboard=oConv.convertToSimpleType(oCont.getTransferData(oTyps(i)), com.sun.star.uno.TypeClass.STRING)
			exit for
		end if
	next
	On Error GoTo 0
End Function

Sub uno(s$, optional oDoc as object) 'simple UNO command
	if isMissing(oDoc) then oDoc=thisComponent
	dim document, dispatcher
	s=".uno:" & s
	document=oDoc.CurrentController.Frame
	dispatcher=createUnoService("com.sun.star.frame.DispatchHelper")
	dispatcher.executeDispatch(document, s, "", 0, array())	
End Sub

.
By the way, what’s with the message board here not allowing spaces between paragraphs in replies? It turns posts into a solid wall of text and really makes them hard to read. The original posts seem fine, it’s just the replies. I have resorted to putting periods between paragraphs so I can proof read my own posts without my eyes falling out. :slight_smile:
.
Also, it is incredibly hard to figure out the order of posts and replies. I have never seen a layout like this. I just had to click around for 3 minutes to find this post I made because the post order was seemingly random. I’ve been using and moderating message boards for over 23 years (40k+ posts) and I can’t understand the layout of this place. lol Is there some way to have the messages show in a standard flat\chronological order, with a way to tell who is replying to who?
.
I would like to mark the solutions, but I feel there were multiple contributions and my end solution is a combination of them… so. Do I mark my own as the solution? That seems wrong since you guys did the work.

This forum isn’t classical discuss forum, but it has a system for Answers (with a possibility to add comments under Answer). The Answers aren’t sorted chronologically, because there is the possibility to upvote ones → so it means the most upvoted Answer is on the top. But the true is, the upvoting is rarely use here. I think the primal idea was to get well arranged system with clear Answers without many useless text like in classical forums, and I think the partially it is functional. Of course it isn’t 100% perfect, but I think it is good step forward :slight_smile:
⁠⁠
The space between paragraphs is problem in comments, and I don’t know why the system not allowed it. I know two ways:

  1. put Html tag <br> for empty line.
  2. put Unicode character U+2060 (it is character Word Joiner) for empty line.

You marked the solution that is functional for you and it is right :-). If somebody want to search the details, he can read whole Ask :-).

I think the easier way is to define the keyboard shortcut for macro FindAll than set two Context menus - for Cell and for Edit Cell.
Macro will do Ctrl+C and then it will get the String from system clipboard. And this String it will use for finding.

Sub FindAll
	dim oDoc as object, oSheet as object, oDesc as object, s$, oFound as object
	oDoc=ThisComponent
	oSheet=oDoc.CurrentController.getActiveSheet
	uno("Copy", oDoc) 'copy selection to system clipboard
	s=getTextFromClipboard 'get text from system clipboard
	oDesc=oSheet.createSearchDescriptor 'search descriptor
	with oDesc
		.SearchString=s
	end with
	oFound=oSheet.findAll(oDesc) 'Find All
	oDoc.CurrentController.Select(oFound) 'select found items
End Sub

Function getTextFromClipboard() as string 'get String from system clipboard
	dim oClip, oConv, oCont, oTyps, i%
	oClip=CreateUNOService("com.sun.star.datatransfer.clipboard.SystemClipboard")
	oConv=CreateUNOService("com.sun.star.script.Converter")
	oCont=oClip.getContents()
	oTyps=oCont.getTransferDataFlavors()
	for i=lbound(oTyps) to ubound(oTyps)
		if oTyps(i).MimeType="text/plain;charset=utf-16" then
			getTextFromClipboard=oConv.convertToSimpleType(oCont.getTransferData(oTyps(i)), com.sun.star.uno.TypeClass.STRING)
			exit for
		end if
	next
End Function

Sub uno(s$, optional oDoc as object) 'simple UNO command
	if isMissing(oDoc) then oDoc=thisComponent
	dim document, dispatcher
	s=".uno:" & s
	document=oDoc.CurrentController.Frame
	dispatcher=createUnoService("com.sun.star.frame.DispatchHelper")
	dispatcher.executeDispatch(document, s, "", 0, array())	
End Sub
1 Like

@KamilLanda Okay, why not take it one step further:

	If ThisComponent.getCurrentSelection().supportsService("com.sun.star.sheet.SheetCell") Then

and further down the line…

1 Like

What I think a good approximation, only using the mouse.

Menu/Tools/Customize/Context Menus

To use:
Select the text to search.
Right-click, select ‘Find and Replace’
Click on 'Find ‘All’

1 Like

@JohnSUN, the author wrote:

and I supposed the phrase: (or be able to select text manually) means: select the text inside a cell.

And because I didn’t recall how to get selected text from the inside of cell and I didn’t want to search it or discover via Xray/Mri, I wrote the “universal solution” via system clipboard, because I recalled quickly where this part of code is in my libraries :slight_smile: .

1 Like

No, no, my friend, I’ve been misunderstood: I’m not criticizing a great solution - I’m trying to help improve it. The check that I suggested to insert into the code, just to help avoid the error message in the case when more than one cell is selected when running the macro.

image

1 Like

@JohnSUN: I didn’t read your note like criticism, really no :slight_smile:. I read it like normal question for possible improvement. And I wanted only to write my reasons for that solution :slight_smile:.
Of course it isn’t problem to add the condition if only one cell is selected, and you are right it could be better. But still I’m not sure if there is needful the detection of selected text inside the cell. So I hope the author will write his feedback.

1 Like

I added a little to your code: I refused to search for empty cells even if the macro was called for an empty cell or from edit mode but without selecting a part of the string. To do this, I had to enclose a type iteration loop in an error handler and add a search string check. In addition, I added an exit from the edit mode before starting the search.

Sub FindAll
	Dim oDoc As Object, oSheet As Object, oDesc As Object, s$, oFound As Object
	oDoc=ThisComponent
	If oDoc.getCurrentSelection().supportsService("com.sun.star.sheet.SheetCell") Then
		oSheet=oDoc.CurrentController.getActiveSheet
		uno("Copy") 'copy selection to system clipboard
		uno("Cancel") 'cancel edit mode if needed
		s=getTextFromClipboard 'get text from system clipboard
		If s <> "" Then ' We will not look for empty cells
			oDesc=oSheet.createSearchDescriptor 'search descriptor
			oDesc.setSearchString(s)
			oFound=oSheet.findAll(oDesc) 'Find All
			oDoc.CurrentController.Select(oFound) 'select found items
		EndIf 
	EndIf 
End Sub

Function getTextFromClipboard() as string 'get String from system clipboard
	dim oClip, oConv, oCont, oTyps, i%
	oClip=CreateUNOService("com.sun.star.datatransfer.clipboard.SystemClipboard")
	oConv=CreateUNOService("com.sun.star.script.Converter")
	oCont=oClip.getContents()
	oTyps=oCont.getTransferDataFlavors()
	On Error Resume Next 
	for i=lbound(oTyps) to ubound(oTyps)
		if oTyps(i).MimeType="text/plain;charset=utf-16" then
			getTextFromClipboard=oConv.convertToSimpleType(oCont.getTransferData(oTyps(i)), com.sun.star.uno.TypeClass.STRING)
			exit for
		end if
	next
	On Error GoTo 0
End Function

(Sub uno did not change)
BothWorkFine

1 Like

I think there is missing only one thing in the code :slight_smile:

If oDoc.getCurrentSelection().supportsService("com.sun.star.sheet.SheetCell") Then
'...
Else
	MsgBox("This function cannot be used with multiple selections or no-cell selection :-)", 32)
End If
2 Likes

If you add the macro to the sheet cell’s context menu, you can omit that test. The command will not appear in a range’s context menu,