2020年11月29日日曜日

51: 任意のLibreOfficeまたはOpenOfficeマクロをあなたのプログラムから呼び出す

<このシリーズの前の記事 | このシリーズの目次 | このシリーズの次の記事>

「任意の」は、ユーザー所有、アプリケーション所有、ドキュメント内、拡張機能内のいずれか、Python他何でも、を意味します。いいえ、'soffice'を呼んだりはしません、それはハンディキャップを負っています。

話題


About: UNO (Universal Network Objects)
About: LibreOffice
About: Apache OpenOffice
About: Javaプログラム言語
About: C++
About: C#
About: Pythonプログラミング言語
About: LibreOffice Basic
About: Apache OpenOffice Basic
About: JavaScript
About: BeanShell

この記事の目次


開始コンテキスト



ターゲットコンテキスト



  • 読者は、任意のLibreOfficeまたはApache OpenOfficeマクロを自らのプログラムから呼び出す方法を知る。

オリエンテーション


ユーザー所有またはアプリケーション所有のPythonマクロを作成することは、ある以前の記事にて取り扱われました。

ドキュメント内Pythonマクロを作成することは、ある以前の記事にて取り扱われました。

拡張機能内Pythonマクロを作成することは、ある以前の記事にて取り扱われました。

Pythonマクロプログラミングの詳細は、いくつかの以降の記事群にて探求されます。

外部フルPythonを使用することは、以前のある記事にて取り扱われました。


本体

ト書き
Hypothesizer 7、Objector 51A、Objector 51Bが、コンピューターの前にいる。


1: 'soffice'を呼ぶのは、ハンディキャップを負っている


Hypothesizer 7
一部の人々は、LibreOfficeまたはApache OpenOfficeマクロを自らのプログラムから呼び出すために、'soffice'を呼ぶようです。

Objector 51A
. . .俺はそうする、実のところ。お前は俺を非難しているのか?

Hypothesizer 7
いいえ、サー。そのやり方はハンディキャップを負っていることをお知らせしているのです。

Objector 51A
お前は俺をあざけってるんだ!「あのばか、'soffice'を呼んでやがる。はは!」 というわけだ。

Hypothesizer 7
. . .サー、私は全然笑いませんでしたよね?

Objector 51A
おう、お前は心の中で高笑いしていたとも!「あのうすのろを見ろよ!奴のあの間抜け面!」というわけだ。

Hypothesizer 7
. . .サー、大丈夫ですか?

Objector 51B
そんなうすのろ放っておきなさい。いいから、それがどうハンディキャップを負っているのかを説明して。

Hypothesizer 7
ええと、マダム、その方法では、適切な引数を渡せませんよね?

Objector 51B
「適切」ってどういう意味?

Hypothesizer 7
UNOオブジェクト引数を渡すことができますか?

Objector 51B
よく知らないけど。

Hypothesizer 7
UNOオブジェクトリターンを取得することができますか?

Objector 51B
. . .よく知らないけど。

Hypothesizer 7
ドキュメント内マクロを呼べますか?

Objector 51B
なんで、私が尋問されなければいけないの?!「あのひよこをしぼってやるぜ!へへ」っていうわけよ!

Hypothesizer 7
「ひよこ」?「へへ」?. . .大丈夫ですか?

Objector 51A
そんなひよこ、放っておきな。

Hypothesizer 7
とにかく、効率面から言っても、感心しません: マクロ呼び出し毎に外部プロセスを呼び出すのですか?

Objector 51A & Objector 51B
あざけってる!


2: 準備


Hypothesizer 7
準備の1部として、LibreOfficeまたはApache OpenOfficeインスタンスへのUNOオブジェクト群コンテキストを取得しましょう。

Objector 51A
はあ?意味がわからん。

Hypothesizer 7
. . .方法をご存知ないのであれば、'開始コンテキスト'にリストされているリンク群の内の1つを参照されることができます。

Objector 51A
信じられん!

Hypothesizer 7
何も信じる必要はありません。仮説を立て、検証する(境界なく)必要があります

Objector 51A
. . .その部分は飛ばしてもいいだろう?

Hypothesizer 7
いいえ、サー。

Objector 51A
. . .意地が悪いな!なんで、ただ飛ばさせてくれない?

Hypothesizer 7
問題は、私の気質や意図ではありません、サー。

Objector 51A
. . .お前は陰険だな。

ト書き
Hypothesizer 7は、深くため息をつく。

Hypothesizer 7
次に、ドキュメント内マクロをお呼びになりたいのであれば、そのマクロを格納しているオープン済みドキュメントのUNOオブジェクトを取得しなければなりません。

Objector 51A
また、意味のわからんことを言ってるぞ。

Hypothesizer 7
もしも、そのドキュメントをご自分でオープンされるのであれば、そうする方法は、ファイルをコンバートすることについてのある以前の記事(JavaC++C#PythonBasic用)に書かれています。もしも、カレントのオープン済みドキュメントを取得されるのであれば、そうする方法は、UNOディスパッチコマンドを実行することについての、いくつかの以前の記事(JavaC++C#PythonBasic用)に書かれています。

Objector 51A
もしも、カレントでないオープン済みドキュメントを取得しようとしたらどうなんだ?

Hypothesizer 7
そうなさることができます。

Objector 51A
. . .方法を聞いているんだよ。

Hypothesizer 7
それは、そのドキュメントを何によって特定されるかによります。

Objector 51A
名前だ、多分な。

Hypothesizer 7
ああ、それは容易です。

Objector 51A
. . .方法を聞いているんだ。

Hypothesizer 7
それは、ここでは説明できませんが、以降の記事でいたします。もしも、ご興味をお持ちでしたら、今後の投稿にご注目ください

Objector 51A
. . .


3: マクロハンドラー群プロバイダを取得する


Hypothesizer 7
マクロハンドラー群プロバイダを取得しましょう。

Objector 51B
「マクロハンドラー群プロバイダ」?

Hypothesizer 7
それは、あるUNOオブジェクトで、それから、それによって管理されている任意のマクロのハンドラーを取得できるものです。

Objector 51B
それが何であるにせよ、私はそれを取得しないといけないの?

Hypothesizer 7
はい、そうです。

それを取得する方法は、対象マクロが非ドキュメント内であるかドキュメント内であるかによって異なります。


3-1: 非ドキュメント内マクロの場合


Hypothesizer 7
任意の非ドキュメント内マクロのためのマクロハンドラー群プロバイダは、あるグローバルUNOサービスインスタンスとして取得できます、以下のようにして('l_remoteUnoObjectsContext'は、LibreOfficeまたはApache OpenOfficeインスタンスへのUNOオブジェクト群コンテキストです)。

@Java ソースコード
~
import com.sun.star.script.provider.XScriptProvider;
~
import com.sun.star.uno.UnoRuntime;
~
						XScriptProvider l_macroHandlersProviderInXScriptProvider = UnoRuntime.queryInterface (XScriptProvider.class, l_remoteUnoObjectsContext.getServiceManager ().createInstanceWithContext ("com.sun.star.script.provider.MasterScriptProvider", l_remoteUnoObjectsContext));

@C++ ソースコード
~
	#include <com/sun/star/script/provider/XScriptProvider.hpp>
	~
	#include <com/sun/star/uno/Reference.hxx>
	~
	using namespace ::com::sun::star::script::provider;
	~
	using namespace ::com::sun::star::uno;
	~
									Reference <XScriptProvider> l_macroHandlersProviderInXScriptProvider (l_remoteUnoObjectsContext->getServiceManager ()->createInstanceWithContext ("com.sun.star.script.provider.MasterScriptProvider", l_remoteUnoObjectsContext), UNO_QUERY);

@C# ソースコード
~
			using unoidl.com.sun.star.script.provider;
			~
									XScriptProvider l_macroHandlersProviderInXScriptProvider = (XScriptProvider) l_remoteUnoObjectsContext.getServiceManager ().createInstanceWithContext ("com.sun.star.script.provider.MasterScriptProvider", l_remoteUnoObjectsContext);			

@Python ソースコード
~
from typing import cast
~
from com.sun.star.script.provider import XScriptProvider
~
						l_macroHandlersProviderInXScriptProvider: XScriptProvider = cast (XScriptProvider, l_remoteUnoObjectsContext.getServiceManager ().createInstanceWithContext ("com.sun.star.script.provider.MasterScriptProvider", l_remoteUnoObjectsContext))				


3-2: ドキュメント内マクロの場合


Hypothesizer 7
任意のドキュメント内マクロのためのマクロハンドラー群プロバイダは、当該ドキュメントUNOオブジェクトから取得できます、'::com::sun::star::script::provider::XScriptProviderSupplier' UNOインターフェイスを使用して、以下のように('l_unoDocumentInXModel'は、当該ドキュメントUNOオブジェクトです)。

@Java ソースコード
~
import com.sun.star.script.provider.XScriptProvider;
import com.sun.star.script.provider.XScriptProviderSupplier;
~
						XScriptProvider l_macroHandlersProviderInXScriptProvider = UnoRuntime.queryInterface (XScriptProviderSupplier.class, l_unoDocumentInXModel).getScriptProvider ();

@C++ ソースコード
	~
	#include <com/sun/star/script/provider/XScriptProvider.hpp>
	#include <com/sun/star/script/provider/XScriptProviderSupplier.hpp>
	#include <com/sun/star/uno/Reference.hxx>
	~
	using namespace ::com::sun::star::script::provider;
	using namespace ::com::sun::star::uno;
	~
									Reference <XScriptProvider> l_macroHandlersProviderInXScriptProvider (Reference <XScriptProviderSupplier> (l_unoDocumentInXModel, UNO_QUERY)->getScriptProvider ());

@C# ソースコード
			~
			using unoidl.com.sun.star.script.provider;
			~
									XScriptProvider l_macroHandlersProviderInXScriptProvider = ( (XScriptProviderSupplier) l_unoDocumentInXModel).getScriptProvider ();

@Python ソースコード
~
from typing import cast
~
from com.sun.star.script.provider import XScriptProvider
from com.sun.star.script.provider import XScriptProviderSupplier
~
						l_macroHandlersProviderInXScriptProvider = cast (XScriptProviderSupplier, l_unoDocumentInXModel).getScriptProvider ()


4: マクロハンドラーを取得する


Hypothesizer 7
マクロハンドラーを、上記マクロハンドラー群プロバイダから取得しましょう、以下のようにして('l_macroLocationName'および'l_macroPathString'は、引き続くテーブル群に挙げられている仕様にしたがってセットされます)。

@Java ソースコード
~
import com.sun.star.script.provider.XScript;
~
				String l_macroProgrammingLanguageName = "Python";
				~
						String l_macroUrl = String.format ("vnd.sun.star.script:%s?language=%s&location=%s", l_macroPathString, l_macroProgrammingLanguageName, l_macroLocationName);
						XScript l_macroHandlerInXScript = l_macroHandlersProviderInXScriptProvider.getScript (l_macroUrl);

@C++ ソースコード
~
#include <com/sun/star/script/provider/XScript.hpp>
~
						string l_macroProgrammingLanguageName ("Python");
						~
									string l_macroUrl (StringHandler::format ("vnd.sun.star.script:%s?language=%s&location=%s", l_macroPathString, l_macroProgrammingLanguageName, l_macroLocationName));
									Reference <XScript> l_macroHandlerInXScript (l_macroHandlersProviderInXScriptProvider->getScript (UnoExtendedStringHandler::getOustring (l_macroUrl)));

上記において、'StringHandler::format (string const & a_formatString, T const & a_currentItem, U const & ... a_remainderItems)'は、私のユーティリティクラスメソッドテンプレートであって、Javaの'String.format'のように振る舞うものであり、'::theBiasPlanet::unoUtilities::stringsHandling::UnoExtendedStringHandler::getOustring (string const & a_utf8String)'は、私のユーティリティクラスメソッドであって、指定されたUTF-8 '::std::string'インスタンスからUNO文字列インスタンスを作成するものですが、それらをここに示す必要はないでしょう。

@C# ソースコード
~
							String l_macroProgrammingLanguageName = "Python";
							~
									String l_macroUrl = String.Format ("vnd.sun.star.script:{0:s}?language={1:s}&location={2:s}", l_macroPathString, l_macroProgrammingLanguageName, l_macroLocationName);
									XScript l_macroHandlerInXScript = l_macroHandlersProviderInXScriptProvider.getScript (l_macroUrl);

@Python ソースコード
~
from com.sun.star.script.provider import XScript
~
			l_macroProgrammingLanguageName: str = "Python"
			~
						l_macroUrl = "vnd.sun.star.script:{0:s}?language={1:s}&location={2:s}".format (l_macroPathString, l_macroProgrammingLanguageName, l_macroLocationName)
						l_macroHandlerInXScript = l_macroHandlersProviderInXScriptProvider.getScript (l_macroUrl)

マクロロケーション名群

名前意味
userユーザー所有、定位置
user:uno_packagesユーザー所有、拡張機能内
shareアプリケーション所有、定位置
share:uno_packagesアプリケーション所有、拡張機能内
documentドキュメント内

マクロパス群

マクロ言語ロケーションパス
Java定位置またはドキュメント内%ライブラリ名%.%ファンクション名%、例えば、'JavaEnvironmentChecker.theBiasPlanet.javaEnvironmentChecker.macros.JavaEnvironmentChecker.checkJavaEnvironment2'
Java拡張機能内%拡張機能ファイル名%/Scripts/java/%ライブラリ名%.%ファンクション名%、例えば、'theBiasPlanet.javaEnvironmentChecker.unoExtension.oxt/Scripts/java/JavaEnvironmentChecker.theBiasPlanet.javaEnvironmentChecker.macros.JavaEnvironmentChecker.checkJavaEnvironment2'
Python定位置またはドキュメント内%'/'区切りのモジュールファイルパス%$%ファンクション名%、例えば、'theBiasPlanet/pythonEnvironmentChecker/macros/PythonEnvironmentChecker.py$checkPythonEnvironment2'
Python拡張機能内%拡張機能ファイル名%/Scripts/python/%'/'区切りのモジュールファイルパス%$%ファンクション名%、例えば、'theBiasPlanet.pythonEnvironmentChecker.unoExtension.oxt/Scripts/python/theBiasPlanet/pythonEnvironmentChecker/macros/PythonEnvironmentChecker.py$checkPythonEnvironment2'
JavaScript定位置またはドキュメント内%ライブラリ名%.%マクロファイル名%、例えば、'JavascriptEnvironmentChecker.checkJavascriptEnvironment2.js'
JavaScript拡張機能内%拡張機能ファイル名%/Scripts/javascript/%ライブラリ名%.%マクロファイル名%、例えば、'theBiasPlanet.javascriptEnvironmentChecker.unoExtension.oxt/Scripts/javascript/JavascriptEnvironmentChecker.checkJavascriptEnvironment2.js'
BeanShell定位置またはドキュメント内%ライブラリ名%.%マクロファイル名%、例えば、'BeanshellEnvironmentChecker.checkBeanshellEnvironment2.bsh'
BeanShell拡張機能内%拡張機能ファイル名%/Scripts/beanshell/%ライブラリ名%.%マクロファイル名%、例えば、'theBiasPlanet.beanshellEnvironmentChecker.unoExtension.oxt/Scripts/beanshell/BeanshellEnvironmentChecker.checkBeanshellEnvironment2.bsh'

Objector 51B
Basicを忘れたわよ。

Hypothesizer 7
ああ、お気づきになりましたか。実のところ、「忘れた」というよりは、無視したのですが。

Objector 51B
しないで。

Hypothesizer 7
Basicのことは忘れることにしませんか?

Objector 51B
なぜ?

Hypothesizer 7
なぜなら、それは、プログラミング言語として、望ましくないからです。

Objector 51B
. . .

Hypothesizer 7
正直に言って、それには私の感覚が傷つけられます. . .

Objector 51B
あなたは、「任意のLibreOfficeまたはOpenOfficeマクロ」という、自分がつけたタイトルに相反するの?!

Hypothesizer 7
. . .えーと、そう仰るのでしたら。

確かに、任意のBasicマクロをあなたのプログラムから呼び出すことができますが、Basicの場合、どういうわけか、事態が非対称です。

実のところ、マクロロケーション名群は、'application'と'document'です。

Objector 51B
はあ?ユーザー所有マクロ群とアプリケーション所有マクロ群はどうやって区別されるの?

Hypothesizer 7
区別されません、奇妙なことに。

Objector 51B
. . .「されません」ってどういう意味?

Hypothesizer 7
ネームスペースが共有されています。

Objector 51B
拡張機能マクロ群は. . .

Hypothesizer 7
. . .区別されません。

Objector 51B
. . .

Hypothesizer 7
マクロパスは、'%ライブラリ名%.%モジュール名%.%ファンクション名%'です、マクロロケーションが何であろうが。

Objector 51B
. . .

Hypothesizer 7
また、ご注意いただきたいのですが、'com.sun.star.script.provider.MasterScriptProvider' UNOグローバルサービスインスタンスは、ある文字列引数でインスタンス化されなければなりません。

Objector 51B
どういう値で、具体的には?

Hypothesizer 7
それはどうでもよいようです、私が知る限り。

Objector 51B
「どうでもよいよう」とはどういう意味よ?

Hypothesizer 7
どんな値でもうまくいくようです、例えば、空文字列です。

Objector 51B
. . .

Hypothesizer 7
その引数がどのように使用されるのか、私は知りませんし、気にもしていません。


5: マクロを呼び出す


Hypothesizer 7
マクロを呼び出しましょう、以下のようにして('l_macroArgumentsArray'(または'l_macroArgumentsSequence'または'l_macroArguments')、'l_macroOutputArgumentIndicesArray'(または'l_macroOutputArgumentIndicesSequence'または'l_macroOutputArgumentIndices')、'l_macroOutputArgumentsArray'(または'l_macroOutputArgumentsSequence'または'l_macroOutputArguments'))は、引数群(アウトプット引数群を含む)、アウトプット引数インデックス群、アウトプット引数群です。

@Java ソースコード
~
				Object [] l_macroArgumentsArray = new Object [1];
				l_macroArgumentsArray [0] = "Hi bro!!";
				short [] [] l_macroOutputArgumentIndicesArray = new short [1] [0];
				Object [] [] l_macroOutputArgumentsArray = new Object [1] [0];
				Object l_macroReturn = null;
				~
						l_macroReturn = l_macroHandlerInXScript.invoke (l_macroArgumentsArray, l_macroOutputArgumentIndicesArray, l_macroOutputArgumentsArray);

@C++ ソースコード
~
#include <com/sun/star/uno/Any.hxx>
~
							Sequence <Any> l_macroArgumentsSequence (1);
							l_macroArgumentsSequence [0] = Any (UnoExtendedStringHandler::getOustring (string ("Hi bro!!")));
							Sequence <short> l_macroOutputArgumentIndicesSequence;
							Sequence <Any> l_macroOutputArgumentsSequence;
							Any l_macroReturn;
							~
									l_macroReturn = l_macroHandlerInXScript->invoke (l_macroArgumentsSequence, l_macroOutputArgumentIndicesSequence, l_macroOutputArgumentsSequence);

@C# ソースコード
~
			using uno;
			~
							Any [] l_macroArgumentsArray = new Any [1];
							l_macroArgumentsArray [0] = new Any ("Hi bro!!");
							short [] l_macroOutputArgumentIndicesArray = new short [0];
							Any [] l_macroOutputArgumentsArray = new Any [0];
							Any l_macroReturn;
							~
									l_macroReturn = l_macroHandlerInXScript.invoke (l_macroArgumentsArray, out l_macroOutputArgumentIndicesArray, out l_macroOutputArgumentsArray);

@Python ソースコード
~
from typing import List
from typing import Optional
~
				l_macroArguments: List [Optional [object]] = ["Hi bro!!"]
				l_macroOutputArgumentIndices: List [int] = []
				l_macroOutputArguments: List [object] = []
				l_macroReturn: object = None
				~
						l_macroReturn = l_macroHandlerInXScript.invoke (l_macroArguments, l_macroOutputArgumentIndices, l_macroOutputArguments)

Objector 51B
うん?

Hypothesizer 7
ご注意いただきたいのですが、Javaバージョンは、2次元配列を取りますが、その理由は、任意のUNOスペースアウトプット引数はJavaスペース配列になるというのがJava UNOのルールだからです: 任意のUNOスペースアウトプット要素群シーケンスは、Javaスペース2次元配列になります、なぜなら、シーケンスは配列になり、シーケンスの各要素は配列になるからです。

Objector 51B
. . . なぜ、Javaだけなの?

Hypothesizer 7
なぜなら、さもないと、Javaは、アウトプットを取得できないからです、なぜなら、Javaにはリファレンスなどというものは存在しないからです。

Objector 51B
でも、それは、Pythonにも言えることでしょう?

Hypothesizer 7
はい、そうです、しかし、Python UNOは、その問題に別の方法で対処しました。

Objector 51B
どんな方法で、具体的には?

Hypothesizer 7
アウトプット引数値群は、リターンされるリストの中でリターンされます。


参考資料


<このシリーズの前の記事 | このシリーズの目次 | このシリーズの次の記事>