Calc(2)課題2:選択範囲の行列番号をメッセージボックスに表示

ラベル: , ,

前の関連記事:Calc(1)課題1:LibreOffice CalcのPythonマクロを動かす


LibreOffice BasicではMsgBox 関数で簡単にできるものがPythonではちょっとひと手間です。

メッセージボックスの表示方法はLibreOffice4.1から4.2で変更あり


まずはLibreOffice(28)4.1.4.2から4.2.2.1にアップグレードする前の話です。

OOoBasic/Window/Dialogs - ...?の例を実行してみると以下のようなエラーがでてきました。

    dlg = message_box(toolkit,parent,"errorbox",1,"error","!!! error.")
NameError: global name 'toolkit' is not defined

関数の仕様でも変わったのかと思ったら #.... needs toolkit and window peer as parentとちゃんとコメントがありました。

toolkitとwindow peerというのは自分で設定しないといけないようです。

OOoPython/OverView - ...?

こちらに完全な例がありました。

課題1と同様にして(今後の課題でも同様にします。)実行すると以下のようなメッセージボックスを表示できました。


LibreOffice(28)4.1.4.2から4.2.2.1にアップグレードに書いたようにLibreOffice4.2ではcom.sun.star.awt.XMessageBoxFactoryのcreateMessageBoxの引数が変わっているのでそのまま実行すると__main__.IllegalArgumentException: incorrect number of parameters passed invoking function createMessageBoxというエラーがでてきて実行できません。
#kadai2.py
def kadai2():
    message("タイトル", "メッセージ")
def message(title="", msg=""):
    win = XSCRIPTCONTEXT.getDesktop().getCurrentFrame().getContainerWindow() #フレームのコンテナウィンドウを取得。
    toolkit = win.getToolkit() #ウィンドウピアオブジェクトからツールキットを取得。
    msgbox = toolkit.createMessageBox(win, "MESSAGEBOX", 1, title, msg)
    msgbox.execute()
このように変更して動くようになりました。

関数kadai2が実行するマクロになります。

関数messageはメッセージボックスに表示するタイトルとメッセージの2つを引数に受けるようにしています。
XMessageBox createMessageBox ( [in] com::sun::star::awt::XWindowPeer aParent,
                         [in] MessageBoxType                   eType,
                               [in] long                             nButtons,
                               [in] string                           sTitle,
                               [in] string                           sMessage
                             )  
createMessageBoxの5個の引数は、ウィンドウピアオブジェクト、メッセージボックスタイプ、ボタンタイプ、タイトル、メッセージ、です。

ウィンドウピアオブジェクトはLibreOffice(32)デベロッパーガイド4:コンポーネントフレームワークでみたようにフレームがもっているコンテナウィンドウやコンポーネントウィンドウになります。

5行目でXSCRIPTCONTEXTからデスクトップ、それからフレーム、それからコンテナウィンドウを取得しています。
    win = XSCRIPTCONTEXT.getDesktop().getCurrentFrame().getComponentWindow() #フレームのコンポーネントウィンドウを取得。
フレームがもつコンポーネントがコンポーネントウィンドウをもっているときはこのようにコンポーネントウィンドウからもウィンドウピアオブジェクトを取得できますが、必ずしも持っているわけではないのでコンテナウィンドウから取得したほうが無難でしょう。


XMessageBoxFactoryの継承図をみるとToolkitが継承していることがわかりますので6行目からツールキットをウィンドウピアオブジェクトから取得しています。

次の引数のメッセージボックスタイプはcom.sun.star.awt.MessageBoxTypeから選択します。

これはenum(列挙型)という名前の集合になります。

UNO Type mappingの例ではenumもconstantsもインポートしてから使用していますが、createMessageBoxメソッドの引数にはインポートしなくても使えました。

メソッドの引数にするときはインポートしなくてもよいのかもしれません。

そもそも列挙型と定数グループの違いがデベロッパーガイドを読んでもよくわかりませんでした。(Enum タイプと定数グループ Mapping of Enums and Constant Groups)

APIリファレンスの定義から推測すると、列挙型は単なる名前の列挙でそれぞれは変数ではないので計算不可能で、定数グループはそれぞれ型を持った変更不可能な変数(つまり計算可能)の集合、ということでしょうかね。

実際、以下にでてきる定数グループcom.sun.star.awt.MessageBoxButttonsでは計算してボタンをデフォルトボタンの組み合わせを設定しています。

まずは列挙型のcom.sun.star.awt.MessageBoxTypeを順番に試してみます。

MESSAGEBOX(アイコン無し)

INFOBOX(ヒントアイコン)

WARNINGBOX(感嘆符アイコン)

ERRORBOX(ストップアイコン)

QUERYBOX(疑問符アイコン)
アイコンが変わるということなんですね。

次の引数のボタンタイプは定数グループcom.sun.star.awt.MessageBoxButttonsから選択します。

対応する整数を指定します。

定数名でも指定できますが、その場合は例えば整数1に対応させるときは
from com.sun.star.awt.MessageBoxButtons import BUTTONS_OK
のようにインポートが必要で1の替わりに定数名BUTTONS_OKを指定します。
(BUTTONS_OKは変数(定数)であって文字列ではないので"BUTTONS_OK"とするとエラーになります。)

1(BUTTONS_OK)

2(BUTTONS_OK_CANCEL)

3(BUTTONS_YES_NO)

4(BUTTONS_YES_NO_CANCEL)

5(BUTTONS_RETRY_CANCEL)

6(BUTTONS_ABORT_IGNORE_RETRY)

上記以外の整数
青線で囲われているボタンがデフォルトで選択されているボタンです。

デフォルト選択ボタンを変更するには以下の数値を上記の整数に加えて指定します。

0x10000  OK

0x20000  キャンセル

0x30000  やり直し

0x40000  はい

0x50000  いいえ

0x60000  無視する

例えば0x60006(0x60000+6でもいけました)とすると「無視する」ボタンがデフォルトボタンになります。

#kadai2.py
def kadai2():
    message("タイトル", "メッセージ")
def message(title="", msg=""):
    win = XSCRIPTCONTEXT.getDesktop().getCurrentFrame().getContainerWindow()
    toolkit = win.getToolkit()
    msgbox = toolkit.createMessageBox(win, "MESSAGEBOX", 0x60006, title, msg)
    msgbox.execute()
メッセージのフォントを太字にするなど修飾したいと思ったのですがやり方がわかりませんでした。

HTMLタグではダメなようです。

選択範囲の左上右下セルの行列番号を得る方法


faq/5/422 - OpenOffice.org Q&Aに回答が載っています。

参考にさせていただいたのは、はにゃ?氏の回答1のPythonの部分です。
#kadai2.py
def kadai2():
    addr = XSCRIPTCONTEXT.getDocument().getCurrentSelection().getRangeAddress() #選択範囲のアドレスの取得。
    t = "選択範囲左上", addr.StartRow, addr.StartColumn, "選択範囲右下", addr.EndRow, addr.EndColumn #置換フィールドにいれる値のタプル。
    txt = "{} 行番号: {} 列番号: {}\n{} 行番号: {} 列番号: {}".format(*t) #書式指定文字列の置換フィールドにタプルをアンパックして置換する。
    message("セルのアドレス", txt) #メッセージボックスを表示。
def message(title="", msg=""):
    win = XSCRIPTCONTEXT.getDesktop().getCurrentFrame().getContainerWindow()
    toolkit = win.getToolkit()
    msgbox = toolkit.createMessageBox(win, "MESSAGEBOX", 1, title, msg)
    msgbox.execute()

Calcでは行列番号は0から始まります。

ですので例えばC4の行列番号は(3, 2)となります。

5行目でPythonの書式指定文字列を使っています。

参考にしたサイト


MsgBox 関数 [実行時] - LibreOffice Help
LibreOffice Basicでメッセージ表示用のダイアログボックスを表示する関数。

OOoBasic/Window/Dialogs - ...?
ダイアログの種類の解説があります。

OOoPython/OverView - ...?
メッセージボックスの表示方法。LibreOffice4.2.2.1では少し修正が必要です。

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

Enum タイプと定数グループ Mapping of Enums and Constant Groups
デベロッパーガイドの列挙型と定数グループの解説。

faq/5/422 - OpenOffice.org Q&A
アクティブセルアドレスの取得方法。

6.1. string — 一般的な文字列操作 — Python 3.3.3 ドキュメント
Pythonの文字列操作の解説。
PR

0 件のコメント:

コメントを投稿