Link macro to document through script

I have a project with a hundred or so documents.

I have a macro I want to link to each document’s OPEN event.

But I want to avoid the dialog conversation required to link a document to a macro.

The documents share a template and I have linked the macro to the template’s OPEN event.

When I make a style change to a template, this new style is applied to documents that are based on the template, but this macro event link is not applied.

Can I do a mass update with a global script/macro?

If so, which document property do I explore for this connection?

I haven’t found a comprehensive scripting API for Python. I suspect that the Python API is easily derived from the UNO API. Is this correct? Where can I find this?

Actually UNO can be used from C++, Basic, Python, Java, JavaScript etc. So there is no derived Python-API, but obviously you have to adapt types…

Write a Python script which replaces the macro code in each document with the updated code. Office documents are zipped XML. Python macros are plain text.

Hello,

the document events (ex: "OnOpen") can be known from the ThisComponent.Events property. The Events property exposes an array of Property type, two per event.

The two event properties are:
Property 1

  • Name: the event managing flag (ex: "Script")
  • Handle: (internal?)
  • Value: the script to call when the event occurs (ex: "vnd.sun.star.script:Standard.Module1.OnOpenDocument?language=Basic&location=document")
  • State: (internal?)

Property 2

  • Name: the event type flag (ex: "EventType")
  • Handle: (internal?)
  • Value: the event name (ex: "OnLoad")
  • State: (internal?)

Note that apparently nothing ensures you read Property 1 before Property 2 (well, I never found any evidence that would ensure the order for reading these properties values).
Thus I have the following function to retrieve the Events information (extracted from my TheCAT extension):

Function GetEventsArray(ByRef pEvents As Object) As Variant
'converts the event properties into an easier to handle array of strings.
'Output: a 3 column array with 1 row per event:
'-- col 0: the event name (‘OnLoad’)
'-- col 1: the event process (‘vnd.sun.star.script:Standard.Module1.OnOpenDocument?language=Basic&location=document’)
'-- col 2: the complete string

Dim l_Array() As Variant
Dim l_Item As String
Dim l_Desc As Variant
Dim l_Str As String
Dim l_Type As String
Dim l_Pos1 As Long
Dim l_Pos2 As Long
Dim i As Integer

ReDim l_Array(UBound(pEvents.ElementNames), 2)
i = 0
For Each l_Item In pEvents.ElementNames
l_Desc = pEvents.getByName(l_Item)
'check the array is valid (ArrayExists() function is part of my array tools)
If Tools.ArrayExists(l_Desc) Then
l_Array(i, 0) = l_Item

  	'get type
  	l_Type = ""
  	If (l_Desc(0).Name = "EventType") Then 
  		l_Type = l_Desc(0).Value
  	ElseIf (l_Desc(1).Name = "EventType") Then 
  		l_Type = l_Desc(1).Value
  	End If
  	l_Array(i, 1) = l_Type

  	'get handler
  	l_Str = ""
  	If (l_Desc(0).Name = l_Type) Then 
  		l_Str = l_Desc(0).Value
  	ElseIf (l_Desc(1).Name = l_Type) Then 
  		l_Str = l_Desc(1).Value
  	End If
  	'if "Script" then l_Str is smthg like: "vnd.sun.star.script:Standard.Module1.OnOpenDocument?language=Basic&location=document"
  	l_Array(i, 2) = l_Str
  	
  	i = i + 1
  End If

Next l_Item

If (i > 0) Then
ReDim Preserve l_Array(i - 1, 2)
Else
Erase l_Array()
End If

GetEventsArray = l_Array()
End Function 'GetEventsArray

Call: MyArray() = GetEventsArray(ThisComponent.Events)

So, changing the event managing string should be feasible, but I never tried to add such an event manager when it doesn’t exist yet.

In the worst case, if you uncompress the document and have a look at its content.xml file, you find:


  <office:scripts>
    <office:event-listeners>
      <script:event-listener script:language="ooo:script" script:event-name="dom:load" xlink:href="vnd.sun.star.script:Standard.Classeur.OnDocumentOpen?language=Basic&amp;location=document" xlink:type="simple" />
    </office:event-listeners>
  </office:scripts>

which means you may add the event manager (aka listener) here. I, for sure, know this can be done.
This solution pro is that you may do that silently in some batch program.

HTH,

It seems you are able to write the macro alone. The source for Basic is A. Pitonyak Macro Book:
I haven’t time to rewrite these macros to Python :frowning:

  1. chapter 13.5 and 13.5.1. to set event to document
  2. chapter 8.5 to get file list in directory (and chapter 8.3 with the Function PrettyFileLen) used in 8.5