Calc(30)コンテクストメニューをカスタマイズする: その3

公開日: 2017年10月22日 更新日: 2019年05月11日

旧ブログ

t f B! P L
入れ子のコンテクストメニューを作成できることを確認しました。さらに、ドキュメントに埋め込んだマクロをドキュメントに埋め込んだマクロで作成したコンテクストメニューの項目から呼び出すCalcドキュメント作成しました。

前の関連記事:Calc(29)コンテクストメニューをカスタマイズする: その2


コンテクストメニューを入れ子にする

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
# -*- coding: utf-8 -*-
import unohelper  # オートメーションには必須(必須なのはuno)。
from com.sun.star.ui import XContextMenuInterceptor
from com.sun.star.ui import ActionTriggerSeparatorType  # 定数
from com.sun.star.ui.ContextMenuInterceptorAction import EXECUTE_MODIFIED  # enum
def macro(): 
    doc = XSCRIPTCONTEXT.getDocument()  # ドキュメントのモデルを取得。
    controller = doc.getCurrentController()  # コントローラーを取得。
    contextmenuinterceptor = ContextMenuInterceptor()
    controller.registerContextMenuInterceptor(contextmenuinterceptor)
class ContextMenuInterceptor(unohelper.Base, XContextMenuInterceptor):
    def notifyContextMenuExecute(self, contextmenuexecuteevent):
        contextmenu = contextmenuexecuteevent.ActionTriggerContainer
        submenucontainer2 = contextmenu.createInstance("com.sun.star.ui.ActionTriggerContainer")
        addMenuentry(submenucontainer2, "ActionTrigger", 0, {"Text": "Content2", "CommandURL": ".uno:HelpIndex", "HelpURL": "5401"})
        addMenuentry(submenucontainer2, "ActionTrigger", 1, {"Text": "Tips2", "CommandURL": ".uno:HelpTip", "HelpURL": "5404"})
        submenucontainer1 = contextmenu.createInstance("com.sun.star.ui.ActionTriggerContainer")
        addMenuentry(submenucontainer1, "ActionTrigger", 0, {"Text": "Help2", "CommandURL": ".uno:HelpMenu", "HelpURL": "5410", "SubContainer": submenucontainer2}) 
        addMenuentry(submenucontainer1, "ActionTrigger", 1, {"Text": "Content1", "CommandURL": ".uno:HelpIndex", "HelpURL": "5401"})
        addMenuentry(submenucontainer1, "ActionTrigger", 2, {"Text": "Tips1", "CommandURL": ".uno:HelpTip", "HelpURL": "5404"}) 
        addMenuentry(contextmenu, "ActionTrigger", 0, {"Text": "Help", "CommandURL": ".uno:HelpMenu", "HelpURL": "5410", "SubContainer": submenucontainer1})
        addMenuentry(contextmenu, "ActionTriggerSeparator", 1, {"SeparatorType": ActionTriggerSeparatorType.LINE})
        return EXECUTE_MODIFIED
def addMenuentry(menucontainer, menutype, i, props):  # i: index, propsは辞書。menutypeはActionTriggerかActionTriggerSeparator。
    menuentry = menucontainer.createInstance("com.sun.star.ui.{}".format(menutype))  # ActionTriggerContainerからインスタンス化する。
    [menuentry.setPropertyValue(key, val) for key, val in props.items()]  #setPropertyValuesでは設定できない。エラーも出ない。
    menucontainer.insertByIndex(i, menuentry)  # submenucontainer[i]やsubmenucontainer[i:i]は不可。挿入以降のメニューコンテナの項目のインデックスは1増える。
g_exportedScripts = macro, #マクロセレクターに限定表示させる関数をタプルで指定。
これで入れ子ができました。


コンテクストメニューからマイマクロフォルダのマクロを呼び出す


マクロをCommandURLで指定するためのURLの書き方はOOoBasic/Generic/ScriptingURL - ...?で解説されています。

マクロのURLはScriptingURLと呼ぶようです。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# -*- coding: utf-8 -*-
def macro():
    doc = XSCRIPTCONTEXT.getDocument()  # ドキュメントを取得。
    sheets = doc.getSheets()  # シートコレクション。
    sheet = sheets[0# 最初のシート。
    sheet[0, 0].clearContents(511# A1セルのすべてを削除。
    selection = doc.getCurrentSelection()  # 選択しているオブジェクトを取得。
    stringaddress = getRangeAddressesAsString(selection)  # セル範囲の文字列アドレスを取得。
    sheet[0, 0].setString("Selection: {}".format(stringaddress))  # A1セルに選択範囲のアドレスを出力。
    sheet[:, 0].getColumns().setPropertyValue("OptimalWidth", True# 列幅を最適化する。
g_exportedScripts = macro, #マクロセレクターに限定表示させる関数をタプルで指定。
def getRangeAddressesAsString(rng):  # セルまたはセル範囲、セル範囲コレクションから文字列アドレスを返す。
    absolutename = rng.getPropertyValue("AbsoluteName") # セル範囲コレクションは$Sheet1.$A$4:$A$6,$Sheet1.$B$4という形式で返る。
    names = absolutename.replace("$", "").split(",")  # $を削除してセル範囲のリストにする。
    addresses = []  # 出力するアドレスを入れるリスト。
    for name in names:  # 各セル範囲について
        addresses.append(name.split(".")[-1])  # シート名を削除する。
    return ", ".join(addresses)  # コンマでつなげて出力。
選択範囲の文字列アドレスをA1セルに出力するこのマクロをコンテクストメニューから呼び出すことにします。

マクロのコマンドURLは自分で考えなくてもCalc(26)シートイベントにマクロを登録してダブルクリックで起動するでやったようにマクロをシートイベントに登録してドキュメントに保存してドキュメント内のcontent.xmlのノードをvnd.sun.star.scriptで検索して探すとそのマクロのScriptingURLが取得できます(但し&を&にする必要がありました)。

vnd.sun.star.script:SpreadSheetExample|SpreadSheetExample|src|etc|calcmacro.py$macro?language=Python&location=user

今回のマクロのScriptingURLはこのようになっていました。

マイマクロフォルダ(~/.config/libreoffice/4/user/Scripts/python/)からの相対パスを|で区切りでpyファイルを指定していました。

このScriptingURLをCommandURLプロパティに指定するとコンテクストメニューからマクロを実行できました。

これでマイマクロのマクロをコンテクストメニューで実行する方法がわかりました

コンテクストメニューから埋め込みマクロを呼び出す


今度は埋め込みマクロをコンテクストメニューから呼び出してみます。

先ほどのマクロファイルmacro.pyをAPSOでCalcドキュメントに埋め込みました。

適当なイベントにマクロを割り当ててマクロのコマンドURLを調べました。

vnd.sun.star.script:calcmacro.py$macro?language=Python&location=document

location=documentすれば埋め込みマクロのScriptingURLになるようです。

Calc(28)コンテクストメニューをカスタマイズする: その1の「コンテクストメニューをカスタマイズするマクロをドキュメントに埋め込む」のマクロの方法で上の「コンテクストメニューを入れ子にする」マクロをドキュメントを開くときに実行するようにして、そのコンテクストメニューでそのドキュメントに埋め込んだcalcmacro.pyのマクロを実行できるようにしました。

CalcExamples - p--qのcontextmenuScriptingURL.odsがマクロを埋め込んだドキュメントになります。


これでWindowsでも動作確認できました。

LibreOffice5(87)Pythonマクロのための拡張機能APSOのインストールのAPSOは埋め込んだpyファイルを編集後に埋め込めるし、manifest.xmlファイルも勝手に編集してくれるのでとても便利です。

参考にしたサイト


OOoBasic/Generic/ScriptingURL - ...?
マクロのCommandURLの解説。

次の関連記事:Calc(31)セルへ日付を入力する方法

ブログ検索 by Blogger

Translate

Created by Calendar Gadget

QooQ