监视文档事件

将宏分配给事件旁边,可以监视 LibreOffice 文档所引发的事件。应用程序编程接口 (API) 广播器负责调用事件脚本。与需要定义所有支持的方法 (即使未使用) 的监听器不同, 文档监视器对已挂钩的事件脚本只需要两个方法。

监听文档事件

本文采用 Basic 与 Python 语言,通过面向对象编程来演示监视功能。将 OnLoad 脚本分配给 文档打开 事件, 就足以启动和终止文档事件监视。工具 – 自定义...菜单的事件选项卡用于分配各脚本。

侦听事件有助于在条件之前和之后安放脚本, 如加载与卸载库, 或在后台跟踪脚本处理进度。Access2Base 跟踪 模块的使用就是第二种情况的体现。

使用 Python

事件监视从对象实例化开始, 并在 Python 释放对象时最终停止。引发的事件通过Access2Base 控制台报告。

note

OnLoadOnUnload 事件可用于分别设置和取消设置 Python 程序路径。它们被称为文档打开 文档关闭



         # -*- 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):
             """ 监视文档事件 """
             '''
             改编自「用于监视 OnSave 事件的 Python 脚本」,见于
             https://forum.openoffice.org/en/forum/viewtopic.php?t=68887
             '''
             def __init__(self):
                 """ 文档事件监视器 """
                 ''' 使用 Access2Base.Trace 控制台报告,*或*
                 在 Calc 文档的第一个工作表的第一列报告 '''
                 ctx = uno.getComponentContext()
                 smgr = ctx.getServiceManager()
                 desktop = smgr.createInstanceWithContext(
                 'com.sun.star.frame.Desktop' , ctx)
                 self.doc = desktop.CurrentComponent
                 #self.row = 0  # 仅对 Calc 文档取消注释
                 Console.setLevel("DEBUG")
                 self.listen()  # 开始监视文档事件
             
             @property
             def Filename(self) -> str:
                 sys_filename = uno.fileUrlToSystemPath(self.doc.URL)
                 return os.path.basename(sys_filename)
             
             def setCell(self, calcDoc, txt: str):
                 """ 在 Calc 电子表格的第一列输出文档事件 """
                 sheet = calcDoc.getSheets().getByIndex(0)
                 sheet.getCellByPosition(0,self.row).setString(txt)
                 self.row = self.row + 1
             
             def listen(self, *args):  # 尽可能早执行 OnLoad/OnNew
                 """ 开始文档事件监视 """
                 self.doc.addDocumentEventListener(self)
                 Console.log("INFO", "正在记录文档事件", True)
             
             def sleep(self, *args):  # 最后执行 OnUnload (可选)
                 """ 停止文档事件监视 """
                 self.doc.removeDocumentEventListener(self)
                 Console.log("INFO", "文档事件已记录", True)
             
             def documentEventOccured(self, event: DocumentEvent):
                 """ 截取所有文档事件 """
                 #self.setCell(event.Source, event.EventName) # 仅适用于 Calc 文档
                 Console.log("DEBUG",
                     event.EventName+" in "+self.Filename,
                     False)
             
             def disposing(self, event: EventObject):
                 """ 释放所有活动 """
                 self.sleep()
                 Console.show()
             
         def OnLoad(*args):  #「文档打开」事件
             listener = UiDocument()  # Initiates listening
             
         def OnUnload(*args):  # '文档已关闭' 事件
             pass  # (可选) 销毁时执行
             
         g_exportedScripts = (OnLoad,)
             
         from com.sun.star.script.provider import XScript
         class Console():
             """
             用于报告/记录程序执行的后台/前台控制台。
             """
             @staticmethod
             def trace(*args,**kwargs):
                 """ 向控制台打印空闲项目列表 """
                 scr = Console._a2bScript(script='DebugPrint', module='Compatible')
                 scr.invoke((args),(),())
             @staticmethod
             def log(level: str, text: str, msgBox=False):
                 """ 日志消息追加到控制台,可选用户提示 """
                 scr = Console._a2bScript(script='TraceLog')
                 scr.invoke((level,text,msgBox),(),())
             @staticmethod
             def setLevel(logLevel: str):
                 """ 设置日志消息下限 """
                 scr = Console._a2bScript(script='TraceLevel')
                 scr.invoke((logLevel,),(),())
             @staticmethod
             def show():
                 """ 显示控制台内容/对话框 """
                 scr = Console._a2bScript(script='TraceConsole')
                 scr.invoke((),(),())
             @staticmethod
             def _a2bScript(script: str, library='Access2Base',
                 module='Trace') -> XScript:
                 ''' Grab application-based Basic script '''
                 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
      
warning

注意拼写错误的 documentEventOccured 方法, 该错误继承自 LibreOffice 应用程序编程接口 (API)。


提示图标

启动应用程序关闭应用程序事件可分别用于为用户脚本或 LibreOffice 脚本设置和取消设置 Python 路径。类似地, 可以使用文档打开文档关闭 事件来加载和释放基于文档的 Python 库或模块。有关详细信息, 请参阅导入 Python 模块


使用 LibreOffice Basic

Onload脚本分配给文档打开事件可通过工具 – 自定义...菜单事件选项卡进行。事件监视从 ConsoleLogger 对象实例化的那一刻起就开始了,并在 Basic 引擎释放它时终止。 OnLoad事件可加载必要的 Basic 库, 同时使用Access2Base.Trace 报告捕获的事件。


          REM controller.Events 模块
          Option Explicit
          Private _obj As Object ' controller.ConsoleLogger 实例
              
          Sub OnLoad(evt As com.sun.star.document.DocumentEvent) ' >> 文档打开 <<
              _obj = New ConsoleLogger : _obj.Start(evt)
          End Sub ' controller.OnLoad
          ' ----
          REM controller.ConsoleLogger 类模块
          Option Explicit
          Option Compatible
          Option ClassModule
              
          '「适配器」设计模式对象,将在 « 文档打开 » 事件中实例化
          Private Const UI_PROMPT = True
          Private Const UI_NOPROMPT = False ' Set it to True to visualise documents events
              
          ' 构造函数/析构函数
          Private Sub Class_Initialize()
          End Sub ' controller.ConsoleLogger.Initialize
          Private Sub Class_Terminate()
          End Sub ' controller.ConsoleLogger.Terminate
              
          ' 成员
          Private _evtAdapter As Object ' com.sun.star.document.XDocumentEventBroadcaster
              
          ' PROPERTIES
          Private Property Get FileName As String
              ''' 受系统影响的文件名 '''
              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
              
          ' 方法
          Private Sub _documentEventOccured(evt As com.sun.star.document.DocumentEvent)
              ''' 监视文档事件 '''
              Access2Base.Trace.TraceLog("DEBUG", _
                  evt.EventName &" in "& Filename(evt.Source.URL), _
                  UI_NOPROMPT)
              Select Case evt.EventName
                  Case "OnUnload" : _Stop(evt)
              End Select
          End Sub ' controller.ConsoleLogger._documentEventOccured
              
          Private Sub _disposing(evt As com.sun.star.lang.EventObject)
          End Sub ' controller.ConsoleLogger.disposing
              
          Public Sub Start(Optional evt As com.sun.star.document.DocumentEvent)
              ''' 初始化文档事件记录 '''
              Const _LIBRARY = "Access2Base" : With GlobalScope.BasicLibraries
                  If Not .IsLibraryLoaded(_LIBRARY) Then .LoadLibrary(_LIBRARY)
              End With : Access2Base.Trace.TraceLevel("DEBUG")
              Access2Base.Trace.TraceLog("INFO", _
                  IIf(IsMissing(evt),"",evt.EventName & "-") & "正在记录文档事件", _
                  UI_PROMPT)
              
              _evtAdapter = CreateUnoListener( "_", "com.sun.star.document.XDocumentEventListener" )
              ThisComponent.addDocumentEventListener( _evtAdapter )
          End Sub ' controller.ConsoleLogger.Start
              
          Private Sub _Stop(Optional evt As com.sun.star.document.DocumentEvent)
              ''' 终止文档事件记录 '''
              ThisComponent.removeDocumentEventListener( _evtAdapter )
              Access2Base.Trace.TraceLog("INFO", _
                  IIf(IsMissing(evt),"",evt.EventName & "-") & "文档事件已记录", _
                  UI_PROMPT)
              Access2Base.Trace.TraceConsole() ' Captured events dialog
          End Sub ' controller.ConsoleLogger._Stop
              
          ' EVENTS
          ' 用于已处理事件的代码放在这里
      
warning

注意拼写错误的 _documentEventOccured 方法, 该错误继承自 LibreOffice 应用程序编程接口 (API)。


探索文档事件

广播器 API 对象提供了它所负责的事件列表:

使用 Python


         # -*- coding: utf-8 -*-
         from __future__ import unicode_literals
             
         import uno, apso_utils as ui
             
         def displayAvailableEvents():
             """ 显示文档事件 """
             '''
             改编自 DisplayAvailableEvents(),作者为 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,)
      
note

替代 Python 脚本管理器 (APSO)」扩展程序用于在屏幕上渲染事件信息。


使用 LibreOffice Basic


         Sub DisplayAvailableEvents
             ''' 显示文档事件 '''
             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
      

请支持我们!