Page 1 of 1

[Solved] Search and Select Character Style

Posted: Sun Jul 14, 2019 1:04 pm
by bassklampfe
I want to write a macro to select a specific text with a specific style.
Now my problem is in search description I can set SearchStyles to True, then a style is searched. Or i can set it to False, then a text is searched, so search for style AND text is not possible
My Idea was to search for text and then sort out all but the correct style:

Code: Select all

	oDoc = ThisComponent
	' Prepare the Search-Descriptor
	oSearchDesc = oDoc.createsearchDescriptor()
	oSearchDesc.SearchRegularExpression = True
	oSearchDesc.SearchWords = True
	oSearchDesc.SearchCaseSensitive = True
	oSearchDesc.SearchString  = "[ABCDEFGH][♯♭b#]"
	oFoundall = oDoc.FindAll(oSearchDesc)

	' drop wrong style
	i = 0
	Do While i < oFoundall.Count
		oFound = oFoundall(i)
		If oFound.CharStyleName = "Placeholder" then
			i=i+1
		Else
			oFoundall.Remove(i)
		End If
	Loop

	' highlight match
	oDoc.getCurrentController().Select(oFoundall)
But oFoundall.Remove(i) throws an error,it seems that oFoundall is no collection. What is the right instruction remove one item from oFoundall?

Thanks and Regards

Re: Search for text AND style

Posted: Sun Jul 14, 2019 1:21 pm
by Villeroy
Do it like you would do in the user interface. Search for one thing and then for the other thing within the first result.
menu:find>replace...
Search for whatever and hit [Find All]. Now you have a selection of all matching snippets. Now search within the current selection for something else.

Keep variable oFoundall, prepare another searchdescriptor and then call oFoundall.FindAll(new_descr)

Re: Search for text AND style

Posted: Sun Jul 14, 2019 1:42 pm
by bassklampfe
Well, I didn't mention, but the Style im searching, is a Character Style, not a Paragraph Style. Sorry.
If didn't make FindAll to find a Character Style at all, maybe then I would find another solution based on this....

Re: Search for text AND style

Posted: Sun Jul 14, 2019 2:26 pm
by Villeroy
Each found snippet can include sections with more than one character style. You have to loop through the search results and through the uniquely formatted snippets of each result. I am not familiar with the Writer API but it may be possible to use something like

Code: Select all

e = oFound.createEnumeration()
while e.hasMoreElements()
  snip = e.nextElement()
  if snip.CharacterStyleName = someCharStyle then ...
wend

Re: Search for text AND style

Posted: Sun Jul 14, 2019 2:39 pm
by Zizi64
Fixed version:
Search style.odt
(14.89 KiB) Downloaded 244 times

Re: Search for text AND style

Posted: Sun Jul 14, 2019 2:46 pm
by JeJe
You can easily create an array with the ranges wanted,

Code: Select all


dim ofoundnew() 

for i = 0 to oFoundall.Count -1
If oFoundall(i).CharStyleName = "Placeholder" then
redim preserve ofoundnew(c)
ofoundnew(c) = oFoundall(i)
c=c+1
End If
next
   



Re: Search for text AND style

Posted: Sun Jul 14, 2019 3:23 pm
by bassklampfe
Zizi64 wrote:
Search style.odt
For the first: I'd never execute Macros from downloaded files.
So, I renamed it to .ZIP, extracted and examined the content.
You code

Code: Select all

  '  drop wrong style
   i = 0
   Print oFoundall.Count
   Do While i < oFoundall.Count
      oFound = oFoundall.getByIndex(i)
      If oFound.CharStyleName = "Placeholder" then         
         Print "The character ' " & oFound.getString & "'  has character style ' Placeholder' . It will not be removed"
      Else
         The Print "The character ' " & oFound.getString & "'  will be removed"   
         oFound.setString("")
      End If
      i=i+1
   Loop
Has one big issue: oFound.setString("") destroys the document content. I want to modify the found content lateron, but keep all other text.

But anyway, thanks for the try.

Re: Search for text AND style

Posted: Sun Jul 14, 2019 3:28 pm
by bassklampfe
JeJe wrote:You can easily create an array with the ranges wanted,
Thank you for your code. I already tried something similar, but

Code: Select all

	' highlight match
	oDoc.getCurrentController().Select(ofoundnew)
Does not work then

Re: Search for text AND style

Posted: Sun Jul 14, 2019 3:46 pm
by Villeroy
Because ofoundnew is a StarBasic type of array. It may be possible to create a new instance of an UNO object (c.s.s.text.TextRanges?) and append snippets to it.
The Calc component can produce an UNO collection of multiple ranges from scratch:

Code: Select all

oBasket = createUnoService("com.sun.star.sheet.SheetCellRanges")
for each range in someRanges()
  oBasket.addRangeAddress(range.getRangeAddress())
next
oController.select(oBasket)

Re: Search for text AND style

Posted: Sun Jul 14, 2019 4:21 pm
by JeJe
If there's an attribute like overlining that you don't use in your document, mark the found result with that and do another find for it:

Code: Select all

for i = 0 to oFoundall.Count -1
If oFoundall(i).CharStyleName = "Placeholder" then
oFoundall(i).charoverline = 2
end if
next


Dim sAttributes(0) As New com.sun.star.beans.PropertyValue

SAttributes(0).Name = "CharOverline"
SAttributes(0).Value =2

oSearchDesc.SetSearchAttributes(SAttributes()) 
oSearchDesc.SearchString  =""
oFoundall = oDoc.FindAll(oSearchDesc)

oDoc.getCurrentController().Select(oFoundall) 
for i = 0 to oFoundall.Count -1
oFoundall(i).charoverline = 0
next
  
(its clunky but...)

Re: Search for text AND style

Posted: Sun Jul 14, 2019 4:23 pm
by Zizi64
For the first: I'd never execute Macros from downloaded files.
So, I renamed it to .ZIP, extracted and examined the content.
Set the macro security to medium, and just open the file without enabling the macros. Then you can check the macro code with the built-in IDE.

Has one big issue: oFound.setString("") destroys the document content. I want to modify the found content lateron, but keep all other text.
A part of your code:
oFoundall.Remove(i)
Do you want to remove the searched characters, those have not the character style "Placeholder", does not?

Re: Search for text AND style

Posted: Sun Jul 14, 2019 9:34 pm
by Zizi64
There is a bug in my code:

Code: Select all

The Print "The character ' " & oFound.getString & "'  will be removed"
Use this:

Code: Select all

Print "The character ' " & oFound.getString & "'  will be removed"

And install and use an object inspesction tool like the Xray.

Re: Search for text AND style

Posted: Sun Jul 14, 2019 9:37 pm
by Zizi64
oFound.setString("") destroys the document content.
The oFound.setString("") will remove one character only. Tested in my LibreOffice 6.1.6

Re: Search for text AND style

Posted: Mon Jul 15, 2019 6:57 am
by bassklampfe
Zizi64 wrote:
A part of your code:
oFoundall.Remove(i)
Do you want to remove the searched characters, those have not the character style "Placeholder", does not?
This shall not remove the found text from the document, but the found item from the list of found items. But it seems, the list of found Items cannot be manipulated or reconstructed.

Just to give you an idea, the whole workflow of the script shall be as follows:
  • build a list (with FindAll or on an other way) of items matching specific criteria
  • Highlight all matching items using select()
  • Show a dialog to ask the user, what to do with the selected items
  • Depending on the choice in the dialog do different things with the selected items
I'm busy this week, I will come back when I make progress

Thanks for you help anyway

Re: Search for text AND style

Posted: Thu Jul 18, 2019 9:41 am
by bassklampfe
I'm back again :-)
I developed some strategies, but im still struggling with the methods available.
oFoundall is of type com.sun.star.text.TextRanges. But I don't manage to create an empty, new TextRanges object.
My attempt was

Code: Select all

Dim foundChords As New com.sun.star.text.TextRanges
but this gives only error.

Second strategy was to manipulate oFoundall. From my understanding this is documented in https://www.openoffice.org/api/docs/com ... anges.html
I would like to use the methods removeByIndex and insertByIndex from https://www.openoffice.org/api/docs/com ... ainer.html, but I find no way to do it.

Re: Search for text AND style

Posted: Thu Jul 18, 2019 10:18 am
by JeJe
To slightly extend my solution, you'd make note of the existing attribute/attributes (overlining if that is chosen) for each item and reaply them at the end. You just need a unique attribute or combination of attributes that you won't find in your document.

An alternative would be instead of selecting the ranges, to just mark them in some other obvious way - such as underlining (as the spellchecker does), overlining, or background color.

Re: Search for text AND style

Posted: Thu Jul 18, 2019 12:55 pm
by musikai
The Extension "Alt-Search and Replace" can find and select the combination by entering this regular Expresssion:

Code: Select all

[:::CharStyleName=Placeholder::][ABCDEFGH]

As with all macro code searches, the first found item always gets deselected here in LO4.4.7.2

But you can try your luck and perhaps find sth useful in the code of Alt-Search&Replace.

Re: Search for text AND style

Posted: Thu Jul 18, 2019 1:27 pm
by bassklampfe
Just to inform you, I now do an attribute search (CharColor is the unique Style of the CharacterStyle in question) and get exactly what I need.
This is the starting of my code:

Code: Select all

Sub SelectPlaceholder

	'
	' set global vars
	'
	Dim oDoc As Object
	oDoc = ThisComponent
	
	'
	' find the character style Placeholder
	'
	Dim oStyleFamilies,oCharStyles,oCharStylePlaceholder as object
	oStyleFamilies = oDoc.getStyleFamilies()
	oCharStyles = oStyleFamilies.getByName("CharacterStyles")
	oCharStylePlaceholder=oCharStyles.getByName("Placeholder")

	'
	' build the seach
	'	
	Dim oSearchDesc As Object
	Dim srchAttributes(0) As New com.sun.star.beans.PropertyValue
	oSearchDesc = oDoc.createsearchDescriptor()
	srchAttributes(0).Name = "CharColor"
	srchAttributes(0).Value = oCharStylePlaceholder.CharColor
	oSearchDesc.SearchStyles = True
	oSearchDesc.SetSearchAttributes(srchAttributes)

	'
	' do the search
	'
	Dim oFoundall As Object
	oFoundall = oDoc.FindAll(oSearchDesc)
   
	'
	' highlight match
	'
	oDoc.getCurrentController().Select(oFoundall)

	'
	' do further processing
	'
	....

end sub
The only issue left is, the FIRST element found is NOT highlighted by oDoc.getCurrentController().Select(oFoundall) this seems to be a bug in OO?
Any solution/workaround for this?

Thanks all for your suggestions.

Re: Search for text AND style

Posted: Fri Jul 19, 2019 11:43 am
by musikai
bassklampfe wrote:
The only issue left is, the FIRST element found is NOT highlighted by oDoc.getCurrentController().Select(oFoundall) this seems to be a bug in OO?
Any solution/workaround for this?
Seems to be a bug in all versions of OO and LO I could test.

As the cursor always collapses to the end of the first item (if the Foundall has more than 1 item) we could move the Viewcursor to the left by the length of the first item:

Code: Select all

    oVC = oDoc.CurrentController.getViewCursor
    if oFoundall.count>1 then oVC.goleft(len(oFoundall(0).string),true)

Re: Search for text AND style

Posted: Fri Jul 19, 2019 7:46 pm
by bassklampfe
musikai wrote:

Code: Select all

    oVC = oDoc.CurrentController.getViewCursor
    if oFoundall.count>1 then oVC.goleft(len(oFoundall(0).string),true)
Yeah man! Thank you,now everything is fine
Regards to all the people getting me on the right way

Re: [Solved] Search and Select Character Style

Posted: Sat Jul 20, 2019 9:02 am
by bassklampfe
I rename the title from "Search for text AND style" to "Search and Select Character Style" to make it more accessible by search topic