前の関連記事:LibreOffice5(88)Writerドキュメントのサービスとインターフェイス一覧
マクロをオートメーションで実行するためのコード
このコードはマクロをオートメーションで動作確認するだけためのものなので、副作用はなるべく少なくしたいものです。
グローバル変数が多くするとマクロ内の同名の変数に対して、PyDevでUndefined variableを指摘されなくなってしまいます。
なので、なるべく関数内のスコープで処理するようにして、グローバル変数を少なくします。
if __name__ == "__main__": # オートメーションで実行するとき
def automation(): # オートメーションのためにglobalに出すのはこの関数のみにする。
import officehelper
from functools import wraps
import sys
from com.sun.star.beans import PropertyValue
from com.sun.star.script.provider import XScriptContext
def connectOffice(func): # funcの前後でOffice接続の処理
@wraps(func)
def wrapper(): # LibreOfficeをバックグラウンドで起動してコンポーネントテクストとサービスマネジャーを取得する。
try:
ctx = officehelper.bootstrap() # コンポーネントコンテクストの取得。
except:
print("Could not establish a connection with a running office.", file=sys.stderr)
sys.exit()
print("Connected to a running office ...")
smgr = ctx.getServiceManager() # サービスマネジャーの取得。
print("Using {} {}".format(*_getLOVersion(ctx, smgr))) # LibreOfficeのバージョンを出力。
return func(ctx, smgr) # 引数の関数の実行。
def _getLOVersion(ctx, smgr): # LibreOfficeの名前とバージョンを返す。
cp = smgr.createInstanceWithContext('com.sun.star.configuration.ConfigurationProvider', ctx)
node = PropertyValue(Name = 'nodepath', Value = 'org.openoffice.Setup/Product' ) # share/registry/main.xcd内のノードパス。
ca = cp.createInstanceWithArguments('com.sun.star.configuration.ConfigurationAccess', (node,))
return ca.getPropertyValues(('ooName', 'ooSetupVersion')) # LibreOfficeの名前とバージョンをタプルで返す。
return wrapper
@connectOffice # createXSCRIPTCONTEXTの引数にctxとsmgrを渡すデコレータ。
def createXSCRIPTCONTEXT(ctx, smgr): # XSCRIPTCONTEXTを生成。
class ScriptContext(unohelper.Base, XScriptContext):
def __init__(self, ctx):
self.ctx = ctx
def getComponentContext(self):
return self.ctx
def getDesktop(self):
return ctx.getByName('/singletons/com.sun.star.frame.theDesktop') # com.sun.star.frame.Desktopはdeprecatedになっている。
def getDocument(self):
return self.getDesktop().getCurrentComponent()
return ScriptContext(ctx)
XSCRIPTCONTEXT = createXSCRIPTCONTEXT() # XSCRIPTCONTEXTの取得。
doc = XSCRIPTCONTEXT.getDocument() # 現在開いているドキュメントを取得。
doctype = "scalc", "com.sun.star.sheet.SpreadsheetDocument" # Calcドキュメントを開くとき。
# doctype = "swriter", "com.sun.star.text.TextDocument" # Writerドキュメントを開くとき。
if (doc is None) or (not doc.supportsService(doctype[1])): # ドキュメントが取得できなかった時またはCalcドキュメントではない時
XSCRIPTCONTEXT.getDesktop().loadComponentFromURL("private:factory/{}".format(doctype[0]), "_blank", 0, ()) # ドキュメントを開く。ここでdocに代入してもドキュメントが開く前にmacro()が呼ばれてしまう。
flg = True
while flg:
doc = XSCRIPTCONTEXT.getDocument() # 現在開いているドキュメントを取得。
if doc is not None:
flg = (not doc.supportsService(doctype[1])) # ドキュメントタイプが確認できたらwhileを抜ける。
return XSCRIPTCONTEXT
XSCRIPTCONTEXT = automation() # XSCRIPTCONTEXTを取得。
macro() # マクロの実行。
40行目と41行目でオートメーションでロードするとドキュメントをCalcかWriterのものか選択できます。すでに開いているドキュメントが同じタイプであるときはそれを利用します。
シート内容を削除するマクロを実行するときはそのことに注意しないといけません。
このコードではグローバルに出しているのはXSCRIPTCONTEXTとautomationだけです。
モジュールのインポートも関数内のスコープで行うようにしました。
macro()はマクロとして実行する関数です。
0 件のコメント:
コメントを投稿