Inhoud

# Documentgebeurtenissen monitoren

Het monitoren van documentgebeurtenissen kan nuttig zijn in de volgende situaties:

- Een nieuw document herkennen bij het openen, als er een andere initialisatie nodig is dan bij een bestaand document.

- Het beheren van opslaan van document, het kopiëren van documenten, afdrukken en brief verzoeken.

- Inhoudsopgave en indexen opnieuw bepalen bij het sluiten van een Writer-document

- Importeer math Python-packages voordat Calc-document wordt geopend. Geef deze weer vrij bij het sluiten van het document.

Naast het koppelen van macro's aan gebeurtenissen, kan men gebeurtenissen volgen die optreden in LibreOffice documenten. Application Programming Interface (API) broadcasters verzorgen het aanroepen van de scripts bij gebeurtenissen. Anders dan listeners waarbij alle ondersteunde methodes moeten zijn gedefinieerd, ook al worden ze niet gebruikt, zijn er hier maar twee methodes verplicht naast de hooked scripts voor gebeurtenissen.

## Documentgebeurtenissen monitoren

Monitoring wordt hier uitgelegd voor de de programmeertalen Basic en Python met gebruik van objectgeoriënteerd programmeren. Het toekennen van het script OnLoad aan de gebeurtenis Open Document, zorgt voor het beginnen en beëindigen van de documentgebeurtenis monitoring. Menu Extra - Aanpassen tab Gebeurtenissen wordt gebruikt voor het toekennen van scripts.

Het onderscheppen van gebeurtenissen dient om vooraf en achteraf voorwaarden te kunnen zetten in het script voor het loaden en unloaden van bibliotheken en het volgen in de achtergrond van de verwerking van het script. Het gebruik van de module Access2Base.Trace is een voorbeeld van het volgen van de verwerking.

### Met Python

Het monitoren van gebeurtenissen begint bij het instantiëren (aanmaken) van het object en stopt bij het door Python vrijgeven van het object. De voorkomende gebeurtenissen worden gemeld op het Access2Base console.

De gebeurtenissen OnLoad en OnUnload kunnen worden gebruikt om het pad van Python respectievelijk te bepalen en te wissen. Zij worden beschreven als Open document en Document closed.

             # -*- coding: utf-8 -*-
             from __future__ import unicode_literals

             import os.path, uno, unohelper
             from com.sun.star.document import DocumentEvent, \
                 XDocumentEventListener as AdapterPattern
             from com.sun.star.lang import EventObject

             class UiDocument(unohelper.Base, AdapterPattern):
                 """ Documentgebeurtenissen monitoren """
                 '''
                 aangepast van 'Python-script om OnSave-gebeurtenis te controleren' op
                 https://forum.openoffice.org/en/forum/viewtopic.php?t=68887
                 '''
                 def __init__(self):
                     """ Documentgebeurtenissen controleren """
                     ''' uitvoer op het Access2Base.Trace console OF
                     rapport in 1e blad, 1e kolom voor Calc-documenten '' '
                     ctx = uno.getComponentContext()
                     smgr = ctx.getServiceManager()
                     desktop = smgr.createInstanceWithContext(
                     'com.sun.star.frame.Desktop' , ctx)
                     self.doc = desktop.CurrentComponent
                     #self.row = 0  # uncomment alleen voor Calc-documenten
                     Console.setLevel("DEBUG")
                     self.listen()  # Start documentgebeurtenissen monitoren

                 @property
                 def Filename(self) -> str:
                     sys_filename = uno.fileUrlToSystemPath(self.doc.URL)
                     return os.path.basename(sys_filename)

                 def setCell(self, calcDoc, txt: str):
                     """ Uitvoer documentgebeurtenissen in 1e kolom van een Calc-document"""
                     sheet = calcDoc.getSheets().getByIndex(0)
                     sheet.getCellByPosition(0,self.row).setString(txt)
                     self.row = self.row + 1

                 def listen(self, *args):  # vanaf OnLoad/OnNew
                     """ Start monitoren documentgebeurtenissen """
                     self.doc.addDocumentEventListener(self)
                     Console.log("INFO", "Documentgebeurtenissen worden gelogd", True)

                 def sleep(self, *args):  # op zijn laatst bij OnUnload (optioneel)
                     """ Stop monitoren documentgebeurtenissen """
                     self.doc.removeDocumentEventListener(self)
                     Console.log("INFO", "Documentgebeurtenissen zijn gelogd", True)

                 def documentEventOccured(self, event: DocumentEvent):
                     """ Onderschept alle documentgebeurtenissen """
                     #self.setCell(event.Source, event.EventName) # alleen voor Calc-documenten
                     Console.log("DEBUG",
                         event.EventName+" in "+self.Filename,
                         False)

                 def disposing(self, event: EventObject):
                     """ Alle activiteiten vrijgeven """
                     self.sleep()
                     Console.show()

             def OnLoad(*args):  # 'Open Document'-gebeurtenis
                 listener = UiDocument()  # Start het afvangen

             def OnUnload(*args):  # De gebeurtenis 'Document gesloten'
                 pass  # (optioneel) uitgevoerd bij verwijdering

             g_exportedScripts = (OnLoad,)

             from com.sun.star.script.provider import XScript
             class Console():
                 """
                 (Achter/Voor)grond console om de programma uitvoering te rapporteren/loggen.
                 """
                 @staticmethod
                 def trace(*args,**kwargs):
                     """ Print vrije item-lijst op console """
                     scr = Console._a2bScript(script='DebugPrint', module='Compatible')
                     scr.invoke((args),(),())
                 @staticmethod
                 def log(level: str, text: str, msgBox=False):
                     """ Zet logbericht op console, optioneel prompt """
                     scr = Console._a2bScript(script='TraceLog')
                     scr.invoke((level,text,msgBox),(),())
                 @staticmethod
                 def setLevel(logLevel: str):
                     """ Bepaal ondergrens logberichten """
                     scr = Console._a2bScript(script='TraceLevel')
                     scr.invoke((logLevel,),(),())
                 @staticmethod
                 def show():
                     """ Toon console inhoud/dialoog """
                     scr = Console._a2bScript(script='TraceConsole')
                     scr.invoke((),(),())
                 @staticmethod
                 def _a2bScript(script: str, library='Access2Base',
                     module='Trace') -> XScript:
                     ''' Haal applicatie-gebaseerd Basic-script op'''
                     sm = uno.getComponentContext().ServiceManager
                     mspf = sm.createInstanceWithContext(
                         "com.sun.star.script.provider.MasterScriptProviderFactory",
                         uno.getComponentContext())
                     scriptPro = mspf.createScriptProvider("")
                     scriptName = "vnd.sun.star.script:"+library+"."+module+"."+script+"?language=Basic&location=application"
                     xScript = scriptPro.getScript(scriptName)
                     return xScript

Denk aan de verkeerd geschreven methode documentEventOccured die een tikfout overerft van LibreOffice Application Programming Interface (API).

De gebeurtenissen Programma starten en Programma sluiten kunnen respectievelijk worden gebruikt voor het zetten en vrijgeven van het Python-pad voor gebruikersscripts of voor LibreOffice-scripts. Op een vergelijkbare manier kunnen documentgebaseerde Python-bibliotheken en modules worden geladen en vrijgegeven met de gebeurtenissen Document openen en Document gesloten. Bekijk Python-modules importeren voor meer informatie.

### Met LibreOffice BASIC.

Via het menu Extra - Aanpassen tabblad Gebeurtenissen, de gebeurtenis Document openen zorgt voor de initialisatie van ConsoleLogger. De routine documentEventOccured - gezet door de ConsoleLogger - dient als een uniek toegangspunt om alle document-gebeurtenissen af te vangen.

#### controller.Events module

            Option Explicit

            Global _obj As Object ' controller.ConsoleLogger instance

            Sub OnLoad(evt As com.sun.star.document.DocumentEvent) ' >> Document openen <<
                _obj = New ConsoleLogger : _obj.StartAdapter(evt)
            End Sub ' controller.OnLoad
            Sub _documentEventOccured(evt As com.sun.star.document.DocumentEvent)
                ''' ConsoleLogger uniek toegangspunt '''
                 _obj.DocumentEventOccurs(evt)
            End Sub ' controller._documentEventOccured

#### module van klasse controller.ConsoleLogger

Het monitoren van gebeurtenissen begint op het moment dat een ConsoleLogger object is aangemaakt en stopt uiterlijk als het document wordt gesloten. De routine StartAdapter laad de benodigde Basic-bibliotheken, afgevangen gebeurtenissen worden gerapporteerd via de module Access2Base.Trace.

              Option Explicit
              Option Compatible
              Option ClassModule

              ' ADAPTER design pattern object aanmaken wordt gedaan door de gebeurtenis "Document openen"
              Private Const UI_PROMPT = True
              Private Const UI_NOPROMPT = False ' Om documentgebeurtenissen te visualiseren, zet dit op True

              ' MEMBERS
              Private _evtAdapter As Object ' com.sun.star.document.XDocumentEventBroadcaster
              Private _txtMsg As String ' tekstbericht om in console te loggen

              ' PROPERTIES
              Private Property Get FileName As String
                  ''' Systeem afhankelijke bestandsnaam '''
                  Const _LIBRARY = "Tools" : With GlobalScope.BasicLibraries
                      If Not .IsLibraryLoaded(_LIBRARY) Then .LoadLibrary(_LIBRARY)
                  End With
                  Filename = Tools.Strings.FilenameOutofPath(ThisComponent.URL)
              End Property ' controller.ConsoleLogger.Filename

              ' METHODS
              Public Sub DocumentEventOccurs(evt As com.sun.star.document.DocumentEvent)
                  ''' Documentgebeurtenissen monitoren '''
                  Access2Base.Trace.TraceLog("DEBUG", _
                      evt.EventName &" in "& Filename(evt.Source.URL), _
                      UI_NOPROMPT)
                  Select Case evt.EventName
                      Case "OnUnload" : _StopAdapter(evt)
                  End Select
              End Sub ' controller.ConsoleLogger.DocumentEventOccurs

              Public Sub StartAdapter(Optional evt As com.sun.star.document.DocumentEvent)
                  ''' Initialiseren logging documentgebeurtenissen '''
                  Const _LIBRARY = "Access2Base" : With GlobalScope.BasicLibraries
                      If Not .IsLibraryLoaded(_LIBRARY) Then .LoadLibrary(_LIBRARY)
                  End With : Access2Base.Trace.TraceLevel("DEBUG")
                  If IsMissing(evt) Then _txtMsg = "" Else _txtMsg = evt.EventName & "-"
                  Access2Base.Trace.TraceLog("INFO", _txtMsg & "Documentgebeurtenissen worden gelogd", UI_PROMPT)
                  _evtAdapter = CreateUnoListener( "_", "com.sun.star.document.XDocumentEventListener" )
                  ThisComponent.addDocumentEventListener( _evtAdapter )
              End Sub ' controller.ConsoleLogger.StartAdapter

              Private Sub _StopAdapter(Optional evt As com.sun.star.document.DocumentEvent)
                  ''' Beëindig de logging van documentgebeurtenissen '''
                  ThisComponent.removeDocumentEventListener( _evtAdapter )
                  If IsMissing(evt) Then _txtMsg = "" Else _txtMsg = evt.EventName & "-"
                  Access2Base.Trace.TraceLog("INFO", _txtMsg & "Documentgebeurtenissen zijn gelogd", UI_PROMPT)
                  Access2Base.Trace.TraceConsole() ' Afgevangen gebeurtenissendialoog
              End Sub ' controller.ConsoleLogger._StopAdapter

              ' EVENTS
              ' Hier komt uw eigen code voor de afgevangen gebeurtenissen

Denk aan de spelfout in de methode _documentEventOccured die een tikfout erft van de LibreOffice Application Programming Interface (API).

## Documentgebeurtenissen vinden

Het object broadcaster API geeft een lijst gebeurtenissen waar het verantwoordelijk voor is:

### Met Python

             # -*- coding: utf-8 -*-
             from __future__ import unicode_literals

             import uno, apso_utils as ui

             def displayAvailableEvents():
                 """ Documentgebeurtenissen weergeven """
                 '''
                 bewerkte versie van DisplayAvailableEvents() gemaakt door A. Pitonyak
                 https://forum.openoffice.org/en/forum/viewtopic.php?&t=43689
                 '''
                 ctx = XSCRIPTCONTEXT.getComponentContext()
                 smgr = ctx.ServiceManager
                 geb = smgr.createInstanceWithContext(
                     "com.sun.star.frame.GlobalEventBroadcaster", ctx)
                 events = geb.Events.getElementNames()
                 ui.msgbox('; '.join(events))

             g_exportedScripts = (displayAvailableEvents,)

De extensie Alternative Python Script Organizer (APSO) wordt gebruikt om informatie over gebeurtenissen op het scherm weer te geven.

### Met LibreOffice BASIC.

             Sub DisplayAvailableEvents
                 ''' Documentgebeurtenissen weergeven '''
                 Dim geb As Object ' com.sun.star.frame.GlobalEventBroadcaster
                 Dim events() As String
                 geb = CreateUnoService("com.sun.star.frame.GlobalEventBroadcaster")
                 events = geb.Events.ElementNames()
                 MsgBox Join(events, "; ")
             End Sub

Verwante onderwerpen

Listeners aanmaken

Python Modules Importeren

Een dialog-handler aanmaken

Python programmeringsvoorbeelden

Programmeren met Python-scripts

Basic-macro's in Python aanroepen