<このシリーズの、前の記事 | このシリーズの目次 | このシリーズの、次の記事>
他の方法ではLibreOfficeまたはApache OpenOfficeの外からアクセスできない一部の機能を呼び出す方法を知る
これまで、UNO拡張機能からいくつかの機能を呼んできたが、すべての機能がUNO拡張機能やスタンドアロンのUNOプログラムから呼べるわけではない。
知っている。あるUNOオブジェクトに属する機能を呼ぶためには、そのUNOオブジェクトへの参照(厳密に言えば、そのUNOオブジェクトのUNOプロキシへの参照)を得なければならないが、その参照を得られるという保証はない。
我々は、以下のプロセスで、UNOオブジェクトへの参照を得ることができる。
コンポーネントコンテキストを得る。コンポーネントコンテキストに格納されたUNOオブジェクト(グローバルUNOサービスマネージャーはその一つ)を得る。グローバルUNOサービスマネージャーからUNOオブジェクトを得る。既にリファレンスを得ているUNOオブジェクトのメソッドの戻り値や出力引数としてUNOオブジェクトを得る。既にリファレンスを得ているUNOオブジェクトのプロパティとしてUNOオブジェクトを得る。
UNOオブジェクトは、戻りstruct値のメンバーや出力struct引数のメンバーなどとしても得られるが、それは言うまでもないだろう。
このプロセスで露出されないUNOオブジェクトは、LibreOfficeやApache OpenOfficeの外からはアクセスできない。
勿論。それに、機能は、UNOコンポーネントのメソッドとして実装されてすらいないかもしれない。
そう。LibreOfficeはほとんどがC++で実装されており、すべてのC++クラスがUNOコンポーネントだというわけではない。
したがって、呼びたいが呼べないという機能が一部あり得る。
しかし、一部の機能を呼べる別のメカニズムがあって、これが、ディスパッチメカニズムだ。
それはどんなものなのか?
あらかじめ定められたコマンド群があって、これらはそれぞれのURLによって識別され、それらのうちの1つを、そのURLとそのコマンドに特有のいくつかの引数を指定することで呼ぶことができる。
それらのコマンドは、すべて呼ぶことができるのか?
その保証はない。コマンドを呼ぶための引数として必要なUNOオブジェクトへのリファレンスを得られないかもしれないし、コマンドが正常に呼ばれるために満たされなければならない何らかの特別な条件があるかもしれない。
特別な条件?
例えば、コマンドを呼ぶ時に、あるダイアログウィンドウが開いていなければならないかもしれない。
ふーむ . . .
それはただ私が思いついた例というにすぎない。実際にはそんなケースはないかもしれない。
ははあ . . .
そうしたURLやその引数はどうすれば知ることができるのか?
それが問題だ。. . . それを包括的に説明する文書は私には見つけられなかった。
ふーむ。
今のところ、私の最良の方法は、LibreOfficeのソースコードを見ることだ。どこをどう見るべきなのかというのが次の問題だが、今はそれには立ち入らないことにする。
オーケー。
マクロを記録することで、コマンドを呼ぶ一部の例を見ることができるが、それらは、常に完全だとは言えない。
どのように不完全であり得るのか。
例えば、ドキュメントをPDFファイルとしてエクスポートする時、PDFファイルに署名することができるが、記録されたマクロはPDFファイルに署名しない。
それでは、一部の引数はただ省かれるのか?
または、一部の引数には値がセットされない。
なるほど。それで、実際には、どうすればコマンドを呼べるのか?
'com.sun.star.frame.DispatchHelper'というグローバルUNOサービスがあり、このUNOサービスのインスタンスをグローバルUNOサービスマネージャーから生成することができる。このインスタンスのUNOコンポーネントはUNOインターフェース、'com.sun.star.frame.XDispatchHelper'を実装しており、このUNOインターフェースには'executeDispatch'というメソッドがあり、このメソッドは、ディスパッチプロバイダ、コマンドURL、コマンド引数を受け取る。
ディスパッチプロバイダというのは何だ?
コマンドは神秘として実行されるわけではなく、ある実体が受け取って対処するが、私の理解では、この実体がディスパッチプロバイダだ。
ディスパッチプロバイダはどのように得られるのか?
それはもちろんコマンドによって違うが、今我々が関心を持つほとんどのケースでは、ドキュメントを格納しているフレームがディスパッチプロバイダだ。
そのフレームはどのように得られるのか?
フレームは、ドキュメントのコントローラーから、コントローラーが実装する'com.sun.star.frame.XController'UNOインターフェースを使って得られる。
なるほど。
結局、以下のサンプルコードを書いた。ここで、 'componentContext'は'com.sun.star.uno.XComponentContext'のコンポーネントコンテキスト(それをどのように得たかを知るには、この以前の記事を参照)、'l_currentSpreadSheetsDocumentModel'は'com.sun.star.frame.XModel'のスプレッドシートドキュメントUNOオブジェクト(それをどのように得たかを知るには、この以前の記事を参照)。
import com.sun.star.frame.XFrame;
import com.sun.star.frame.XController;
import com.sun.star.frame.XDispatchHelper;
import com.sun.star.frame.XDispatchProvider;
import com.sun.star.beans.PropertyValue;
XDispatchHelper l_dispatchHelperInXDispatchHelper = (XDispatchHelper) UnoRuntime.queryInterface (XDispatchHelper .class, componentContext.getServiceManager ().createInstanceWithContext ("com.sun.star.frame.DispatchHelper", componentContext));
XController l_controllerInXController = (XController) UnoRuntime.queryInterface (XController.class, l_currentSpreadSheetsDocumentModel.getCurrentController ());
l_frameInXDispatchProvider = (XDispatchProvider) UnoRuntime.queryInterface (XDispatchProvider.class, l_controllerInXController.getFrame ());
PropertyValue [] l_commandProperties = new PropertyValue [1];
l_commandProperties [0] = new PropertyValue ();
l_commandProperties [0].Name = "ToPoint";
l_commandProperties [0].Value = "$B$2";
l_dispatchHelperInXDispatchHelper.executeDispatch (l_frameInXDispatchProvider, ".uno:GoToCell", "", 0, l_commandProperties);
このコマンドは何だ?
これは、セルのカレント位置をB2セルに移動するコマンドだ。
それは、セルを選択するのとは違うのか?
違う、少なくとも、見た目の上で。セルが選択されたとき、セルには色がつくが、セルがただカレントのときはセルには色がつかない。
うーむ、それは微妙な違いだ。
それに、スプレッドシートドキュメントをPDFファイルとしてエクスポートするとき、選択されたセルは選択箇所として認識されるが、ただのカレントセルはそうではない。
「選択箇所として認識される」というのはどういう意味なのか?
スプレッドシートドキュメントをPDFファイルとしてエクスポートするとき、ドキュメント内の選択された箇所のみをエクスポートすることができる。
なるほど。