Error on Search at End of Document/Table Cell

Creating a macro - Writing a Script - Using the API (OpenOffice Basic, Python, BeanShell, JavaScript)
Post Reply
Tyll
Posts: 17
Joined: Tue Jun 10, 2008 1:50 pm

Error on Search at End of Document/Table Cell

Post by Tyll »

Hi!

I'm using OOo 2.4.0 on Win XP, I'm also fairly new to coding OOo Basic while having plenty of VBA experience.

What I do

The relevant Basic code searches in a selected text for a regular expression and replaces the found occurances with underscores. This is the relevant code snippet:

Code: Select all

'... declaration of oSearch, oTextRange (created by range from oSelection.getByIndex(i)), oDocument, etc. ...
oFound = oDocument.findNext(oTextRange.getStart(), oSearch)
do while not IsNull(oFound)
   'ERROR OCCURS IN THE NEXT LINE:
  if oTextRange.getText().compareRegionEnds(oFound, oTextRange.getEnd()) = -1 then exit do
  oFound.setString(String(Len(oFound.getString()), "_"))
  oFound = oDocument.findNext(oFound.getEnd(), oSearch)
loop
The Problem

The code works fine, except in certain exotic circumstances: The marked line of code triggers an IllegalArgumentException (no Message) only if oTextRange is such that it
  • a) contains the last or next to last character of any text in a table cell which is not the last table cell (and not the only table cell in a table with only one cell),
or
  • b) contains the last or next to last character of text in a document which anywhere contains an anchor for a textframe.
Since under 'normal' conditions (no tables, no textframes) the code works without problems at the end of the document or other objects, it seems unlikely that the comparison of region ends should be faulty, but what else could it be?

Does anyone recognize this behaviour and knows how to fix or avoid it? I cannot make sure in advance that the working document contains no tables, textframes, etc. and I want the replace to work in as many scenarios (different types/positions of selected text) as possible.

Thanks! Tyll
TerryE
Volunteer
Posts: 1401
Joined: Sat Oct 06, 2007 10:13 pm
Location: UK

Re: Error on Search at End of Document/Table Cell

Post by TerryE »

You need to be careful when folding method calls. The method call compareRegionEnds expects two input arguments which support the XTextRange interface. Your mistake is to assume that oFound and oTextRange.getEnd() always support XTextRange. If you break the code out and put in the extra checks you will see why :-)
Ubuntu 11.04-x64 + LibreOffice 3 and MS free except the boss's Notebook which runs XP + OOo 3.3.
Tyll
Posts: 17
Joined: Tue Jun 10, 2008 1:50 pm

Re: Error on Search at End of Document/Table Cell

Post by Tyll »

Thanks Terry!

I already do check beforehand if the selection (from which the ranges are created) supports the TextRanges service, and if not the replace function isn't even called -- so when the above error occurs, a check has already passed. Is that not sufficient, and why not?

Xraying oFound and oTextRange shows that both objects support the XTextRange interface under any of the above circumstances.

And concerning my specific observation: Do you have an explanation why text at the very end of a document should not support the service if there is a textframe anchor anywhere in the document, while text in any other paragraph of the document does seem to support the service? I know that VBA often shows inexplicably strange behaviour when the "end of document" mark is selected, so maybe it's just the same here: Shit happens. But your answer seems to imply that I'm missing some obvious point. Please enlighten me (or maybe you can point me to a resource of enlightenment?) ... :)

Regards, Tyll
TerryE
Volunteer
Posts: 1401
Joined: Sat Oct 06, 2007 10:13 pm
Location: UK

Re: Error on Search at End of Document/Table Cell

Post by TerryE »

Tyll,

Here was my little test Q&D harness:

Code: Select all

Sub Main
oDocument  = ThisComponent
oText      = oDocument.Text
'print oText.String
oEnd       = oText.End
oStart     = oText.Start
oSearch    = oDocument.createSearchDescriptor()

oSearch.SearchString            = "the"
oSearch.SearchCaseSensitive     = True
oSearch.SearchRegularExpression = False

oFound = oDocument.findNext(oStart, oSearch)
Do While Not IsNull(oFound)
'  print oFound.String
   'ERROR OCCURS IN THE NEXT LINE:
  If oText.compareRegionEnds(oFound, oEnd) = -1 Then Exit Do
  oFound.String = String( Len(oFound.String), "_")
  oFound = oDocument.findNext(oFound.End, oSearch)
Loop

End Sub
If you read the API manual for compareRegionEnds

Returns
  • 1, if xR1 ends before xR2, 0, if xR1 ends at the same position as xR2 and -1, if xR1 ends behind xR2.
Throws
  • com::sun::star::lang::IllegalArgumentException if either xR1 or xR2 is not within this text.
[My italics]. What this is saying is that compareRegionEnds is a method associated with an object that supports the XTextRangeCompare interface. The two text ranges which are arguments must be contained within the parent object. Your code assumes that this is true. This works fine for flat text, but frames and tables introduce a hierarchical structure to the Text objects and in this case the assumption can fail.

The findNext method traverses this hierarchical structure. oFound.Text is not the same object as oText when oFound is in a table or Frame, (and the same can apply for oFound).
Ubuntu 11.04-x64 + LibreOffice 3 and MS free except the boss's Notebook which runs XP + OOo 3.3.
Tyll
Posts: 17
Joined: Tue Jun 10, 2008 1:50 pm

Re: Error on Search at End of Document/Table Cell

Post by Tyll »

Okay, thanks! I think what I missed was, that the compared region ends can very well lie beyond the text range on which the search is done -- and the if-clause checking on parameter "-1" even relies on the oFound region end transgressing the oTextCursor region end, yes?

So, the obvious question is: Is there a way to exit the search without comparing region ends? Textbook examples don't seem to consider alternatives, but I cannot be the first person with macro searches that should work beyond flat text. :) You said in your first posting that I'd have to put in additional checks, so I'll try that and post again if I find a solution. Until then I work around the problem by resume next on local error, because the replacements are already all done at the time when the exception is thrown, but it's not very satisfactory.

Regards, Tyll
Post Reply