「Web出版サイト」ベータ公開

Q&A集[?]

当サイトでのご質問の受付は終了しました

すべてのコンテンツを読み込み専用としたため、回答欄からも投稿できません

Apache OpenOffice/LibreOfficeのご質問はそれぞれのフォーラムへご投稿ください

質問コーナー

サイト内検索

分類メニュー

関連サイト


本日:1
昨日:0
総数:2506
現在:2


EclipseからOOoのPythonマクロの実行方法について教えて下さい。

ページOpenOffice.org FAQの登録ページ
投稿者new_OOo3
分類
edit/refer
優先順位
edit/refer
状態
edit/refer
カテゴリー
edit/refer
投稿日2010-08-15 21:06:28 (日)
OSWindowsXP SP3
依存するページfaq/5/461
バージョン
edit/refer

メッセージ

回答ページでは行末に「~」を付加する必要はありません

お世話になります。 以前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が表示されました。

ErrorMessage01.png

理解度が悪く何度もお世話になりますが、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から実行できる様になりました。

07automation01.png


また、以前にご教示頂きましたCalcでのActive CellのAddressを取得するmacroもautomationにて実施出来ましたので参考として以下に記させて頂きます。

07automation02.png


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名")

********************************************************



本当にありがとうございました。

お名前:
題名:


添付ファイル: file07automation02.png 830件 [詳細] file07automation01.png 786件 [詳細] fileErrorMessage01.png 833件 [詳細]