Found another answer. This is actually a way of configuring events programmatically, including actions in response to the opening of a form in Base, i.e. event “When loading”. When editing “manually” you access this on the “Events” tab when you edit a form, so it certainly seems to belong to the form. And actually, it does.
It seems you have to open the form to get to this. There is a little bit of confusion about the word “form”. I refer to the thing seen by the user as the “user-seen-form”.
The first thing you have to do, assuming you know the name of the user-seen-form (as it appears as an icon in the main dialog under “Forms” on opening Base) is get the “content”. I call this content
because the implementation name is “com.sun.star.comp.sdb.Content”.
contents = doc.FormDocuments.getElementNames()
content = doc.FormDocuments.getByName(form_name) # implementation name .sdb.Content
The next thing is to get the com.sun.star.form.OFormsCollection
object. It is important to realise that each “user-seen-form” has one of these OFormsCollection
s.
content_component = content.getComponent()
o_forms_collection = content_component.getDrawPage().getForms() # implementation name form.OFormsCollection
NB clearly this variable o_forms_collection
can be obtained only if you have access to a genuine XComponent
. In fact, getComponent()
on content
above, representing the user-seen-form, returns None
until the user-seen-form in question is actually opened and visible by the user.
This OFormsCollection
object seems always to have 2 script events. The first of the two seems to contain things of interest:
o_forms_collection.getScriptEvents(0)
If there is a macro PythonVersion
in embedded module myscript.py
, attached to event “When record changes”, this prints as:
((com.sun.star.script.ScriptEventDescriptor){ ListenerType = (string)"XRowSetListener", EventMethod = (string)"cursorMoved", AddListenerParam = (string)"", ScriptType = (string)"Script", ScriptCode = (string)"vnd.sun.star.script:myscript.py$PythonVersion?language=Python&location=share" },)
Rather strangely for what is a “collective” object, it implements XEventAttacherManager, and exposes the events of the user-seen-form. So it’s possible to “edit” the events of the user-seen-form by revokeScriptEvent
, insertEntry
, etc. This would be a way of configuring events automatically, removing the need to configure manually. When I also manually attached another macro (“Standard.Module1.RemoveImages”), to a different event (“When loading”) on the same user-seen-form getScriptEvents(0)
then printed out thus:
((com.sun.star.script.ScriptEventDescriptor){ ListenerType = (string)"XLoadListener", EventMethod = (string)"loaded", AddListenerParam = string)"", ScriptType = (string)"Script", ScriptCode = string)"vnd.sun.star.script:Standard.Module1.RemoveImages?language=Basic&location=application" }, (com.sun.star.script.ScriptEventDescriptor){ ListenerType = (string)"XRowSetListener", EventMethod = (string)"cursorMoved", AddListenerParam = (string)"", ScriptType = (string)"Script", ScriptCode = string)"vnd.sun.star.script:myscript.py$PythonVersion?language=Python&location=share" })
The elements in this OFormsCollection
are of implementation name com.sun.star.comp.forms.ODatabaseForm
, but all of these belong to the “user-seen-form”, and there can be more than one such for each “user-seen-form”.
These ODatabaseForm
s implement many interfaces, including things like com.sun.star.sdb.XResultSetAccess
, com.sun.star.sdbc.XResultSetUpdate
, so the other way to achieve automation, for example when the record set is changed, is to use an appropriate listener.
PS it is possible to obtain the .sdb.Content
object when you use an XDocumentListener
on the main .odb top-of-hierarchy “document”:
class DocEventListener(unohelper.Base, XDocumentEventListener):
def documentEventOccured(self, event):
if event.EventName == 'OnSubComponentOpened':
if event.Supplement != None:
if is_uno_interface(event.Supplement, XComponent):
frame = event.Supplement # object of implementation name ... frame.XFrame
contents = doc.FormDocuments.getElementNames()
found_corresponding_form = False
# now iterate through the names of all the user-seen-forms:
for content_name in contents:
content = doc.FormDocuments.getByName(content_name) # object of implementation name sdb.Content
content_component = content.getComponent()
if content_component == None: # "None" indicates an unopened user-seen-form
continue
# this line checks whether the "content" and the "frame" indeed belong to one another...
if content_component.getCurrentController().getFrame() == frame:
found_corresponding_form = True
break
if found_corresponding_form == False:
return
# at this point, `content` is the sdb.Content corresponding to the frame.XFrame