Calc(52)追加できるリスナー一覧: その4

公開日: 2017年12月30日 更新日: 2019年05月11日

旧ブログ

t f B! P L
リスナーがどのタイミングで発火するのかよくわからなかったので、Calc(51)追加できるリスナー一覧: その3の各リスナーのメソッドについて発火したらログファイルを出力するマクロを作成しました。
(2018.1.3追記Calc(52)追加できるリスナー一覧: その4で作り直しました。)

前の関連記事:Calc(51)追加できるリスナー一覧: その3


リスナーのメソッドが発火したらログファイルを出力するマクロ


このマクロを起動したらその後リスナーのメソッドが発火するたびにこのマクロファイルがあるフォルダにログファイルを出力します。

埋め込みマクロをにしているときは埋め込んだドキュメントのフォルダに出力します。

20171230T113317_88doc_documenteventlistener_documentEventOccured_OnTitleChanged.log

マクロファイルの起動年月日T時分秒_発火順リスナーが追加されているオブジェクト_リスナー名_発火メソッド名_イベント名など.log

ログファイル名はこのようになっています。

発火順は桁揃えが面倒なので10番から始まるようにしています。

最後の要素の「イベント名など」はenum名やイベント名などリスナーの種類によってあったりなかったりします。

ログファイル内に書き出している内容はリスナーによってそれぞれです。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
#!/opt/libreoffice5.4/program/python
# -*- coding: utf-8 -*-
import unohelper  # オートメーションには必須(必須なのはuno)。
import os
import inspect
from datetime import datetime
from com.sun.star.awt import XEnhancedMouseClickHandler
from com.sun.star.awt import XKeyHandler
from com.sun.star.view import XSelectionChangeListener
from com.sun.star.view import XPrintJobListener
from com.sun.star.view.PrintableState import JOB_STARTED, JOB_COMPLETED, JOB_SPOOLED, JOB_ABORTED, JOB_FAILED, JOB_SPOOLING_FAILED  # enum
from com.sun.star.util import XCloseListener
from com.sun.star.util import XModifyListener
from com.sun.star.util import XChangesListener
from com.sun.star.frame import XTerminateListener
from com.sun.star.frame import XFrameActionListener
from com.sun.star.frame import XTitleChangeListener
from com.sun.star.frame import XBorderResizeListener
from com.sun.star.frame.FrameAction import COMPONENT_ATTACHED, COMPONENT_DETACHING, COMPONENT_REATTACHED, FRAME_ACTIVATED, FRAME_DEACTIVATING, CONTEXT_CHANGED, FRAME_UI_ACTIVATED, FRAME_UI_DEACTIVATING  # enum
from com.sun.star.document import XDocumentEventListener
from com.sun.star.document import XEventListener
from com.sun.star.document import XStorageChangeListener
from com.sun.star.sheet import XActivationEventListener
from com.sun.star.chart import XChartDataChangeEventListener
from com.sun.star.chart.ChartDataChangeType import ALL, DATA_RANGE, COLUMN_INSERTED, ROW_INSERTED, COLUMN_DELETED, ROW_DELETED  # enum
def macro(documentevent=None):  # 引数は文書のイベント駆動用。OnStartAppでもDocumentEventが入るがSourceはNoneになる。# import pydevd; pydevd.settrace(stdoutToServer=True, stderrToServer=True)  # デバッグサーバーを起動していた場合はここでブレークされる。import pydevdは時間がかかる。
    doc = XSCRIPTCONTEXT.getDocument() if documentevent is None else documentevent.Source  # ドキュメントのモデルを取得。
    path = doc.getURL() if __file__.startswith("vnd.sun.star.tdoc:") else __file__  # このスクリプトのパス。fileurlで返ってくる。埋め込みマクロの時は埋め込んだドキュメントのURLで代用する。
    thisscriptpath = unohelper.fileUrlToSystemPath(path)  # fileurlをsystempathに変換。
    dirpath = os.path.dirname(thisscriptpath)  # このスクリプトのあるディレクトリのフルパスを取得。
    desktop = XSCRIPTCONTEXT.getDesktop()  # デスクトップの取得。
    desktop.addTerminateListener(TerminateListener(dirpath, "desktop_terminatelistener"))  # TerminateListenerは使い終わったらremoveしないと問題が起こる。
    desktop.addFrameActionListener(FrameActionListener(dirpath, "desktop_frameactionlistener"))  # FrameActionListener
    controller = doc.getCurrentController()  # コントローラーの取得。
    frame = controller.getFrame()  # フレームの取得。
    frame.addFrameActionListener(FrameActionListener(dirpath, "frame_frameactionlistener"))  # FrameActionListener
    frame.addCloseListener(CloseListener(dirpath, "frame_closelistener"))  # CloseListener
    frame.addTitleChangeListener(TitleChangeListener(dirpath, "frame_titlechangelistener"))  # TitleChangeListener
    controller.addActivationEventListener(ActivationEventListener(dirpath, "controller_activationeventlistener"))  # ActivationEventListener
    controller.addEnhancedMouseClickHandler(EnhancedMouseClickHandler(dirpath, "controller_enhancedmouseclickhandler"))  # EnhancedMouseClickHandler
    controller.addSelectionChangeListener(SelectionChangeListener(dirpath, "controller_selectionchangelistener"))  # SelectionChangeListener
    controller.addBorderResizeListener(BorderResizeListener(dirpath, "controller_borderresizelistener"))  # BorderResizeListener
    controller.addTitleChangeListener(TitleChangeListener(dirpath, "controller_titlechangelistener"))  # TitleChangeListener
    controller.addKeyHandler(KeyHandler(dirpath, "controller_keyhandler"))  # KeyHandler 
    doc.addDocumentEventListener(DocumentEventListener(dirpath, "doc_documenteventlistener"))  # DocumentEventListener
    doc.addEventListener(EventListener(dirpath, "doc_eventlistener"))  # EventListener
    doc.addModifyListener(ModifyListener(dirpath, "doc_modifylistener"))  # ModifyListener 
    doc.addPrintJobListener(PrintJobListener(dirpath, "doc_printjoblistener"))  # PrintJobListener
    doc.addStorageChangeListener(StorageChangeListener(dirpath, "doc_storagechangelistener"))  # StorageChangeListener
    doc.addTitleChangeListener(TitleChangeListener(dirpath, "doc_titlechangelistener"))  # TitleChangeListener
    doc.addChangesListener(ChangesListener(dirpath, "doc_changelistener"))  # ChangesListener
    sheet = controller.getActiveSheet()  # アクティブシートを取得。
    sheet.addChartDataChangeEventListener(ChartDataChangeEventListener(dirpath, "sheet_chartdatachangeeventlistener"))  # ChartDataChangeEventListener
    sheet.addModifyListener(ModifyListener(dirpath, "sheet_modifylistener"))  # ModifyListener
    cell = sheet["A1"# セルの取得。
    cell.addChartDataChangeEventListener(ChartDataChangeEventListener(dirpath, "cell_chartdatachangeeventlistener"))  # ChartDataChangeEventListener 
    cell.addModifyListener(ModifyListener(dirpath, "cell_modifylistener"))  # ModifyListener
    cells = sheet["A2:C4"# セル範囲の取得。
    cells.addChartDataChangeEventListener(ChartDataChangeEventListener(dirpath, "cells_chartdatachangeeventlistener"))  # ChartDataChangeEventListener
    cells.addModifyListener(ModifyListener(dirpath, "cells_modifylistener"))  # ModifyListener
class ChartDataChangeEventListener(unohelper.Base, XChartDataChangeEventListener):
    def __init__(self, dirpath, name):
        self.args = dirpath, name
        enums = ALL, DATA_RANGE, COLUMN_INSERTED, ROW_INSERTED, COLUMN_DELETED, ROW_DELETED  # enum
        chartdatachangetypenames = "ALL", "DATA_RANGE", "COLUMN_INSERTED", "ROW_INSERTED", "COLUMN_DELETED", "ROW_DELETED"
        self.args = dirpath, name, zip(enums, chartdatachangetypenames)
    def chartDataChanged(self, chartdatachangeevent):
        dirpath, name, chartdatachangetypes = self.args
        chartdatachangetype = chartdatachangeevent.Type
        methodname = "_".join((name, inspect.currentframe().f_code.co_name))
        for enum, chartdatachangetypename in chartdatachangetypes:
            if chartdatachangetype==enum:
                methodname = "_".join((name, inspect.currentframe().f_code.co_name, chartdatachangetypename))  # ChartDataChangeType名を追加。
                createLog(dirpath, methodname, "ChartDataChangeType: {}".format(chartdatachangetypename))
                return
    def disposing(self, eventobject):
        pass 
class ChangesListener(unohelper.Base, XChangesListener):
    def __init__(self, dirpath, name):
        self.args = dirpath, name
    def changesOccurred(self, changesevent):
        dirpath, name = self.args
        methodname = "_".join((name, inspect.currentframe().f_code.co_name))
        createLog(dirpath, methodname, "Changes: {}".format(changesevent.Changes))
    def disposing(self, eventobject):
        pass 
class StorageChangeListener(unohelper.Base, XStorageChangeListener):
    def __init__(self, dirpath, name):
        self.args = dirpath, name
    def notifyStorageChange(self, document, storage):
        dirpath, name = self.args
        methodname = "_".join((name, inspect.currentframe().f_code.co_name))
        createLog(dirpath, methodname, "Storage: {}".format(storage))
    def disposing(self, eventobject):
        pass  
class PrintJobListener(unohelper.Base, XPrintJobListener):
    def __init__(self, dirpath, name):
        self.args = dirpath, name
        enums = JOB_STARTED, JOB_COMPLETED, JOB_SPOOLED, JOB_ABORTED, JOB_FAILED, JOB_SPOOLING_FAILED  # enum
        printablestatenames = "JOB_STARTED", "JOB_COMPLETED", "JOB_SPOOLED", "JOB_ABORTED", "JOB_FAILED", "JOB_SPOOLING_FAILED"
        self.args = dirpath, name, zip(enums, printablestatenames)
    def printJobEvent(self, printjobevent):
        dirpath, name, printablestates = self.args
        printablestate = printjobevent.State
        methodname = "_".join((name, inspect.currentframe().f_code.co_name))
        for enum, printablestatename in printablestates:
            if printablestate==enum:
                methodname = "_".join((name, inspect.currentframe().f_code.co_name, printablestatename))  # State名も追加。
                createLog(dirpath, methodname, "PrintableState: {}, Source: {}".format(printablestatename, printjobevent.Source))
                return
    def disposing(self, eventobject):
        pass 
class ModifyListener(unohelper.Base, XModifyListener):
    def __init__(self, dirpath, name):
        self.args = dirpath, name
    def modified(self, eventobject):
        dirpath, name = self.args
        methodname = "_".join((name, inspect.currentframe().f_code.co_name))
        createLog(dirpath, methodname, "Source: {}".format(eventobject.Source))
    def disposing(self, eventobject):
        pass 
class EventListener(unohelper.Base, XEventListener):
    def __init__(self, dirpath, name):
        self.args = dirpath, name
    def notifyEvent(self, eventobject):
        dirpath, name = self.args
        methodname = "_".join((name, inspect.currentframe().f_code.co_name, eventobject.EventName))  # イベント名も追加。
        createLog(dirpath, methodname, "EventName: {}, Source: {}".format(eventobject.EventName, eventobject.Source))
    def disposing(self, eventobject):
        pass 
class DocumentEventListener(unohelper.Base, XDocumentEventListener):
    def __init__(self, dirpath, name):
        self.args = dirpath, name
    def documentEventOccured(self, documentevent):
        dirpath, name = self.args
        methodname = "_".join((name, inspect.currentframe().f_code.co_name, documentevent.EventName))  # イベント名も追加。
        createLog(dirpath, methodname, "EventName: {}, Source: {}".format(documentevent.EventName, documentevent.Source))
    def disposing(self, eventobject):
        pass
class KeyHandler(unohelper.Base, XKeyHandler):
    def __init__(self, dirpath, name):
        self.args = dirpath, name
    def keyPressed(self, keyevent):
        dirpath, name = self.args
        methodname = "_".join((name, inspect.currentframe().f_code.co_name))
        createLog(dirpath, methodname, "KeyCode: {}, KeyChar: {}, KeyFunc: {}, Modifiers: {}".format(keyevent.KeyCode, keyevent.KeyChar, keyevent.KeyFunc, keyevent.Modifiers)) 
        return False
    def keyReleased(self, keyevent):
        dirpath, name = self.args
        methodname = "_".join((name, inspect.currentframe().f_code.co_name))
        createLog(dirpath, methodname, "KeyCode: {}, KeyChar: {}, KeyFunc: {}, Modifiers: {}".format(keyevent.KeyCode, keyevent.KeyChar, keyevent.KeyFunc, keyevent.Modifiers)) 
        return False 
    def disposing(self, eventobject):
        pass  
class BorderResizeListener(unohelper.Base, XBorderResizeListener):
    def __init__(self, dirpath, name):
        self.args = dirpath, name
    def borderWidthsChanged(self, obj, borderwidths):
        dirpath, name = self.args
        methodname = "_".join((name, inspect.currentframe().f_code.co_name))
        createLog(dirpath, methodname, "Top: {}, Left: {}, Right: {}, Bottom: {}, Object: {}".format(borderwidths.Top, borderwidths.Left, borderwidths.Right, borderwidths.Bottom, obj))
    def disposing(self, eventobject):
        pass 
class SelectionChangeListener(unohelper.Base, XSelectionChangeListener):
    def __init__(self, dirpath, name):
        self.args = dirpath, name
    def selectionChanged(self, eventobject):
        dirpath, name = self.args
        methodname = "_".join((name, inspect.currentframe().f_code.co_name))
        source = eventobject.Source
        txt = "Selection: {}".format(source.getSelection()) if source.supportsService("com.sun.star.sheet.SpreadsheetView") else "Source: {}".format(source)  # sourceがコントローラーのときは選択しているオブジェクトを書き出す。
        createLog(dirpath, methodname, txt)
    def disposing(self, eventobject):
        pass
class EnhancedMouseClickHandler(unohelper.Base, XEnhancedMouseClickHandler):
    def __init__(self, dirpath, name):
        self.args = dirpath, name
    def mousePressed(self, enhancedmouseevent):
        dirpath, name = self.args
        methodname = "_".join((name, inspect.currentframe().f_code.co_name))
        createLog(dirpath, methodname, "Buttons: {}, ClickCount: {}, PopupTrigger {}, Modifiers: {}, Target: {}".format(enhancedmouseevent.Buttons, enhancedmouseevent.ClickCount, enhancedmouseevent.PopupTrigger, enhancedmouseevent.Modifiers, enhancedmouseevent.Target))
        return True
    def mouseReleased(self, enhancedmouseevent):
        dirpath, name = self.args
        methodname = "_".join((name, inspect.currentframe().f_code.co_name))
        createLog(dirpath, methodname, "Buttons: {}, ClickCount: {}, PopupTrigger {}, Modifiers: {}, Target: {}".format(enhancedmouseevent.Buttons, enhancedmouseevent.ClickCount, enhancedmouseevent.PopupTrigger, enhancedmouseevent.Modifiers, enhancedmouseevent.Target))
        return True
    def disposing(self, eventobject):
        pass
class ActivationEventListener(unohelper.Base, XActivationEventListener):
    def __init__(self, dirpath, name):
        self.args = dirpath, name
    def activeSpreadsheetChanged(self, activationevent):
        dirpath, name = self.args
        methodname = "_".join((name, inspect.currentframe().f_code.co_name))
        source = activationevent.Source
        txt = "Selection: {}".format(source.getSelection()) if source.supportsService("com.sun.star.sheet.SpreadsheetView") else "Source: {}".format(source)  # sourceがコントローラーのときは選択しているオブジェクトを書き出す。
        createLog(dirpath, methodname, txt)
    def disposing(self, eventobject):
        pass
class TitleChangeListener(unohelper.Base, XTitleChangeListener):
    def __init__(self, dirpath, name):
        self.args = dirpath, name
    def titleChanged(self, titlechangedevent):
        dirpath, name = self.args
        methodname = "_".join((name, inspect.currentframe().f_code.co_name))
        createLog(dirpath, methodname, "Title: {}, Source: {}".format(titlechangedevent.Title, titlechangedevent.Source))
    def disposing(self, eventobject):
        pass
class CloseListener(unohelper.Base, XCloseListener):
    def __init__(self, dirpath, name):
        self.args = dirpath, name
    def queryClosing(self, eventobject, getsownership):
        dirpath, name = self.args
        methodname = "_".join((name, inspect.currentframe().f_code.co_name))
        createLog(dirpath, methodname, "getsownership: {}, Source: {}".format(getsownership, eventobject.Source))
    def notifyClosing(self, eventobject):
        dirpath, name = self.args
        methodname = "_".join((name, inspect.currentframe().f_code.co_name))
        createLog(dirpath, methodname, "Source: {}".format(eventobject.Source))
    def disposing(self, eventobject):
        pass
class FrameActionListener(unohelper.Base, XFrameActionListener):
    def __init__(self, dirpath, name):
        enums = COMPONENT_ATTACHED, COMPONENT_DETACHING, COMPONENT_REATTACHED, FRAME_ACTIVATED, FRAME_DEACTIVATING, CONTEXT_CHANGED, FRAME_UI_ACTIVATED, FRAME_UI_DEACTIVATING  # enum
        frameactionnames = "COMPONENT_ATTACHED", "COMPONENT_DETACHING", "COMPONENT_REATTACHED", "FRAME_ACTIVATED", "FRAME_DEACTIVATING", "CONTEXT_CHANGED", "FRAME_UI_ACTIVATED", "FRAME_UI_DEACTIVATING"
        self.args = dirpath, name, zip(enums, frameactionnames)
    def frameAction(self, frameactionevent):
        dirpath, name, frameactions = self.args
        frameaction = frameactionevent.Action
        for enum, frameactionname in frameactions:
            if frameaction==enum:
                methodname = "_".join((name, inspect.currentframe().f_code.co_name, frameactionname))  # Action名も追加。
                createLog(dirpath, methodname, "FrameAction: {}, Source: {}".format(frameactionname, frameactionevent.Source))
                return
    def disposing(self, eventobject):
        pass
class TerminateListener(unohelper.Base, XTerminateListener):  # TerminateListener
    def __init__(self, dirpath, name):  # 出力先ディレクトリのパス、リスナーのインスタンス名。
        self.args = dirpath, name
    def queryTermination(self, eventobject):
        dirpath, name = self.args
        methodname = "_".join((name, inspect.currentframe().f_code.co_name))  # このメソッド名を取得。メソッド内で実行する必要がある。
        createLog(dirpath, methodname, "Source: {}".format(eventobject.Source))  # Sourceを出力。
    def notifyTermination(self, eventobject):
        dirpath, name = self.args
        methodname = "_".join((name, inspect.currentframe().f_code.co_name))  # このメソッド名を取得。メソッド内で実行する必要がある。
        createLog(dirpath, methodname, "Source: {}".format(eventobject.Source))  # Sourceを出力。
        desktop = eventobject.Source
        desktop.removeTerminateListener(self# TerminateListenerを除去。除去しなmethodname = inspect.currentframe().f_code.co_nameいとLibreOfficeのプロセスが残って起動できなくなる。
    def disposing(self, eventobject):
        pass
C = 10  # カウンターの初期値。
TIMESTAMP = datetime.now().isoformat().split(".")[0].replace("-", "").replace(":", "")  # コピー先ファイル名に使う年月日T時分秒を結合した文字列を取得。
def createLog(dirpath, methodname, txt):  # 年月日T時分秒リスナーのインスタンス名_methodname.logファイルを作成。txtはファイルに書き込むテキスト。dirpathはファイルを書き出すディレクトリ。
    global C
    filename = "".join((TIMESTAMP, "_", str(C), methodname, ".log"))
    C += 1
    with open(os.path.join(dirpath, filename), "w") as f:
        f.write(txt)
g_exportedScripts = macro,  #マクロセレクターに限定表示させる関数をタプルで指定。
EnhancedMouseClickHandlerを使っているので、コントローラーに追加できるリスナーのうちXMouseClickHandlerは使っていません。

ListenersForCalc.ods
このマクロを埋め込んだCalcドキュメントです。

「文書を開いた時」に埋め込みマクロを起動するようにしています。

マクロを有効化してこのドキュメントを起動してドキュメントの操作をすると、リスナーが発火するたびにドキュメントがあるフォルダにログファイルが出力されます。

リスナーのメソッド内にエラーがあってもエラーメッセージウィンドウはでてこないので、発火していないのかどうかは慎重に判断する必要があります。

次の関連記事:Calc(53)追加できるリスナー一覧: その5

ブログ検索 by Blogger

Translate

«
Dec. 2017
»
Sun
Mon
Tue
Wed
Thu
Fri
Sat
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Created by Calendar Gadget

QooQ