LibreOffice5(89)マクロをオートメーションで実行するためのコード

2017-10-27

旧ブログ

t f B! P L
LibreOffice5(59)モードレスダイアログの例をPythonに翻訳する:その5の「マクロをオートメーションで実行するためのコード」はグローバル変数が多いので、それを減らしたものに変更します。

前の関連記事: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()はマクロとして実行する関数です。

次の関連記事:LibreOffice5(90)ScriptingURLの動的取得

ブログ検索 by Blogger

Translate

最近のコメント

Created by Calendar Gadget

QooQ