EclipseからOOoのPythonマクロの実行方法について教えて下さい。 †
ページ | OpenOffice.org FAQの登録ページ |
---|---|
投稿者 | new_OOo3 |
分類 | |
優先順位 | |
状態 | |
カテゴリー | |
投稿日 | 2010-08-15 21:06:28 (日) |
OS | WindowsXP SP3 |
依存するページ | faq/5/461 |
バージョン |
メッセージ †
回答ページでは行末に「~」を付加する必要はありません |
お世話になります。 以前OOoユーザー会にてeclipseを用いたPythonマクロ作成環境構築方法をご教示頂いたものです。 教えて頂きました環境にてPythonマクロを作成しておりますが、実行は別途OpenOffice.orgを起動させて、OOoの「ツール」=>「マクロの管理」=>「Python」から行っております。 しかしながらeclipseにて作成し、それをOOoにて別途実行するのは少し非効率に感じております。 つきましては、eclipseからOOoを操作するべく下記操作を行ないました。
【 手順 】 1)下記内容のbat fileを作成して、OpenOffice.orgをListenモードで起動する。
***** bat file 内容 ********* cd \ set CLASSPATH=Program Files/OpenOffice.org 3/URE/java/bootstrapconnector.jar "C:\Program Files\OpenOffice.org 3\program\soffice" "-accept=socket,host=localhost,port=2002;urp;StarOffice.ServiceManager" ******************************
2)eclipseを起動させてPythonマクロからOpenOffice.org Calcを起動させる下記コードを作成。
********* Macro Code ************ import uno def connect(): try: localctx = uno.getComponentContext() resolver = localctx.ServiceManager.createInstanceWithContext( "com.sun.star.bridge.UnoUrlResolver",localctx) ctx = resolver.resolve( "uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext") except: pass # return None return ctx #if __name__=="__main__": ctx = connect() # if ctx == None: # print "Failed to connect." # import sys # sys.exit() smgr = ctx.ServiceManager desktop = smgr.createInstanceWithContext("com.sun.star.frame.Desktop",ctx) model = desktop.loadComponentFromURL("private:factory/scalc","_default",0,()) ctx.ServiceManager *****************************************
#部はeclipseにてError表示がされたのでコメントにしました。
しかしながら、上記コードをeclipseにて実行しましたが、Calcは起動せず、OOoからも「ツール」=>「マクロの管理」=>「Python」=>「connect」を実行してもCalcが起動しません。
また、eclipseの環境設定等は以下のURLの「準備」項目にて記した様に設定しました。
[eclipse設定] URL : http://openoffice3.web.fc2.com/Python_Macro.html
更に同じ環境にて以下のマクロをOOoから実行すると上手く実行出来ました。
***** OOoから実行出来たマクロコード ***** [#pb295372] #! # -*- coding: utf_8 -*- import uno def helloWorld(): desktop = XSCRIPTCONTEXT.getDesktop() frame = desktop.getCurrentFrame() win = frame.getContainerWindow() toolkit = win.getToolkit() rect = uno.createUnoStruct("com.sun.star.awt.Rectangle") title = "title" msg = "Hello World in Python!!" msgbox = toolkit.createMessageBox(win, rect, "messbox", 1, title, msg) msgbox.execute() g_exportedScripts = helloWorld, ********************************************
つきましては以下の項目についてご教示頂けます様お願いします。
[ 質問項目 ]
1)eclipseから直接にPythonマクロを実行させる方法をご教示下さい。
2)eclipseから直接OpenOffice.orgのApplicationを起動させる方法をご教示下さい。
[ 開発環境 ]
eclipse3.6
Python2.6(OOo3.2.1付属)
宜しくお願いします。
無題 †
tani (2010-08-16 11:18:05 (月))
eclipseは使ったことが無いので、何故動かないのかよくわかりませんが、私の手元では以下のようなコードが動きました。
# -*- coding: utf-8 -*- import uno localContext = uno.getComponentContext() resolver = localContext.ServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", localContext ) ctx = resolver.resolve( "uno:socket,host=localhost,port=8100;urp;StarOffice.ComponentContext" ) smgr = ctx.ServiceManager desktop = smgr.createInstanceWithContext( "com.sun.star.frame.Desktop",ctx) NewDoc = desktop.loadComponentFromURL( "private:factory/scalc","_blank", 0, () )
ちなみにWindows環境なら以下のような手もあると思います。
(Pythonのwin32用拡張モジュールをインストールしないと動作しないかもしれません。)
from win32com.client.dynamic import Dispatch objServiceManager = Dispatch('com.sun.star.ServiceManager') Stardesktop = objServiceManager.CreateInstance('com.sun.star.frame.Desktop') doc = Stardesktop.loadComponentfromURL('private:factory/swriter', '_blank', 0, []) text = doc.getText() text.setString("Hello World")
以上参考までに。
上記コード connect 中のコメント行 †
はにゃ? (2010-08-17 01:03:42 (火))
手順 2 のコードで #if __name__=="__main__": の行がコメントアウトされているので、全体が connect 関数になっている気がします。
途中に return ctx があるので何も起きないはずです。
Eclipse でオートメーションとしてマクロを作成する理由 †
はにゃ? (2010-08-17 01:22:12 (火))
>しかしながらeclipseにて作成し、それをOOoにて別途実行するのは少し非効率に感じております
http://oooug.jp/faq/index.php?faq%2F5%2F461 の参考 URL1 では、非効率だからこそオートメーションとしてマクロを作成するのが目的です。マクロがほぼ完成するまではオートメーションで実行、大体できたらマクロとして OOo から実行して確認する、のが想定した手順です。
Eclipse から OOo のマクロとして (正しく) 実行するには、プラグインでも作成しなければ無理です。なので、次のようなコードを使って実行します。def run_script(ctx, mod_name, func_name, location="user"): script_url = "vnd.sun.star.script:%s$%s?language=Python&location=%s" % (mod_name, func_name, location) msp = ctx.getValueByName("/singletons/com.sun.star.script.provider.theMasterScriptProviderFactory") sp = msp.createScriptProvider("") script = sp.getScript(script_url) return script.invoke((), (), ())色々前提条件がありますが、unopy.py などに入れておき次のようにしたりします。
if __name__ == '__main__': unopy.run_script("module.py", "hello")
質問項目2 (Eclipse から OOo を起動) †
はにゃ? (2010-08-17 01:25:25 (火))
ただのツールとして起動したいのであれば OOo を外部ツールとして登録して Eclipse から起動できます。
オートメーションの一環として起動したいのであれば、officehelper.py などを参考にしてください (uno.py と同じディレクトリにあります)。
ご回答ありがとうございます。今しばらく時間を下さい。 †
new_OOo3 (2010-08-18 21:11:03 (水))
tani 様 はにゃ? 様
ご回答頂きましてありがとうございます。
ご指摘頂いた内容を自分なりに整理していますが、脳みそと手が追いついていけておりません。
今しばらくお時間を頂けます様お願いします。
管理人様
今しばらく、「回答中」で保留させて頂けます様お願いします。
OOo起動までは出来ました。 †
new_OOo3 (2010-08-20 23:52:22 (金))
お世話になります。
eclipseのDL & Installからやり直したところ、tani様よりご提示頂きましたPython CodeにてEclipseからcalcを起動させることが出来ました。
そして、次にはにゃ?様からのご回答とはにゃ?様のサイトを元に以下の事を行いました。
1)unopy.pyの変更
教えて頂いたCodeを以下の様にunopy.pyに追加しました。********* unopy.py ************* #! # unopy.py # -*- coding: utf_8 -*- import uno import unohelper from com.sun.star.script.provider import XScriptContext class ScriptContext(unohelper.Base, XScriptContext): def __init__(self, ctx): self.ctx = ctx def getComponentContext(self): return self.ctx def getDesktop(self): return self.ctx.getServiceManager().createInstanceWithContext( "com.sun.star.frame.Desktop", self.ctx) def getDocument(self): return self.getDesktop().getCurrentComponent() def connect(): ctx = None try: localctx = uno.getComponentContext() resolver = localctx.getServiceManager().createInstanceWithContext( "com.sun.star.bridge.UnoUrlResolver", localctx) ctx = resolver.resolve( "uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext") if ctx: return ScriptContext(ctx) except: pass return None def run_script(ctx, mod_name, func_name, location="user"): script_url = "vnd.sun.star.script:%s$%s?language=Python&location=%s" % (mod_name, func_name, location) msp = ctx.getValueByName("/singletons/com.sun.star.script.provider.theMasterScriptProviderFactory") sp = msp.createScriptProvider("") script = sp.getScript(script_url) return script.invoke((), (), ()) *********************************************
そして、下記CodeにてWriter起動 => Hello! を表示する事を試みました。********** test2.py ************************ #! # test.py # -*- coding: utf_8 -*- import uno localContext = uno.getComponentContext() resolver = localContext.ServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", localContext ) ctx = resolver.resolve( "uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext" ) smgr = ctx.ServiceManager desktop = smgr.createInstanceWithContext( "com.sun.star.frame.Desktop",ctx) doc = desktop.loadComponentFromURL( "private:factory/swriter","_blank", 0, () ) def hello(): doc.getText().setString("Hello!") *****************************************
を実行しましたが、Writerが起動されるだけで「Hello!」が表示されません。
また、OOo側からツール=>マクロ=>マクロの管理=>Python=>OOoPython => src => python => helloを実行実行しましたところ下記Eroor Messageが表示されました。
理解度が悪く何度もお世話になりますが、Writer起動 => Hello! と表示されるマクロのコードをご教示頂けます様お願いします。
また、それとも本行為は、はにゃ?様よりご教示頂いた
「Eclipse から OOo のマクロとして (正しく) 実行するには、プラグインでも作成しなければ無理」
と言う事を理解していないのでしょうか?
宜しくご回答を頂けます様お願いします。
Re: OOo起動までは出来ました。 †
はにゃ? (2010-08-21 02:39:22 (土))
Eclipse から実行した場合、test2.py の hello は呼ばれていないので "Hello!" は表示されません。hello()の行を test2.py に追加してください。
オートメーションとしての実行およびマクロとしての実行の両方を想定すると次のようにします。test2.py は user の Scripts/python/test2.py に配置してあるとします。
#! # test2.py # -*- coding: utf_8 -*- def hello(arg=''): doc = XSCRIPTCONTEXT.getDocument() doc.getText().setString("Hello!" if not arg else arg) if __name__ == '__main__': import uno localContext = uno.getComponentContext() resolver = localContext.ServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", localContext ) ctx = resolver.resolve( "uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext" ) smgr = ctx.ServiceManager desktop = smgr.createInstanceWithContext( "com.sun.star.frame.Desktop",ctx) doc = desktop.loadComponentFromURL( "private:factory/swriter","_blank", 0, () ) import unopy XSCRIPTCONTEXT = unopy.ScriptContext(ctx) if 1: hello("Hello! (from automation)") else: unopy.run_script(ctx, "test2.py", "hello", "user")
マクロとして実行したときのエラーについて †
はにゃ? (2010-08-21 03:02:01 (土))
Python マクロとして実行できるのは、ファイル内に定義された関数です。参照:
http://udk.openoffice.org/python/scriptingframework/index.html#coding
まず、マクロが実行される直前にマクロのファイルが一度実行されます。その後でマクロとして実行する関数に引数が渡されて呼び出されます。
ファイル全体が一度実行されるので、マクロとして定義したい関数以外は global な部分に書かない方がいいと思います。
if __name__ == '__main__': は Python では一般的な書き方で、そのファイルが (モジュールとして) import されずに実行されたときに (__name__ が "__main__" なので) 処理されます。Eclipse のメニューから Run したときにはこの部分は実行されます。マクロとして OOo から実行されたときには __name__ = 'ooo_script_framework' なので無視されます。
オートメーション用とマクロ用のファイルに分けたくないので、上記のコードではこれを利用してどちらでも実行できるようにしています。
出来ました。本当にありがとうございます。 †
new_OOo3 (2010-08-21 21:06:04 (土))
はにゃ? 様
お世話になっております。
親切・丁寧にご指導頂きまして本当にありがとうございます。
ご教示頂きましたCodeにて、Eclipseを用いてAutomationでmacroの作成し、それをOOoから実行できる様になりました。
また、以前にご教示頂きましたCalcでのActive CellのAddressを取得するmacroもautomationにて実施出来ましたので参考として以下に記させて頂きます。
URL : http://oooug.jp/faq/index.php?faq/5/422
******** OOoから実行するCode(faq/5/422より抜粋) ************** from com.sun.star.awt import Rectangle~ def show_message(desktop, message): """shows message.""" frame = desktop.getCurrentFrame() window = frame.getContainerWindow() toolkit = window.getToolkit() msgbox = toolkit.createMessageBox( window, Rectangle(), 'messbox', 1, '', message) return msgbox.execute() def get_active_cell(): doc = XSCRIPTCONTEXT.getDocument() selected = doc.getCurrentSelection() try: if selected.supportsService('com.sun.star.sheet.SheetCellRange'): addr = selected.getRangeAddress() txt = 'Column: %s\nRow: %s' % (addr.EndColumn, addr.EndRow) show_message(XSCRIPTCONTEXT.getDesktop(), txt) except: pass *********************************************************
******* ecipseからAutomationにて実行するCode ************ import uno from com.sun.star.awt import Rectangle def show_message(desktop, message): """shows message.""" frame = desktop.getCurrentFrame() window = frame.getContainerWindow() toolkit = window.getToolkit() msgbox = toolkit.createMessageBox( window, Rectangle(), 'messbox', 1, '', message) return msgbox.execute() def get_active_cell(): doc = XSCRIPTCONTEXT.getDocument() selected = doc.getCurrentSelection() try: if selected.supportsService('com.sun.star.sheet.SheetCellRange'): addr = selected.getRangeAddress() txt = 'Column: %s\nRow: %s' % (addr.EndColumn, addr.EndRow) show_message(XSCRIPTCONTEXT.getDesktop(), txt) except: pass if __name__ == '__main__': # import uno localContext = uno.getComponentContext() resolver = localContext.ServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", localContext ) ctx = resolver.resolve( "uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext" ) smgr = ctx.ServiceManager desktop = smgr.createInstanceWithContext( "com.sun.star.frame.Desktop",ctx) doc = desktop.loadComponentFromURL( "private:factory/scalc","_blank", 0, () ) import unopy XSCRIPTCONTEXT = unopy.ScriptContext(ctx) if 1: get_active_cell() else: unopy.run_script(ctx, "test3.py","" , "user名") ********************************************************
本当にありがとうございました。