Page 1 of 1
ToC incorrectly updated with automated script
Posted: Wed Apr 22, 2009 11:09 am
by Beld
I have an automated script that pulls data from a database and then places it in an OpenOffice document.
In this document I have specified a Table of Content, I want to update this Table of Content and then save the file in any format I please.
For this I use the following script:
Code: Select all
' Save document as the given type.
Sub SaveAs( cType, cExtension, cFile )
On Error Goto test
cURL = ConvertToURL( cFile )
' Open the document. Just blindly assume that the document
' is of a type that OOo will correctly recognize and open
' without specifying an import filter.
oDoc = StarDesktop.loadComponentFromURL( cURL, "_blank", 0, _
Array(MakePropertyValue( "Hidden", True ),))
' in case OOo doesn't recognize the type then do nothing at all.
If Not IsNull(oDoc) Then
oIndexes = oDoc.getDocumentIndexes()
for i = 0 to oIndexes.getCount () - 1
oIndexes (i).update
next i
cFile = Left( cFile, Len( cFile ) - 4 ) + cExtension
cURL = ConvertToURL( cFile )
' Save the document using a filter.
oDoc.storeToURL( cURL, Array(_
MakePropertyValue( "FilterName", cType ),)
oDoc.close( True )
EndIf
Exit Sub
test:
' We do not want any errors displayed.
On Error Goto End
If Not IsNull(oDoc) and Not IsEmpty(oDoc) Then
oDoc.close( True )
EndIf
End Sub
The result is sadly a ToC like this:
Topic 1 .................. 2
Topic 2 .................. 3
Topic 3 .................. 4
The headers Topic 1, Topic 2, and Topic 3 are respectively on pages: 2,3,7
When I open the file and manually update the ToC it displays the page numbers correctly,
but when I use my automated script it doesn't.
I think the problem here is that I load the document and while it's not entirely loaded I update the ToC.
Is there a way to check if the document is fully loaded and at that time update the ToC?
Re: ToC incorrectly updated with automated script
Posted: Wed Apr 22, 2009 4:53 pm
by FJCC
I don't know how to check if a document is fully loaded. I think you could test your theory by adding a Wait step immediately after the loadComponentFromURL step. The unit of Wait is milliseconds, so you could put in
Wait 10000
to create a 10 second pause. If your ToC is then correct, you will at least know that there is not some other problem.
Re: ToC incorrectly updated with automated script
Posted: Wed Apr 22, 2009 5:01 pm
by Beld
I've been testing with this.
at wait 2000 the ToC is close to correct (1 page off at topic 3)
at wait 5000 the ToC is correct.
But I don't know the size of the documents that will go through it so I need it to be always correct no matter the size.
so it looks like the problem is cause by parallel execution of the macro and document laoding.
Re: ToC incorrectly updated with automated script
Posted: Wed Apr 22, 2009 5:06 pm
by FJCC
Thanks for running the test. I'll look around for a way to confirm that the document is loaded. I might not be able to work on this until tonight. (It is morning in my part of the world.)
Re: ToC incorrectly updated with automated script
Posted: Wed Apr 22, 2009 8:57 pm
by Hardy
Hi Beld, why don't you attach an event listener and wait for the
OnLoad event?
Re: ToC incorrectly updated with automated script
Posted: Thu Apr 23, 2009 11:21 am
by Beld
Hardy, thanks for that link it helped quite a bit.
ok I currently have the following code,
this appears to work but I'm not satisfied with it:
Code: Select all
Dim DocumentLoaded as boolean '<-- changes to previous code are marked with these arrows
Sub RegisterListener (ThisComponent) '<--
oListener = CreateUnoListener( "DocumentListener_","com.sun.star.document.XEventListener" ) '<--
ThisComponent.com_sun_star_document_XEventBroadcaster_addEventListener( oListener ) '<--
End Sub '<--
Sub DocumentListener_notifyEvent( o as object ) '<--
DocumentLoaded = true '<--
end sub '<--
Sub DocumentListener_disposing() '<--
End Sub '<--
' Save document as the given type.
Sub SaveAs( cType, cExtension, cFile )
' On Error Goto test
DocumentLoaded = false '<--
cURL = ConvertToURL( cFile )
' Open the document. Just blindly assume that the document
' is of a type that OOo will correctly recognize and open
' without specifying an import filter.
oDoc = StarDesktop.loadComponentFromURL( cURL, "_blank", 0, _
Array(MakePropertyValue( "Hidden", True ),))
RegisterListener(oDoc) '<--
' in case OOo doesn't recognize the type then do nothing at all.
If Not IsNull(oDoc) Then
oIndexes = oDoc.getDocumentIndexes()
If oIndexes.getCount () > 0 Then '<--
Do Until DocumentLoaded '<--
wait 100 '<--
Loop '<--
for i = 0 to oIndexes.getCount () - 1
oIndexes (i).update
next i
EndIf '<--
cFile = Left( cFile, Len( cFile ) - 4 ) + cExtension
cURL = ConvertToURL( cFile )
' Save the document using a filter.
oDoc.storeToURL( cURL, Array(_
MakePropertyValue( "FilterName", cType ),)
oDoc.close( True )
EndIf
Exit Sub
test:
' We do not want any errors displayed.
On Error Goto End
If Not IsNull(oDoc) and Not IsEmpty(oDoc) Then
oDoc.close( True )
EndIf
End Sub
I don't know if the event that is triggered is the onLoad event.
when I try to get the Event Name at the Sub DocumentListener_notifyEvent it returns an empty string.
I used the link from Hardy's post to get this far, and in that link also has an example using the event name.
Code: Select all
IF o.EventName = "OnPrepareUnload" THEN
print o.Source.URL
ENDIF
I changed this to see what event(s) are triggered like this:
and all I got was an empty MsgBox.
This might be a bug or a feature, I don't know which
Now I am wondering if the first event that is triggered is ALWAYS the onload event and not some other event,
that might ruin the workings of this Macro.
Re: ToC incorrectly updated with automated script
Posted: Thu Apr 23, 2009 2:10 pm
by Hardy
Hi Beld
I don't understand what you want to achieve with that part of your code:
Beld wrote:Code: Select all
...
Sub DocumentListener_notifyEvent( o as object ) '<--
DocumentLoaded = true '<--
end sub '<--
...
I thought you'd try something like:
Code: Select all
Sub DocumentListener_notifyEvent( o as object ) '<--
if "OnLoad"=o.EventName then doMakeToC ' or however you called the routine
end sub
Beld wrote:Now I am wondering if the first event that is triggered is ALWAYS the onload event and not some other event,
that might ruin the workings of this Macro.
The first events (if you open a document via GUI) are "OnTitleChanged", "OnModifyChanged", ...
The ""-named event surprised me too (if that be the "OnLoad"?). I currently don't get a complete list, because I haven't got the log file working.
Re: ToC incorrectly updated with automated script
Posted: Thu Apr 23, 2009 2:38 pm
by Beld
well as I stated before it is an automated script.
This macro is called from outside OpenOffice as follows: (ps. it isn't always saved in MS Word format)
"C:/progra~1/openoffice.org 3/program/soffice" -invisible -headless macro:///LLinxx.Conversions.SaveAsDoc("MS Word 97", ".doc","C:/MyFile.odt")
after this macro is done executing I use it again in my automated script.
My script nicely waits for the openoffice macro to finish before continuing with it's own tasks.
In order to make the Macro wait till the event is triggered I added a somewhat global Boolean.
This boolean is not listed in the sub but outside it so that the event can change this value and the macro can notice the change.
Then in my macro that updates the ToC and then saves the file I add the code that makes it wait until the event is fired:
Code: Select all
Do Until DocumentLoaded
wait 100 ' check every 100 ms if DocumentLoaded is true
Loop
Now when the event fires I set the DocumentLoaded boolean to true so that the macro continues at that point.
I haven't put any of my variables (cType, cExtension, cFile) outside the sub SaveAs.
So with the current setup I can't wait for the event to fire, and on another note.
I never found that the OnLoad event fires.
I did find the events:
"OnTitleChanged"
"OnModifyChanged"
... (several others also fired don't remember which ones)
but before these were fired an event without an eventname was fired.
the cause for that might be that I run my macro with "-invisible -headless"
Or perhaps because I open the document hidden:
Code: Select all
oDoc = StarDesktop.loadComponentFromURL( cURL, "_blank", 0, _
Array(MakePropertyValue( "Hidden", True ),))
In short the actions that my Macro currently contain are:
1. Open the document
2. reset the global boolean
3. Register event handler to notice when the document is done loading
4. check if there are indexes
a. wait for the document to finish loading
b. update the indexes
5. save the document in the specified file format
6. close the document
In short the actions that I need:
1. open the document
2. update the indexes if any
3. save the document in the specified file format
4. close the document
Re: ToC incorrectly updated with automated script
Posted: Thu Apr 23, 2009 4:50 pm
by Hardy
Beld wrote:Then in my macro that updates the ToC and then saves the file I add the code that makes it wait until the event is fired:
Code: Select all
Do Until DocumentLoaded
wait 100 ' check every 100 ms if DocumentLoaded is true
Loop
But your code...
Beld wrote:Code: Select all
...
Sub DocumentListener_notifyEvent( o as object ) '<--
DocumentLoaded = true '<--
end sub '<--
...
... doesn't wait for anythig, but for the first event whatever that is.
To fire it for "OnLoad" you might change it to:
Code: Select all
...
Sub DocumentListener_notifyEvent( o as object ) '<--
if NOT DocumentLoaded then DocumentLoaded = ("OnLoad"=o.EventName) '<--
end sub '<--
...
But you wouldn't need the wait loop, if you triggered the launch of your ToC-routine directly by the event.
Re: ToC incorrectly updated with automated script
Posted: Thu Apr 23, 2009 5:03 pm
by Beld
Hardy wrote:But you wouldn't need the wait loop, if you triggered the launch of your ToC-routine directly by the event.
true but how would I transfer the variables passed through to the subroutine.
Cause at the end of my function I use the given variables to save the document.
Hardy wrote:...
doesn't wait for anythig, but for the first event whatever that is.
To fire it for "OnLoad" you might change it to:
Code: Select all
...
Sub DocumentListener_notifyEvent( o as object ) '<--
if NOT DocumentLoaded then DocumentLoaded = ("OnLoad"=o.EventName) '<--
end sub '<--
...
OnLoad event doesn't seem to trigger, so either it's the first event without text or it simply never triggers because the view isn't rendered.
That's the reason why my code currently triggers at the first event is because else it would end up doing nothing at all.....
so in other words triggering at the first event that comes is a
quickfix that I want to get rid off.
Re: ToC incorrectly updated with automated script
Posted: Thu Apr 23, 2009 5:42 pm
by Hardy
ok, "OnLoad" never occurs - that's interesting, but not exactly helpful for you...
Do you have a list of all events that are fired during the first few seconds?
If so, please let me know how you got it (I'm still fighting to get that into a log file, because my document isn't hidden and so the focus events don't allow me to use messsage boxes or the like) and...
... consider to trigger on the last observed event that occurs, before your subsequent code interferes.
Re: ToC incorrectly updated with automated script
Posted: Thu Apr 23, 2009 6:12 pm
by Beld
Sequence when no Indexes in document
""
"OnCopyTo"
"OnCopyToDone"
"OnTitleChanged"
"OnViewClosed"
"OnUnload"
Sequence with Indexes in document
during loop:
""
when updating indexes:
"OnTitleChanged"
"OnModifyChanged"
When saving the file:
"OnCopyTo"
"OnCopyToDone"
When closing the file:
"OnTitleChanged"
"OnViewClosed"
"OnUnload"
randomly during runtime???:
""
how I got the info:
open the Macro window,
place breakpoint at the location where I set the boolean
place several other breakpoints to determine when what events is triggered.
at the variable watch screen add the Event object (o) to the list.
run the macro (with manual call if need be)
now when the runtime reaches the breakpoint you can check what the content of the Event object is.
In this picture you can see the Macro standing in LLinxx/Conversions.
In this picture you can see the breakpoints (see in green square) that I set and the Watch (see in lightblue square) that I set.
example of running the macro I made (using the standard OpenOffice 3.0 directory) assuming the macro is placed at Standard/Module1:
"C:/progra~1/openoffice.org 3/program/soffice" -invisible -headless macro:///Standard.Module1.SaveAs("MS Word 97", ".doc","C:/MyFile.odt")
The complete Macro so you can copy and paste it to test it (most of it was found online as tutorial information) :
Made it as small as possible to save room. most of it is already available in other posts so
Code: Select all
REM ***** BASIC *****
Dim DocumentLoaded as boolean
Sub RegisterListener (ThisComponent)
oListener = CreateUnoListener( "DocumentListener_","com.sun.star.document.XEventListener" )
ThisComponent.com_sun_star_document_XEventBroadcaster_addEventListener( oListener )
End Sub
Sub DocumentListener_notifyEvent( o as object )
DocumentLoaded = true
end sub
Sub DocumentListener_disposing()
End Sub
' Save document as the given type.
Sub SaveAs( cType, cExtension, cFile )
' On Error Goto test
DocumentLoaded = false
cURL = ConvertToURL( cFile )
' Open the document. Just blindly assume that the document
' is of a type that OOo will correctly recognize and open
' without specifying an import filter.
oDoc = StarDesktop.loadComponentFromURL( cURL, "_blank", 0, _
Array(MakePropertyValue( "Hidden", True ),))
RegisterListener(oDoc)
' in case OOo doesn't recognize the type then do nothing at all.
If Not IsNull(oDoc) Then
oIndexes = oDoc.getDocumentIndexes()
If oIndexes.getCount () > 0 Then
Do Until DocumentLoaded
wait 100
Loop
for i = 0 to oIndexes.getCount () - 1
oIndexes (i).update
next i
EndIf
cFile = Left( cFile, Len( cFile ) - 4 ) + cExtension
cURL = ConvertToURL( cFile )
' Save the document using a filter.
oDoc.storeToURL( cURL, Array(_
MakePropertyValue( "FilterName", cType ),)
oDoc.close( True )
EndIf
Exit Sub
test:
' We do not want any errors displayed.
On Error Goto End
If Not IsNull(oDoc) and Not IsEmpty(oDoc) Then
oDoc.close( True )
EndIf
End Sub
Function MakePropertyValue( Optional cName As String, Optional uValue ) _
As com.sun.star.beans.PropertyValue
Dim oPropertyValue As New com.sun.star.beans.PropertyValue
If Not IsMissing( cName ) Then
oPropertyValue.Name = cName
EndIf
If Not IsMissing( uValue ) Then
oPropertyValue.Value = uValue
EndIf
MakePropertyValue() = oPropertyValue
End Function
[/size]
Re: ToC incorrectly updated with automated script
Posted: Thu Apr 23, 2009 6:57 pm
by Hardy
Well these breakpoints might work for you, since your document is hidden. Mine is visible and each such breakpoint fires a series (minimum 14) events including, of course, the focus events but these cause a row of other resulting events (either before or after the focus events). That's why I want to write it to a log file in the background, but that file seems always to be closed prematurely.
Re: ToC incorrectly updated with automated script
Posted: Tue Apr 28, 2009 12:21 pm
by Hardy
Hi Beld
Just found some more document events (event property of the document object (thisComponent)).
The ElementNames Pseudoproperty contains the following array:
(0) = OnStartApp
(1) = OnCloseApp
(2) = OnNew
(3) = OnLoad
(4) = OnSaveAs
(5) = OnSaveAsDone
(6) = OnSave
(7) = OnSaveDone
(8) = OnPrepareUnload
(9) = OnUnload
(10) = OnFocus
(11) = OnUnfocus
(12) = OnPrint
(13) = OnModifyChanged
(14) = OnCopyTo
(15) = OnCopyToDone
(16) = OnViewCreated
(17) = OnPrepareViewClosing
(18) = OnViewClosed
(19) = OnVisAreaChanged
(20) = OnCreate
(21) = OnLoadFinished
(22) = OnSaveAsFailed
(23) = OnSaveFailed
(24) = OnCopyToFailed
(25) = OnTitleChanged
(26) = OnModeChanged
(27) = OnMailMerge
(28) = OnPageCountChange
Perhaps "OnLoadFinished" occurs for your document and is the one that helps?
Re: ToC incorrectly updated with automated script
Posted: Tue Apr 28, 2009 12:31 pm
by Beld
wel the events with these names are triggered according to my test:
"" (not listed, and no EventName specified)
"OnTitleChanged" (nr 25 in that list of yours)
"OnModifyChanged" (nr 13)
"OnCopyTo" (nr 14)
"OnCopyToDone" (nr 15)
"OnViewClosed" (nr 18)
"OnUnload" (nr 9)
I've reported that empty event as a bug because it should have an EventName and according to my tests it doesn't.
Re: ToC incorrectly updated with automated script
Posted: Tue Apr 28, 2009 1:06 pm
by Hardy
The numbers in my post above are array indices, no relation to sequence of occurence.
My suspicion is that the ""-event is actually the the "OnLoad", but that it is triggered before the load and thus lacks some space (allocated memory) to store the string.
Under the events you could log, have you tried all of them for suitability? ("OnViewClosed" or "OnUnload" which might occur before actually unloading (wonder whether there is such a thing as "CancelEvent" for this one, then closing the doc after having written the ToC)?)
Re: ToC incorrectly updated with automated script
Posted: Sun Dec 17, 2017 11:51 pm
by _savage
Was there ever a proper solution to this problem? I noticed that a Writer document’s
statistics are similarly incomplete when the initial call to
loadComponentFromURL() returns. A related discussion is
Is there any loading status for LoadComponentFromURL.