Справка LibreOffice 26.2
Прослушивание событий документа может помочь в следующих ситуациях:
Идентификация документа в момент открытия как нового (чтобы отличить от уже существующих) для выполнения специализированной настройки.
Контроль обработки запросов на сохранение, копирование и печать документа, а также на выполнение рассылки писем.
Обновление оглавлений, указателей или элементов таблицы документа Writer перед его закрытием
Импорт математических пакетов Python перед открытием документа Calc. Отключение этих пакетов после закрытия документа.
После назначения макросов событиям можно отслеживать события, возникающие в документах LibreOffice. За вызов сценариев обработки событий отвечают источники событий API. В отличие от слушателей, требующих определения всех поддерживаемых методов (даже неиспользуемых), обработчики событий документа требуют наличия лишь двух методов помимо самих сценариев обработки событий.
Отслеживание событий показано здесь на языках Basic и Python с применением объектно ориентированного программирования. Для запуска и завершения процесса отслеживания событий документа достаточно назначить сценарий OnLoad событию . Назначение события какому-либо сценарию выполняется в меню на вкладке .
Перехват событий помогает настраивать сценарии пред- и постусловия, например, загрузка и выгрузка библиотек или фоновое отслеживание выполнения сценариев. Использование модуля Access2Base.Trace служит иллюстрацией последнего из указанных вариантов.
Отслеживание событий начинается с создания экземпляра документа и окончательно завершается после автоматического удаления объекта средствами Python. Возникающие события регистрируются в консоли Access2Base.
События OnLoad и OnUnload можно использовать, соответственно, для установки и сброса путей к программам 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):
""" Отслеживание событий документа """
'''
Основано на примере «Сценарий Python для отслеживания события OnSave» на
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() # Инициализирует прослушивание
def OnUnload(*args): # Событие 'Документ закрыт'
pass # (необязательно) выполняется при вызове метода disposed
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:
''' Получение сценария Basic из общей библиотеки'''
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
Обратите внимание на грамматическую ошибку в названии метода documentEventOccured, в котором опечатка наследуется из LibreOffice API.
События и могут использоваться, соответственно, для установки и сброса путей к программам Python для пользовательских сценариев или сценариев LibreOffice. Таким же образом можно загружать и выгружать встроенные библиотеки или модули Python с помощью событий и . Более подробную информацию см. в разделе Импорт модулей Python.
При помощи меню вкладка , событие запускает инициализацию ConsoleLogger. Процедура _documentEventOccured, которую запускает ConsoleLogger, служит единой точкой входа для перехвата всех событий документа.
Option Explicit
Global _obj As Object ' экземпляр controller.ConsoleLogger
Sub OnLoad(evt As com.sun.star.document.DocumentEvent) ' >> Открытие файла <<
_obj = New ConsoleLogger : _obj.StartAdapter(evt)
End Sub ' controller.OnLoad
Sub _documentEventOccured(evt As com.sun.star.document.DocumentEvent)
''' Единая точка входа ConsoleLogger '''
_obj.DocumentEventOccurs(evt)
End Sub ' controller._documentEventOccured
Отслеживание событий начинается с момента инициализации объекта ConsoleLogger и окончательно завершается при закрытии документа. Процедура StartAdapter загружает необходимые библиотеки Basic, а перехваченные события регистрируются при помощи модуля Access2Base.Trace.
Option Explicit
Option Compatible
Option ClassModule
' Объект шаблона проектирования ADAPTER, экземпляр которого необходимо создать при событии «Открытие файла»
Private Const UI_PROMPT = True
Private Const UI_NOPROMPT = False ' Установите значение True для визуализации событий документа
' ЭЛЕМЕНТЫ КЛАССА
Private _evtAdapter As Object ' com.sun.star.document.XDocumentEventBroadcaster
Private _txtMsg As String ' текстовое сообщение для записи в консоль
' СВОЙСТВА
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
' МЕТОДЫ
Public Sub DocumentEventOccurs(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" : _StopAdapter(evt)
End Select
End Sub ' controller.ConsoleLogger.DocumentEventOccurs
Public Sub StartAdapter(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")
If IsMissing(evt) Then _txtMsg = "" Else _txtMsg = evt.EventName & "-"
Access2Base.Trace.TraceLog("INFO", _txtMsg & "Выполняется регистрация событий документа", 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)
''' Завершение регистрации событий документа '''
ThisComponent.removeDocumentEventListener( _evtAdapter )
If IsMissing(evt) Then _txtMsg = "" Else _txtMsg = evt.EventName & "-"
Access2Base.Trace.TraceLog("INFO", _txtMsg & "События документа записаны", UI_PROMPT)
Access2Base.Trace.TraceConsole() ' Диалоговое окно перехваченных событий
End Sub ' controller.ConsoleLogger._StopAdapter
' СОБЫТИЯ
' Собственный код для обработки событий можно вставить здесь
Обратите внимание на грамматическую ошибку в названии метода _documentEventOccured, в котором опечатка наследуется из LibreOffice API.
Объект рассылки событий предоставляет список событий, за которые он отвечает:
# -*- 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,)
Расширение Alternative Python Script Organizer (APSO) используется для вывода информации о событиях на экран.
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