LibreOffice(44)UNOオブジェクトの属性3:Writerドキュメントに出力

ラベル: ,

前の関連記事:LibreOffice(43)UNOオブジェクトの属性2:メッセージボックスに表示


汎用化を進めるために対象とするUNOオブジェクトを引数にした関数にして、さらに結果をWriterに出力します。

UNOオブジェクトを引数とする一つの関数にしてWriterに出力

import re
def obj_atr(obj):
    match = re.findall(r"\((.+?)\)|(\w+?)=({)?([^}]+?)(?(3)}|,)", str(obj))
    output = list()
    for i in match:
        if i[0]:
            list1 = ["継承している型", "\t"+i[0]]
        else:
            dic = {"implementationName": "実装名", "supportedServices": "使えるサービス", "supportedInterfaces": "使えるインターフェイス"}
            atr0 = "".join([dic[i[1]], "(", i[1], ")"])
            if "," in i[3]:
                list0 = i[3].split(",")
                list0.sort()
                list1 = [atr0]
                list1.extend(["".join(["\t", j]) for j in list0])
            else:
                list1 = [atr0, "\t"+i[3]]
        list1.append("")
        output.extend(list1)
    win = XSCRIPTCONTEXT.getDesktop().getCurrentFrame().getContainerWindow()
    win.getToolkit().createMessageBox(win, "MESSAGEBOX", 1, "オブジェクトの属性", "\n".join(output)).execute()
メッセージボックスを表示する関数も含めてすべて一つの関数にまとめてしまいました。
def libreoffice44():
    obj = XSCRIPTCONTEXT.getDocument()
    obj_atr(obj)
これで呼び出します。

ところがドキュメントオブジェクトなどは属性が多くてメッセージボックスでははみ出て全部が見えません。

そこでWriterのドキュメントに結果を書き込めるようにします。
def obj_atr(obj, flags=0):
    import re  # 正規表現モジュールをインポート。
    match = re.findall(r"\((.+?)\)|(\w+?)=({)?([^}]+?)(?(3)}|,)", str(obj))
    output = list()
    for i in match:
        if i[0]:
            list1 = ["継承している型", "\t"+i[0]]
        else:
            dic = {"implementationName": "実装名", "supportedServices": "使えるサービス", "supportedInterfaces": "使えるインターフェイス"}
            atr0 = "".join([dic[i[1]], "(", i[1], ")"])
            if "," in i[3]:
                list0 = i[3].split(",")
                list0.sort()
                list1 = [atr0]
                list1.extend(["".join(["\t", j]) for j in list0])
            else:
                list1 = [atr0, "\t"+i[3]]
        list1.append("")
        output.extend(list1)
    txt = "\n".join(output)
    desktop = XSCRIPTCONTEXT.getDesktop()
    if flags == 1:  # フラグが1のときメッセージボックスに表示。
        win = desktop.getCurrentFrame().getContainerWindow()
        win.getToolkit().createMessageBox(win, "MESSAGEBOX", 1, "オブジェクトの属性", txt).execute()
    else:  # フラグが1以外のときWriterドキュメントに出力。
        doc1 = desktop.loadComponentFromURL("private:factory/swriter", "_blank", 0, ())  # 新規Writerドキュメントを作成。
        doc1.getText().setString(txt)  # Writerドキュメントに出力。
        doc1.getCurrentController().getViewCursor().jumpToFirstPage()  # 見えている範囲を先頭に移動する。
26行目で新規Writerドキュメントを開いています。

LibreOffice(38)埋め込みマクロ1:セキュリティレベルを変更して開くで使ったloadComponentFromURL()を使っています。

URLをprivate:factory/swriterにすると新規Writerドキュメント、private:factory/scalctとすると新規Calcドキュメントが開きます。(URL パラメータ URL Parameter
        doc1.getText().setString(txt)  # Writerドキュメントに出力。
新しく開いたWriterドキュメントのテキスト全体をgetText()で取得してそれにsetString()で文字列をWriterドキュメントへ出力しています。

28行目で属性を出力したドキュメントのページの先頭に移動しています。

複数のサービスをもっているオブジェクトではインターフェイスが重複している



Writerドキュメントに対して上記のlibreoffice44()を実行すると新しいWriterのドキュメントが開いてそこに属性が出力されます。

よくみるとcom.sun.star.lang.XTypeProviderが3つ、com.sun.star.lang.XUnoTunnelが2つなど重複しているインターフェイスがあることに気づきます。

これは使えるサービスが3つありそれぞれがもっているインターフェイスが重複していると思われます。

リストから重複要素を削除する - Keep it in the fridgeを参考にリストを一旦集合型に変換してからリストに再度変換します。
def obj_atr(obj, flags=0):
    import re
    match = re.findall(r"\((.+?)\)|(\w+?)=({)?([^}]+?)(?(3)}|,)", str(obj))
    output = list()
    for i in match:
        if i[0]:
            list1 = ["継承している型", "\t"+i[0]]
        else:
            dic = {"implementationName": "実装名", "supportedServices": "使えるサービス", "supportedInterfaces": "使えるインターフェイス"}
            atr0 = "".join([dic[i[1]], "(", i[1], ")"])
            if "," in i[3]:
                list0 = list(set(i[3].split(",")))
                list0.sort()
                list1 = [atr0]
                list1.extend(["".join(["\t", j]) for j in list0])
            else:
                list1 = [atr0, "\t"+i[3]]
        list1.append("")
        output.extend(list1)
    txt = "\n".join(output)
    desktop = XSCRIPTCONTEXT.getDesktop()
    if flags == 1:
        win = desktop.getCurrentFrame().getContainerWindow()
        win.getToolkit().createMessageBox(win, "MESSAGEBOX", 1, "オブジェクトの属性", txt).execute()
    else:
        doc1 = desktop.loadComponentFromURL("private:factory/swriter", "_blank", 0, ())
        doc1.getText().setString(txt)
        doc1.getCurrentController().getViewCursor().jumpToFirstPage()
12行目で重複要素を削除しています。
def obj_atr(obj, flags=0):
    import re
    match = re.findall(r"\((.+?)\)|(\w+?)=({)?([^}]+?)(?(3)}|,)", str(obj))
    output = list()
    dic = dict(implementationName="実装名(implementationName)",
               supportedServices="使えるサービス(supportedServices)",
               supportedInterfaces="使えるインターフェイス(supportedInterfaces)")
    for i in match:
        if i[0]:
            list1 = ["継承している型", "\t"+i[0]]
        else:
            if "," in i[3]:
                list0 = list(set(i[3].split(",")))
                list0.sort()
                list1 = [dic[i[1]]]
                list1.extend(["".join(["\t", j]) for j in list0])
            else:
                list1 = [dic[i[1]], "\t"+i[3]]
        list1.append("")
        output.extend(list1)
    txt = "\n".join(output)
    desktop = XSCRIPTCONTEXT.getDesktop()
    if flags == 1:
        win = desktop.getCurrentFrame().getContainerWindow()
        win.getToolkit().createMessageBox(win, "MESSAGEBOX", 1, "オブジェクトの属性", txt).execute()
    else:
        doc1 = desktop.loadComponentFromURL("private:factory/swriter", "_blank", 0, ())
        doc1.getText().setString(txt)
        doc1.getCurrentController().getViewCursor().jumpToFirstPage()

5.5. 辞書を読んで辞書定義の部分を変更しました。

さらに辞書定義をfor内でするのは非効率なのでforの外に出しました。

参考にしたサイト


Apache OpenOffice Developer's Guide - Apache OpenOffice Wiki
PDF版の表紙にOpenOffice.org 3.1 Developer's Guideと書いてあります。

Developer's Guide
OpenOffice Developer's Guideの日本語版。OpenOffice.org 2.0より前のもののようです。

LibreOffice: Namespace List
LibreOffice 4.2 SDK APIの入り口com.sun.star。

OOoBasic/Writer/ViewCursor - ...?
Writerドキュメントのページの移動方法。

リストから重複要素を削除する - Keep it in the fridge
Pythonのリストから重複要素を削除する方法。

4.9. 集合型 — set, frozenset
リストを一旦集合型に変換することで重複要素を削除できます。

5.5. 辞書
dict() コンストラクタを使いました。

次の関連記事:LibreOffice(45)APIリファレンス、LibreOffice 4.2 SDK APIをたどる

PR

4 件のコメント:

  1. 慣れてきてオブジェクトの情報を得たくなったら、インスペクタを試してみるといいかもしれません。
    http://extensions.openoffice.org/en/project/mri-uno-object-inspection-tool

    返信削除
    返信
    1. 情報ありがとうございます。
      このインスペクタはLibreOffice4.2でも使えているでしょうか?
      サポートしているのがApach OpenOfficeが4.0とそれ以降、LibreOfficeは3.5まで、Pythonは2.6まで、と書いてあるので、はなから動かないと思い込んで試していませんでした。
      GitHubのReadMeにはLibreOfficeへの言及すらないです。
      私の環境はLibreOffice4.2.2.1、Python3.3.3になります。

      削除
    2. 1.2.0 以降であれば Python3 系でも動作します。LO 4.2.3 でも動くようです。

      削除
    3. ありがとうございます。
      早速使ってみたいと思います。

      削除