Writer macro to search for attributes and apply styles

Creating a macro - Writing a Script - Using the API (OpenOffice Basic, Python, BeanShell, JavaScript)
Post Reply
tomarnold
Posts: 3
Joined: Tue Feb 19, 2008 6:58 pm

Writer macro to search for attributes and apply styles

Post by tomarnold »

I am trying to apply styles to documents that were created with manually applied attributes. The author was consistent in use of attributes. Therefore I'd like to change everything that is formatted like this

HERE IS A HEADING:

To a level 2 heading.

I started out by trying to record a macro. I have one that searches for the right text with attributes and then applies the "Header 2" style. But I don't know the proper way to make this loop through the document. I expect this is very simple but I've never done any coding in OO nor do I know any of the macro languages in OO (If it matters, I'm actually using StartSuite 8 on Windows xp)

Basically I want:
  • LOOP
    search for desired attribute
    if not found, break out of loop
    else apply format
    END of LOOP
Here's what I have from recording a macro so far:

Code: Select all

sub ApplyLevel2Head
rem ----------------------------------------------------------------------
rem define variables
dim document   as object
dim dispatcher as object
rem ----------------------------------------------------------------------
rem get access to the document
document   = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")

rem ----------------------------------------------------------------------
dim args1(18) as new com.sun.star.beans.PropertyValue
args1(0).Name = "SearchItem.StyleFamily"
args1(0).Value = 2
args1(1).Name = "SearchItem.CellType"
args1(1).Value = 0
args1(2).Name = "SearchItem.RowDirection"
args1(2).Value = true
args1(3).Name = "SearchItem.AllTables"
args1(3).Value = false
args1(4).Name = "SearchItem.Backward"
args1(4).Value = false
args1(5).Name = "SearchItem.Pattern"
args1(5).Value = false
args1(6).Name = "SearchItem.Content"
args1(6).Value = false
args1(7).Name = "SearchItem.AsianOptions"
args1(7).Value = false
args1(8).Name = "SearchItem.AlgorithmType"
args1(8).Value = 0
args1(9).Name = "SearchItem.SearchFlags"
args1(9).Value = 65536
args1(10).Name = "SearchItem.SearchString"
args1(10).Value = ":"
args1(11).Name = "SearchItem.ReplaceString"
args1(11).Value = ""
args1(12).Name = "SearchItem.Locale"
args1(12).Value = 255
args1(13).Name = "SearchItem.ChangedChars"
args1(13).Value = 2
args1(14).Name = "SearchItem.DeletedChars"
args1(14).Value = 2
args1(15).Name = "SearchItem.InsertedChars"
args1(15).Value = 2
args1(16).Name = "SearchItem.TransliterateFlags"
args1(16).Value = 1280
args1(17).Name = "SearchItem.Command"
args1(17).Value = 0
args1(18).Name = "Quiet"
args1(18).Value = true

dispatcher.executeDispatch(document, ".uno:ExecuteSearch", "", 0, args1())

rem ----------------------------------------------------------------------
dim args2(1) as new com.sun.star.beans.PropertyValue
args2(0).Name = "Template"
args2(0).Value = "Heading 2"
args2(1).Name = "Family"
args2(1).Value = 2

dispatcher.executeDispatch(document, ".uno:StyleApply", "", 0, args2())

rem ----------------------------------------------------------------------

end sub
So how do I put it in a loop?

[Note: if I get this far, I also would like to create a loop to search for all blank paragraphs - which where used to provide vertical spacing - and delete them. I think if I get the basic iteration down I can generalize to different search and replace options as well as applying styles.]

I'm sure this pretty trivial but I couldn't find anything that explained it here, and I would greatly appreciate some enlightenment.
Thanks!
TerryE
Volunteer
Posts: 1402
Joined: Sat Oct 06, 2007 10:13 pm
Location: UK

Re: Writer macro to search for attributes and apply styles

Post by TerryE »

I've just tidied up your post for the benefit of our poor readers. Unfortunately OOoBasic is different to VBA in that there are two macro programming models: one which uses the UNO API and one which uses the recorder. You've posted a macro using the lattter. Type of macro is fine for automating a simple sequence of actions but just isn't up to what you want to do. So the answer isn't that simple. So before we start going into detail you need to be willing to get to grips with proper Basic . UNO API programming. Are you up for this?
Ubuntu 11.04-x64 + LibreOffice 3 and MS free except the boss's Notebook which runs XP + OOo 3.3.
tomarnold
Posts: 3
Joined: Tue Feb 19, 2008 6:58 pm

Re: Writer macro to search for attributes and apply styles

Post by tomarnold »

I'll take a stab at it. If I can find some examples I should be ok. I've done a lot of coding over the years but not in the "right" languages for this - C, C++, assembler, PHP. And I've muddled though visual basic for MS Office macros. What do I need to do?
TerryE
Volunteer
Posts: 1402
Joined: Sat Oct 06, 2007 10:13 pm
Location: UK

Re: Writer macro to search for attributes and apply styles

Post by TerryE »

Good. I'll give a more detailed post tomorrow if one of the other guys doesn't beat me to it. If you've done VBA and some real languages then you shouldn't have too much trouble converting. The object model for the UNO API is just different to that of the Word COM API — more DOM-like. Talk later.
Ubuntu 11.04-x64 + LibreOffice 3 and MS free except the boss's Notebook which runs XP + OOo 3.3.
pitonyak
Volunteer
Posts: 186
Joined: Sun Oct 07, 2007 9:13 pm
Location: Columbus, Ohio, USA

Re: Writer macro to search for attributes and apply styles

Post by pitonyak »

My primary concern with the macro as presented is that it always assumes success. You want to find something and then if, and only if, you find a match, apply the styles. You probably want to do this until you no longer find a match. Clearly you understand this (from your post).

I do not have a lot of time, and it looks like you are able to figure out many things after someone points you in the right direction. So... First, consider this code snippet:

Code: Select all

REM Find the first cell that contains sString$
REM If bWholeWord is True, then the cell must contain ONLY the text
REM as indicated. If bWholeWord is False, then the cell must only contain
REM the requested string.
Function SimpleSheetSearch(sString$, oSheet, bWholeWord As Boolean) As Variant
  Dim oDescriptor
  Dim oFound
  REM Create a descriptor from a searchable document.
  oDescriptor = oSheet.createSearchDescriptor()
  REM Set the text for which to search and other 
  REM http://api.openoffice.org/docs/common/ref/com/sun/star/util/SearchDescriptor.html 
  With oDescriptor
    .SearchString = sString$
    REM These all default to false
    REM SearchWords forces the entire cell to contain only the search string
    .SearchWords = bWholeWord
    .SearchCaseSensitive = False
  End With
  REM Find the first one
  oFound = oSheet.findFirst(oDescriptor)
  SimpleSheetSearch = oFound
  
  REM Do you really want to find more instances
  REM You can continue the search using a cell if you want!
  'Do While Not IsNull(oFound)
  '  Print oFound.getString()
  '  oFound = oSheet.findNext( oFound, oDescriptor)
  'Loop
End Function
Notice that this uses a sheet to perform the search. You can obtain a sheet based on the sheet name or index. Also, you can obtain the active sheet from the document's controller.

Code: Select all

oSheet = ThisComponent.getSheets().getByIndex(0)
oSheet = ThisComponent.getSheets().getByName("Sheet1")
oSheet = ThisComponent.CurrentController.ActiveSheet
Now, in the searching code, notice that it creates a search descriptor. The following link shows the properties of the descriptor

http://api.openoffice.org/docs/common/r ... iptor.html

The provided macro searches for a word. You want to set the SearchStyles property to True, which should cause it to search for the style.

Hmmm, why am I thinking that you are searching a Calc document. Oh yes, because the properties are talking about CellType and RowDirection. Then, you set the style to Heading2. OK, so this is really a Writer document... Is this correct?

Take a look at my free macro document in section titled "Search and Replace with Attributes and Regular Expressions".

Notice that the found item is also a cursor, and the cursor should support a ParaStyleName property that you can set directly.
Andrew Pitonyak
http://www.pitonyak.org/oo.php
LO and AOO on Fedora
TerryE
Volunteer
Posts: 1402
Joined: Sat Oct 06, 2007 10:13 pm
Location: UK

Re: Writer macro to search for attributes and apply styles

Post by TerryE »

OOoBasic offers various syntactic sugar to make the calls more "VBA like". These improve the readability without a runtime performance hit, so the equivalent to Andrews first two examples are:

Code: Select all

oSheet = ThisComponent.Sheets(0)
oSheet = ThisComponent.Sheets.Sheet1
Also as Andrew says his macros give some excellent examples (google "pitonyak macro"). Also read the Text Document section of the SDK developers guide.
Ubuntu 11.04-x64 + LibreOffice 3 and MS free except the boss's Notebook which runs XP + OOo 3.3.
pitonyak
Volunteer
Posts: 186
Joined: Sun Oct 07, 2007 9:13 pm
Location: Columbus, Ohio, USA

Re: Writer macro to search for attributes and apply styles

Post by pitonyak »

I had no idea that you could do this

Code: Select all

oSheet = ThisComponent.Sheets.Sheet1
Basic is much easier to use than the other methods for scripting OOo.
Andrew Pitonyak
http://www.pitonyak.org/oo.php
LO and AOO on Fedora
TerryE
Volunteer
Posts: 1402
Joined: Sat Oct 06, 2007 10:13 pm
Location: UK

Re: Writer macro to search for attributes and apply styles

Post by TerryE »

Yup it is buried in the bowels of the SDK, hidden in section 3.4.2 C++ Language Binding (even though its got nothing to do with C++!). I only came across it because I took the RTL apart. I'll expand on this as a separate tutorial. Look out for the post.
Ubuntu 11.04-x64 + LibreOffice 3 and MS free except the boss's Notebook which runs XP + OOo 3.3.
tomarnold
Posts: 3
Joined: Tue Feb 19, 2008 6:58 pm

Re: Writer macro to search for attributes and apply styles

Post by tomarnold »

O.k., I'm going to have to sit on this one for a little bit until I get a few hours clear to play around with it. The examples look good and I'm sure I'll make some progress. I'll report back when I do. In the meantime I've just had more work crop up that will require me to set this aside for a day or three.

Thank you for the pointers. I will report my results.
Post Reply