ເນື້ອໃນ

# ການຮັບຟັງເຫດການຂອງເອກະສານ

ການຮັບຟັງເຫດການຂອງເອກະສານສາມາດຊ່ວຍໃນສະຖານະການຕໍ່ໄປນີ້:

- ລະບຸເອກະສານໃໝ່ໃນເວລາເປີດ, ເພື່ອແຍກອອກຈາກເອກະສານທີ່ມີຢູ່ແລ້ວ, ແລະ ເຮັດການຕັ້ງຄ່າສະເພາະ.

- ຄວບຄຸມຂະບວນການບັນທຶກເອກະສານ, ສຳເນົາເອກະສານ, ພິມ ຫຼື ການຮ້ອງຂໍຈົດໝາຍວຽນ.

- ຄິດໄລ່ຄືນສາລະບານ, ດັດຊະນີ ຫຼື ລາຍການຕາຕະລາງຂອງເອກະສານ Writer ເມື່ອເອກະສານກຳລັງຈະຖືກປິດ.

- ນຳເຂົ້າແພັກເກັດ Python ທາງຄະນິດສາດກ່ອນເປີດເອກະສານ Calc ແລະ ຖອນແພັກເກັດເຫຼົ່ານັ້ນອອກເມື່ອເອກະສານປິດ.

ນອກຈາກ ການກຳນົດແມັກໂຄຣໃຫ້ກັບເຫດການ ແລ້ວ, ເຮົາສາມາດຕິດຕາມເຫດການທີ່ເກີດຂຶ້ນໂດຍເອກະສານ LibreOffice ໄດ້. Broadcasters ຂອງ API ມີໜ້າທີ່ໃນການເອີ້ນໃຊ້ສະຄຣິບເຫດການ. ບໍ່ຄືກັບ listeners ທີ່ຕ້ອງກຳນົດທຸກເມັດທອດທີ່ຮອງຮັບ, ຕົວຕິດຕາມເອກະສານຕ້ອງການພຽງແຕ່ສອງເມັດທອດເທົ່ານັ້ນ.

## ການຕິດຕາມເຫດການຂອງເອກະສານ

ການຕິດຕາມເຫດການແມ່ນສະແດງໄວ້ໃນນີ້ສຳລັບພາສາ Basic ແລະ Python ໂດຍໃຊ້ການຂຽນໂປຣແກຣມແບບເຊີງອອບເຈັກ. ການກຳນົດສະຄຣິບ OnLoad ໃຫ້ກັບເຫດການ ເປີດເອກະສານ ແມ່ນພຽງພໍທີ່ຈະເລີ່ມ ແລະ ສິ້ນສຸດການຕິດຕາມເຫດການ. ແຖບ ເຫດການ ໃນເມນູ ເຄື່ອງມື - ປັບແຕ່ງ ແມ່ນໃຊ້ເພື່ອມອບໝາຍສະຄຣິບ.

ການດັກຈັບເຫດການຊ່ວຍໃນການຕັ້ງເງື່ອນໄຂກ່ອນ ແລະ ຫຼັງການເຮັດວຽກຂອງສະຄຣິບ ເຊັ່ນ ການໂຫຼດ ຫຼື ຖອນໄລບຣາຣີ ຫຼື ຕິດຕາມການປະມວນຜົນສະຄຣິບໃນພື້ນຫຼັງ. ການໃຊ້ໂມດູນ Access2Base.Trace ແມ່ນສະແດງໃຫ້ເຫັນໃນບໍລິບົດທີສອງນີ້.

### ດ້ວຍ Python

ການຕິດຕາມເຫດການຈະເລີ່ມຈາກການສ້າງອອບເຈັກ ແລະ ຢຸດລົງເມື່ອ 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 ຫຼື
                     ລາຍງານໃນແຜ່ນງານທີ 1, ຖັນທີ 1 ສຳລັບເອກະສານ 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):
                     """ ສົ່ງຜົນເຫດການຂອງເອກະສານໃນຖັນທີ 1 ຂອງແຜ່ນງານ 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  # (ຕົວເລືອກເສີມ) ປະຕິບັດເມື່ອຖືກທຳລາຍ

             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 ແມ່ນສະກົດຜິດ ເຊິ່ງເປັນການສືບທອດຂໍ້ຜິດພາດມາຈາກ API ຂອງ LibreOffice.

ເຫດການ ເລີ່ມແອັບພລິເຄຊັນ ແລະ ປິດແອັບພລິເຄຊັນ ສາມາດໃຊ້ເພື່ອຕັ້ງຄ່າ ແລະ ຍົກເລີກເສັ້ນທາງ Python ສຳລັບສະຄຣິບຂອງຜູ້ໃຊ້ ຫຼື ສະຄຣິບຂອງ LibreOffice. ໃນທຳນອງດຽວກັນ, ໄລບຣາຣີ ຫຼື ໂມດູນ Python ທີ່ອີງໃສ່ເອກະສານ ສາມາດໂຫຼດ ແລະ ປ່ອຍອອກໄດ້ໂດຍໃຊ້ເຫດການ ເປີດເອກະສານ ແລະ ປິດເອກະສານ. ເບິ່ງຂໍ້ມູນເພີ່ມເຕີມໄດ້ທີ່ ການນຳເຂົ້າໂມດູນ Python.

### ດ້ວຍ LibreOffice Basic

ໂດຍການໃຊ້ແຖບ ເຫດການ ໃນເມນູ ເຄື່ອງມື - ປັບແຕ່ງ, ເຫດການ ເປີດເອກະສານ ຈະກະຕຸ້ນການເລີ່ມຕົ້ນຂອງ ConsoleLogger. ຣູທິນ _documentEventOccured ທີ່ຕັ້ງໂດຍ ConsoleLogger ຈະເຮັດໜ້າທີ່ເປັນຈຸດເຂົ້າດຽວເພື່ອດັກຈັບທຸກເຫດການຂອງເອກະສານ.

#### ໂມດູນ controller.Events

            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

#### ໂມດູນຄລາສ controller.ConsoleLogger

ການຕິດຕາມເຫດການເລີ່ມຕົ້ນເມື່ອອອບເຈັກ 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 ແມ່ນສະກົດຜິດ ເຊິ່ງເປັນການສືບທອດຂໍ້ຜິດພາດມາຈາກ API ຂອງ LibreOffice.

## ການຄົ້ນຫາເຫດການຂອງເອກະສານ

ອອບເຈັກ API broadcaster ຈະໃຫ້ລາຍການເຫດການທີ່ມັນມີໜ້າທີ່ຮັບຜິດຊອບ:

### ດ້ວຍ 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,)

ສ່ວນຂະຫຍາຍ Alternative Python Script Organizer (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

ຫົວຂໍ້ທີ່ກ່ຽວຂ້ອງ

ການສ້າງຕົວຮັບຟັງເຫດການ

ການນຳເຂົ້າໂມດູນ Python

ການສ້າງ Dialog Handler

ຕົວຢ່າງການຂຽນໂປຣແກຣມ Python

ການຂຽນໂປຣແກຣມດ້ວຍສະຄຣິບ Python

ການເອີ້ນໃຊ້ແມັກໂຄຣ Basic ຈາກ Python

ກະລຸນາສະໜັບສະໜູນພວກເຮົາ!