任意のドキュメント内モジュールもあなたのマクロまたはあなたのマクロによってインポートされた任意のモジュールへインポートできます。以下はその方法です。
話題
About: UNO (Universal Network Objects)
About: LibreOffice
About: Apache OpenOffice
About: Pythonプログラミング言語
この記事の目次
- 開始コンテキスト
- ターゲットコンテキスト
- オリエンテーション
- 本体
- 1: ドキュメント内モジュールは別問題です、なぜならば . . .
- 2: モジュールはインポートすることができる、もしも、モジュールのコンテンツが得られたならば
- 3: モジュールコンテンツはオープン済みのドキュメントから取得できる、もしもそのURLが知られていれば
- 4: 対象モジュールが、同一ドキュメント内のマクロにインポートされると仮定すると
- 5: しかし、もしも、対象モジュールが、同一ドキュメント内のあるマクロにインポートされたあるモジュールへインポートされるならば?
- 6: 対象モジュールが、同一ドキュメント内にないマクロまたはモジュールへインポートされると仮定すると
- 7: あるソースローダーおよびあるモジュールインポーターのコード
- 8: 使用例
開始コンテキスト
- 読者は、LibreOfficeまたはApache OpenOfficeの基本的知識を持っている。
- 読者は、UNOとは何であるかおよびそれがLibreOfficeまたはApache OpenOfficeにどう関係しているかの知識を持っている。
- 読者は、Pythonプログラミング言語の基本的知識を持っている。
ターゲットコンテキスト
- 読者は、任意のドキュメント内モジュールを自らのLibreOfficeまたはApache OpenOffice Pythonマクロモジュールにインポートする方法を知る。
オリエンテーション
外部フルPythonを使用することは、以前のある記事にて取り扱われました。.
ユーザー所有またはアプリケーション所有のPythonマクロを作成することは、ある以前の記事にて取り扱われました。
ドキュメント内Pythonマクロを作成することは、ある以前の記事にて取り扱われました。.
拡張機能内Pythonマクロを作成することは、ある以前の記事にて取り扱われました。.
任意の非ドキュメント内モジュールをインポートすることは、本記事の第1パートにて取り扱われました。
Pythonマクロプログラミングの詳細は、いくつかの以降の記事群にて探求されます。
本体
ト書きHypothesizer 7、Objector 54A、Objector 54Bが、コンピューターの前にいる。
1: ドキュメント内モジュールは別問題です、なぜならば . . .
Hypothesizer 7
もしも、インポートされるべきモジュールがドキュメント内でないのであれば、本記事の第1パートだけで十分なはずです。
任意のドキュメント内モジュールは別問題ですが、その理由は、それがオペレーティングシステムファイル内にあるのではないことです。
Objector 54A
ドキュメント・オペレーティングシステムファイル内にあるがね。
Hypothesizer 7
確かに、サー、しかし、私が申し上げているのは、ドキュメント・オペレーティングシステムファイルは、モジュールファイルではなく、モジュールファイルを格納しているZIPファイルであるということです。
Objector 54A
じゃあ、私が正しかったわけだ。
Hypothesizer 7
えーと、厳密に言うと、任意のドキュメント内モジュールは、オペレーティングシステムファイル内に直接にはありません。
とにかく、問題は、そうしたモジュール位置は'PYUNO_LOADER_PYTHONPATH'や'sys.path'にはセットできないということです。
2: モジュールはインポートすることができる、もしも、モジュールのコンテンツが得られたならば
Hypothesizer 7
実のところ、もしも、モジュールのコンテンツが得られたのであれば、そのモジュールはインポートすることができます。
Objector 54B
. . . それじゃあ、ソースローダーを作ればよいだけだと?
Hypothesizer 7
もしも、当該モジュールコンテンツの取得がおできになるのであれば、そうです、マダム。
Objector 54B
ZIPファイルからモジュールファイルを抽出すればいいんでしょ(ドキュメントファイルはZIPファイルですよね)?
Hypothesizer 7
それは1つのオプションかもしれません、もしも、当該ドキュメントファイルが暗号化されていないのであれば。
Objector 54B
えーと、もしされてたらどうなの?
Hypothesizer 7
そのモジュールファイルのコンテンツは暗号化されているでしょう。
Objector 54B
. . . コンテンツは復号化できるでしょう?
Hypothesizer 7
おできになりますか?
Objector 54B
. . . できない?
Hypothesizer 7
えーと、論理的に言えば、可能なはずです、もしも、当該ロジックをLibreOfficeまたはApache OpenOfficeのソースファイルから学ばれて、また、勿論、ユーザーにパスワードを提供させるのであれば。
Objector 54B
. . .
3: モジュールコンテンツはオープン済みのドキュメントから取得できる、もしもそのURLが知られていれば
Hypothesizer 7
実のところ、モジュールコンテンツは、オープン済みのドキュメントから取得することができます、以下のようにして、ここで、'l_remoteUnoObjectsContextInXComponentContext'は、LibreOfficeまたはApache OpenOfficeインスタンスへのUNOオブジェクト群コンテキスト、'a_url'は、モジュールURL、リターンは、'bytes'データです。
@Python ソースコード
from uno import ByteSequencefrom com.sun.star.io import XInputStreamfrom com.sun.star.ucb import XSimpleFileAccessl_simpleFilesAccessUnoService: XSimpleFileAccess = cast (XSimpleFileAccess, l_remoteUnoObjectsContextInXComponentContext.getServiceManager ().createInstanceWithContext ("com.sun.star.ucb.SimpleFileAccess", l_remoteUnoObjectsContextInXComponentContext))try:l_inputStream: "XInputStream" = l_simpleFilesAccessUnoService.openFileRead (a_url)l_readLength: int = 0l_inputDatum: ByteSequence = ByteSequence (b"")l_inputBuffer: ByteSequence = Nonewhile True:l_readLength, l_inputBuffer = l_inputStream.readBytes (None, 1024)l_inputDatum = l_inputDatum + l_inputBufferif l_readLength < 1024:breakfinally:if l_inputStream is not None:l_inputStream.closeInputreturn l_inputDatum.value
Objector 54A
. . . はあ?「UNOオブジェクト群コンテキスト」?何だ、それは?
Hypothesizer 7
. . . 基本を学ばずに済まそうとしないでください。
Objector 54A
「基本」だと?ふざけてるのか?そんなのを学ぶのは私のこ券に関わる。
Hypothesizer 7
. . . もしも、あなたのプログラムがマクロであれば、'XSCRIPTCONTEXT.getComponentContext ()'がそれをリターンします。
Objector 54A
それで、URLは何だ?
Hypothesizer 7
URLは、'vnd.sun.star.tdoc:/1/Scripts/python/theBiasPlanet/pythonEnvironmentChecker/InDocumentModuleTest.py'のようなものです。
Objector 54A
それじゃあ、'Scripts/python'の後ろの部分を置き換えればいいのか?
Hypothesizer 7
実は、そこの数字、'1'は、ドキュメントロードナンバーです。
Objector 54A
どういう意味だ?
Hypothesizer 7
1番目にロードされたドキュメントには'1'が与えられ、2番目のものには'2'が、等になります、インスタンスが開始されてから。
Objector 54A
一体全体、特定のドキュメントの番号をどうやって私が知るように想定されているのだ?
Hypothesizer 7
えーと、いくつかの方法がありえます。
4: 対象モジュールが、同一ドキュメント内のマクロにインポートされると仮定すると
Hypothesizer 7
対象モジュールが、同一ドキュメント内のマクロにインポートされると仮定しましょう、それは、私が想像するに、普通のケースでしょう。
Objector 54B
他にどうありえると言うの?
Hypothesizer 7
そのモジュールは、別のドキュメント内のマクロ、または、ユーザ所有、アプリケーション所有、拡張機能内のいずれかのマクロにインポートされるかもしれません。
Objector 54B
それは考えにくい、と私は思うけど。
Hypothesizer 7
もしもそうであれば、それはとても好都合です、私にとっても、あなたにとっても。
Objector 54B
じゃあ、そうだと仮定して . . .
Hypothesizer 7
実は、本記事の第1パートのあるセクションにて、当該マクロモジュールのURLをそのマクロモジュールのある変数('s_sourceFileUrl')にセットするロジックを私は実装済みです。
Objector 54B
. . . ふーむ、あなたが言ってるのは、インポートするマクロのURLのことでしょ、私が本当に必要としている、インポートされるモジュールのURLのことじゃなく?
Hypothesizer 7
はい、しかし、あなたが必要とする、ドキュメントロードナンバーは、同じものです。
Objector 54B
確かに。
5: しかし、もしも、対象モジュールが、同一ドキュメント内のあるマクロにインポートされたあるモジュールへインポートされるならば?
Objector 54B
でも、もしも、対象モジュールが、同一ドキュメント内のあるマクロにインポートされたあるモジュール(勿論、同一ドキュメント内にある)へインポートされるとしたら?
Hypothesizer 7
そこで、当該マクロに、インポートされたモジュールのURLをインポートされたモジュールへセットさせましょう。
Objector 54B
ああ、もちろん、それじゃあ、URLたちが順次セットされていくわけね。
Hypothesizer 7
実装上は、ソースローダーが、URLを、インポートされるモジュールへセットできます。
6: 対象モジュールが、同一ドキュメント内にないマクロまたはモジュールへインポートされると仮定すると
Objector 54A
それじゃあ、対象モジュールが、同一ドキュメント内にないマクロまたはモジュールへインポートされると仮定しろ。
Hypothesizer 7
えーと、本当にそれを必要とされますか、サー?
Objector 54A
実際にはしない、少なくとも、今のところはな、しかし、とにかくそうしろ。
Hypothesizer 7
なぜでございますか、サー?
Objector 54A
なぜなら、任意のモジュールがインポートできると言った約束をお前が果たさずに済ますことを、私は許さんからだ。
Hypothesizer 7
結構でございます。いくつか方法がありえますが、私であれば、当該ドキュメント内に1つマクロを用意して、そのマクロに、そのドキュメントのPythonモジュール群ベースURLをリターンさせるでしょう。
Objector 54A
. . . どうすれば、そのマクロをコールできるんだ?
Hypothesizer 7
ある以前の記事にて紹介された方法でできるでしょう。
Objector 54A
. . . えーと、他にどんな方法がある?
Hypothesizer 7
えーと、より推奨できる方法を私は知りませんが、多分、ドキュメントオープンイベント群ハンドラを作成してドキュメントのオープン群を記録させるとか、単に力ずくで試行するとか、することができるでしょう、例えば。
7: あるソースローダーおよびあるモジュールインポーターのコード
Hypothesizer 7
以下は、あるソースローダーおよびあるモジュールインポーターのコードです。
theBiasPlanet/unoUtilities/pythonSourceLoader/UnoExtendedPythonSourceLoader.py
@Python ソースコード
from typing import Unionfrom typing import castfrom importlib.abc import SourceLoaderimport unofrom uno import ByteSequencefrom com.sun.star.io import XInputStreamfrom com.sun.star.ucb import XSimpleFileAccessfrom com.sun.star.uno import XComponentContextclass UnoExtendedPythonSourceLoader (SourceLoader):c_readingBlockSize: int = 1024def __init__ (a_this: "UnoExtendedPythonSourceLoader", a_remoteUnoObjectsContextInXComponentContext: "XComponentContext", a_uriPrefix: str) -> None:a_this.i_simpleFilesAccessUnoService: XSimpleFileAccess = Nonea_this.i_uriPrefix: str = a_uriPrefixa_this.i_simpleFilesAccessUnoService = cast (XSimpleFileAccess, a_remoteUnoObjectsContextInXComponentContext.getServiceManager ().createInstanceWithContext ("com.sun.star.ucb.SimpleFileAccess", a_remoteUnoObjectsContextInXComponentContext))def get_filename (a_this: "UnoExtendedPythonSourceLoader", a_moduleName: str) -> str:return "{0:s}{1:s}.{2:s}".format (a_this.i_uriPrefix, a_moduleName.replace (".", "/"), "py")def get_data (a_this: "UnoExtendedPythonSourceLoader", a_url: Union [bytes, str]) -> bytes:try:l_inputStream: "XInputStream" = a_this.i_simpleFilesAccessUnoService.openFileRead (a_url)l_readLength: int = 0l_inputDatum: ByteSequence = ByteSequence (b"")l_inputBuffer: ByteSequence = Nonewhile True:l_readLength, l_inputBuffer = l_inputStream.readBytes (None, 1024)l_inputDatum = l_inputDatum + l_inputBufferif l_readLength < 1024:breakfinally:if l_inputStream is not None:l_inputStream.closeInputreturn l_inputDatum.value
theBiasPlanet/unoUtilities/pythonModuleImporter/UnoExtendedPythonModuleImporter.py
@Python ソースコード
from typing import Optionalfrom collections import OrderedDictimport sysfrom types import ModuleTypefrom theBiasPlanet.unoUtilities.pythonSourceLoader.UnoExtendedPythonSourceLoader import UnoExtendedPythonSourceLoaderclass UnoExtendedPythonModuleImporter:c_pythonModulesBaseDirectoryIndicator: str = "/Scripts/python/"c_sourceFileUrlModulePropertyName: str = "s_sourceFileUrl"@staticmethoddef getUriPrefix (a_sourceFileUrl: str) -> str:l_uriPrefix: str = a_sourceFileUrl [0: a_sourceFileUrl.find (UnoExtendedPythonModuleImporter.c_pythonModulesBaseDirectoryIndicator) + len (UnoExtendedPythonModuleImporter.c_pythonModulesBaseDirectoryIndicator)]return l_uriPrefix@staticmethoddef importModule (a_unoExtendedPythonSourceLoader: "UnoExtendedPythonSourceLoader", a_moduleName: str, a_setModuleProperties: "Optional [OrderedDict [str, object]]") -> ModuleType:l_pythonModule = ModuleType (a_moduleName)l_pythonModule.__dict__ [UnoExtendedPythonModuleImporter.c_sourceFileUrlModulePropertyName] = a_unoExtendedPythonSourceLoader.get_filename (a_moduleName)l_propertyName: strl_propertyValue: objectfor l_propertyName, l_propertyValue in a_setModuleProperties.items ():l_pythonModule.__dict__ [l_propertyName] = l_propertyValuea_unoExtendedPythonSourceLoader.exec_module (l_pythonModule)sys.modules [a_moduleName] = l_pythonModulereturn l_pythonModule
Objector 54B
えーと . . .
Hypothesizer 7
そのソースローダのコンストラクタは、LibreOfficeまたはApache OpenOfficeインスタンスへのUNOオブジェクト群コンテキスト、および'vnd.sun.star.tdoc:/1/Scripts/python/'のようなURLプリフィックスを取ります。
そのモジュールインポーターのインポート実行メソッドは、モジュール名、およびインポートされたモジュールへセットされるプロパティ群を取ります。
8: 使用例
Hypothesizer 7
以下は、同一ドキュメント内モジュール、'theBiasPlanet.pythonEnvironmentChecker.InDocumentModuleTest'を、あるモジュール(それはマクロモジュールであるかもないかもしれない)インポートする使用例です。
@Python ソースコード
from collections import OrderedDict~import sys~from types import ModuleType~from com.sun.star.script.provider import XScriptContext~from theBiasPlanet.unoUtilities.pythonModuleImporter.UnoExtendedPythonModuleImporter import UnoExtendedPythonModuleImporterfrom theBiasPlanet.unoUtilities.pythonSourceLoader.UnoExtendedPythonSourceLoader import UnoExtendedPythonSourceLoaderXSCRIPTCONTEXT: XScriptContexts_unoExtendedPythonSourceLoader: "UnoExtendedPythonSourceLoader" = UnoExtendedPythonSourceLoader (XSCRIPTCONTEXT.getComponentContext (), UnoExtendedPythonModuleImporter.getUriPrefix (s_sourceFileUrl))s_pythonModule: ModuleType = UnoExtendedPythonModuleImporter.importModule (s_unoExtendedPythonSourceLoader, "theBiasPlanet.pythonEnvironmentChecker.InDocumentModuleTest", OrderedDict ( [ ("XSCRIPTCONTEXT", XSCRIPTCONTEXT)]))InDocumentModuleTest = s_pythonModule.InDocumentModuleTest~def checkPythonEnvironment2 (a_message: str) -> str:return "The Python environment: version -> {0:s}, paths -> {1:s}\n".format (sys.version, str (sys.path)) + ", " + InDocumentModuleTest.c_test + ", " + s_sourceFileUrl
Objector 54A
. . . それは、なんかごてごてしてるぞ。
Hypothesizer 7
そうですか?どう見えるかはとにかくとして、あなたが変更しなければならないのは、モジュール名だけです。
Objector 54A
うーん . . .
Hypothesizer 7
ご注意いただきたいのですが、そこの's_sourceFileUrl'がそこに存在するのは、'pythonscript.py'(本記事の第1パートにおけるように変更された)またはそのモジュールインポーターがそこにセットしたからにほかなりません。
Objector 54A
同一ドキュメント内にないモジュールはどうなる?
Hypothesizer 7
えーと、唯一の課題は、's_sourceFileUrl'の代わりに適切な値を用いなければならないということだけです。
Objector 54A
どのように適切にしろと?
Hypothesizer 7
とても適切に。
Objector 54A
. . . 「そのドキュメントのPythonモジュール群ベースURLをリターンさせる」当該ドキュメント内マクロ」なるものが具体的にどのようであるべきなのか、私には分からん。
Hypothesizer 7
お分かりになりませんか?そのマクロは、単に、'UnoExtendedPythonModuleImporter.getUriPrefix (s_sourceFileUrl)'をリターンすることになります、以下のように。
@Python ソースコード
def getBaseUrlOfThisDocumentPythonModules () -> str:return UnoExtendedPythonModuleImporter.getUriPrefix (s_sourceFileUrl)
既に申し上げたとおり、そのマクロをどのようにコールするかは、ある以前の記事に記述されております。