Top > OOoPython > OverView

Python-UNO 概要 Edit

OpenOffice.org と Python 関連概要

概要 Edit

Python-UNO (Py-UNO) は Python-UNO ブリッジを介して python から OpenOffice.org API を利用する OOo-Python 間の仲立ちをしてくれます。単純に Python から OOo を操作できるとみなしてかまいません。

使い方は自分で調べるという人のためにいくつかページを挙げておきます。

Python-UNO ブリッジは C++ で書かれたコードなので高速に動作します。また、スクリプトの実行速度は OOo Basic と比較できないほど早いです (C++、Java などとは比較しません)。

OpenOffice.org の Windows パッケージではわざわざ取り除かなければ Python が一緒にインストールされます。Python 2.3.4 の実行環境がついてきます。OOo 3.1 から Python 2.6.1 になりました。Python 標準モジュールのうち利用できないものがいくつかあります。

また、Linux などの環境では Py-UNO パッケージをインストールしておく必要があります。

Py-UNO でできること Edit

Py-UNO では次の三種類のことができます。

マクロとしてというのは、OOo Basic で書いたマクロのように実行できるということです。また、UNO コンポーネント作成は新しいサービスを実装できます。Py-UNO bridge を介してというのは、OOo と関係の無い Python スクリプトからドキュメントを作成するために OOo を利用できることになります。

日本語 Edit

OOo に付属している Python は 2.3.5 のため日本語文字コードの取り扱いがデフォルトではうまくいきません。OOo 3.1 以降では Python 2.6.1 なので問題ありません。

日本語などの文字列をソースに入れる場合には次のようにエンコードを utf8 に設定します。

  0
  1
 #!
 # -*- coding: utf_8 -*-

また、shift_jis や euc_jp などの文字コードを指定して decode や encode もできません。OOo に付属のPython が 2.4 系以上にアップデートされればデフォルトで利用できるようになります。

また、OOo 2.4 系では各 Linux ディストリビューションが独自にビルドしている OOo ではシステムの Python を利用していて Python 2.4, 2.5 系を使用している場合もあります。Ubuntu 8.0.2 (?) では Python 2.5.2、Momonga Linux 5 beta1 では Python 2.5.1 ? などが利用されています。

各種取得 Edit

各種いろいろなものを Py-Uno で利用する方法。OOo Basic で行う場合と対比させてみます。

uno や unohelper は OOo の program ディレクトリに置かれています。利用に際して import しておきます。

import uno
import unohelper

XSCRIPTCONTEXT Edit

Scripting Framework のスクリプトで使われる XSCRIPTCONTEXT グローバル変数は Py-UNO でも利用できます。これを使うのはマクロとして実行するときです。

現在のドキュメントを取得します。

document = XSCRIPTCONTEXT.getDocument()

StarDesktop.getCurrentComponent() 'OOo Basic

デスクトップ com.sun.star.frame.Desktop サービスを取得します。

desktop = XSCRIPTCONTEXT.getDesktop()

StarDesktop 'OOo Basic
CreateUnoService("com.sun.star.frame.Desktop") 'another

コンポーネントコンテキストを取得します。

ctx = XSCRIPTCONTEXT.getComponentContext()

GetDefaultContext() 'OOo Basic

サービスマネージャ Edit

MultiServiceFactory を利用するには次のようにします。ctx はコンポーネントコンテキストです。

smgr = ctx.ServiceManager
oServiceManager = GetProcessServiceManager() ' OOo Basic

サービス Edit

サービスマネージャから createInstanceWithContext メソッドで作成します。

desktop = smgr.createInstanceWithContext("com.sun.star.frame.Desktop",ctx)
oDesktop = CreateUnoService("com.sun.star.frame.Desktop") 'OOo Basic

struct Edit

struct の作成
uno.createUnoStruct("com.sun.star.awt.Size")

または、

from com.sun.star.beans import PropertyValue
porp = PropertyValue()

() が必要です。

OOo Basic では

CreateUnoStruct("com.sun.star.awt.Size")

や Dim ... New As ...

タイプ名が []com.sun.star.beans.PropertyValue などのシークエンスが必要な時には一つずつ作成します。

from com.sun.star.beans import PropertyValue

args = []
a1 = PropertyValue()
a1.Name = "InputStream"
a1.Value = ioin
a2 = PropertyValue()
a2.Name = "FilterName"
a2.Value = "calc8"

args.append(a1)
args.append(a2)

desktop.loadComponentFromURL("private:stream", "_blank",0, tuple(args))

Basic では簡単に

Dim args(1) As New com.sun.star.beans.PropertyValue

enum Edit

enum は import します。

from com.sun.star.awt.WindowClass import TOP as UNO_WC_TOP

また、次のようにも出来ます。

uno.Enum("com.sun.star.awt.WindowClass","TOP")

OOo Basic では

nEnum = com.sun.star.awt.WindowClass.TOP

With ステートメントも利用できます。

Constants Edit

enum 同様に import します。

from com.sun.star.beans.MethodConcept import ALL as UNO_MC_ALL

また、

uno.getConstantByName("com.sun.star.beans.MethodConcept.ALL")

OOo Basic は enum と同様。

配列 Edit

配列というより UNO の sequence 型。API 関数から戻される sequence は Py-UNO ではタプルになります。また、メソッドの引数として与えるときもタプルで与えます。tuple、list などで必要に応じて変換したりしなければいけません。

edit_model.setPropertyValues(
  ("MultiLine",),
  (True,) )
oEdit_model.setPropertyValues( _
  Array("MultiLine"), Array(true) ) ' OOo Basic

boolean Edit

True または False

OOo Basic だと大文字と小文字に依存しませんが、python だと syntax error になります。

string Edit

文字列は python unicode。8 bit を与えたときは自動的に変換されます。

Char Edit

文字というか char は uno.py で定義されている Char クラスのインスタンスです。実際の文字を取得するには value attribute を取得します。Char は普段は見かけませんがキーリスナーやマウスリスナーを利用しているとと時々遭遇します。

ByteSequence Edit

Python ではバイトは文字として扱うが、UNO 側から渡されたバイトシークエンスは uno.py で定義された ByteSequence クラスのインスタンスになっている。値を取得するには value attribute を参照する。詳細は uno.py 参照。

インターフェース Edit

サービスを実装したり、リスナーを利用するときにはインターフェースを継承したクラスを作成する必要があります。インターフェースはインポートします。

import unohelper
from com.sun.star.awt import XActionListener

class aclistener(unohelper.Base,XActionListener):
	def __init__(self,ctx):
		self.ctx = ctx
		return
	
	def actionPerformed(self,ev):
		pass
	
	def disposing(self,ev):
		pass

URL <-> System FilePath Edit

システムパスから URL

unohelper.systemPathToFileUrl( systemPath )

URL からシステムパス

unohelper.fileUrlToSystemPath( url )

引数と返り値 Edit

API メソッドの引数に [out] のものが時々ありますが、Py-UNO では元々の返り値を加えたタプルで返ります。

Basic では

aURL = CreateUnoStruct("com.sun.star.util.URL")
aURL.Complete = ".uno:Paste"
CreateUnoService("com.sun.star.util.URLTransformer")._
   parseStrict(aURL)
'parseStrict の返り値は void で、最初の引数が [inout]

Py-UNO だと

aURL = uno.createUnoStruct("com.sun.star.util.URL")
aURL.Complete = ".uno:Paste"
transformer = smgr.createInstanceWithContext(
   "com.sun.star.util.URLTransformer",ctx)
dummy,aURL = transformer.parseStrict(aURL)
# 元々の返り値,out のある引数の値
# ここでは dummy は void (Python では None)

詳細は上記リンク参照。

ダイアログ Edit

com.sun.star.awt.DialogProvider サービスを利用してダイアログエディタで作成したダイアログが利用できます。ボタンなどのリスナーは UNO コンポーネントを設定していないのであればリスナーを設定する必要があります。

def dialog_test():
	ctx = XSCRIPTCONTEXT.getComponentContext()
	smgr = ctx.ServiceManager
	dialogprovider = smgr.createInstanceWithContext(
	   "com.sun.star.awt.DialogProvider",ctx)
	url = "vnd.sun.star.script:Standard.Dialog1?location=application"
	dialog = dialogprovider.createDialog(url)
	dialog.execute()

ダイアログを指定する URL はダイアログライブラリの URI でなくローカルファイルでも可能です。たとえば、file:///home/huga/Desktop/dlg.xdl などとします。拡張機能でダイアログを利用するがダイアログライブラリとしてインストールしたくないときに利用できます。

実行するスクリプト一覧に表示する関数名 Edit

OOo で python スクリプトをマクロとして実行するときは関数定義を実行する形になります。一覧に表示したい名前を制限するには次のようにします。

g_exportedScripts = calc_thread,

タプルで表示したい関数名を指定します。g_exportedScripts の変数名を変えてはいけません。

import Edit

2.4 から Python の標準ライブラリ以外の独自のファイルインポートが容易になりました。

実行するスクリプトファイルと同じディレクトリに pythonpath ディレクトリを作成してインポートしたいファイルを配置します。

test.py (実行するスクリプトファイル)
--pythonpath/inc.py (インポートするファイル)
import inc

ディレクトリの代わりに pythonpath.zip ファイルを作成してインポートしたいファイルを入れておくこともできます。

Framework script でなく Py-UNO コンポーネントのときにも同様にインポートできます。

2.4 で修正済み該当 issue i76281

import したファイルは拡張機能パッケージがインストールされるときにバイトコードにコンパイルされます。

メッセージボックス Edit

簡単なメッセージボックスは 2.3 以降では次のように簡単に表示できます。

  0
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
import uno
 
 
def test10():
    message(XSCRIPTCONTEXT.getDesktop(),"message","title")
 
 
def message(desktop,msg="",title=""):
    frame = desktop.getCurrentFrame()
    win = frame.getContainerWindow()
    toolkit = win.getToolkit()
    rect = uno.createUnoStruct("com.sun.star.awt.Rectangle")
    msgbox = toolkit.createMessageBox( 
        win,rect,"messbox",1,title,msg)
    msgbox.execute()

例外 Edit

基本的に Python の try、except、else、raise を使う。UNO での例外は com.sun.star.uno.Exception をすべての親クラスとなっているが、Py-UNO では Python の Exception も継承されているので同じように取り扱えます。

また、利用する例外は struct と同じように import しておきます。例は以下参照。

http://udk.openoffice.org/python/python-bridge.html#exception

例外を raise で送出できます。

  0
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
import uno
import unohelper
 
from com.sun.star.lang import XServiceInfo
from com.sun.star.container import XIndexContainer
from com.sun.star.uno.TypeClass import STRING as TC_STRING
from com.sun.star.lang import \
    IndexOutOfBoundsException as UNO_IndexOutOfBoundsException, \
    IllegalArgumentException as UNO_IllegalArgumentException, \
    IndexOutOfBoundsException as UNO_IndexOutOfBoundsException
 
IMPLE_NAME = u'mytools.service.Test1'
 
 
class new_service(unohelper.Base, XIndexContainer, XServiceInfo):
    """This service implements container that retains strings with their indexes."""
    def __init__(self):
        print "initialize..."
        self.cont = []
    
    def getImplementationName(self):
        return IMPLE_NAME
    
    def supportsService(self, name):
        return name == IMPLE_NAME
    
    def getSupportedServiceNames(self):
        return (IMPLE_NAME,)
    
    def insertByIndex(self, i, item):
        if isinstance(item, basestring):
            if 0 <= i <= len(self.cont):
                self.cont.insert(i, item)
            else:
                uno_e = UNO_IndexOutOfBoundsException()
                uno_e.Message = u'Index out of bounds. %s' % len(self.cont)
                raise uno_e
        else:
            uno_e = UNO_IllegalArgumentException()
            uno_e.ArgumentPosition = 1
            raise uno_e
    
    def removeByIndex(self, i):
        if 0 <= i < len(self.cont):
            del self.cont[i]
        else:
            uno_e = UNO_IndexOutOfBoundsException()
            uno_e.Message = u'Index out of bounds. %s' % len(self.cont)
            raise uno_e
    
    def replaceByIndex(self, i, item):
        if isinstance(item, basestring):
            if 0 <= i < len(self.cont):
                self.cont[i] = item
            else:
                uno_e = UNO_IndexOutOfBoundsException()
                uno_e.Message = u'Index out of bounds. %s' % len(self.cont)
                raise uno_e
        else:
            uno_e = UNO_IllegalArgumentException()
            uno_e.ArgumentPosition = 1
            raise uno_e
    
    def getCount(self):
        return len(self.cont)
    
    def getByIndex(self, i):
        try:
            return self.cont.get(i)
        except ValueError,e:
            uno_e = UNO_IndexOutOfBoundsException()
            uno_e.Message = u'Index out of bounds. %s' % len(self.cont)
            raise uno_e
    
    def getElementType(self):
        return uno.Type(u'string', TC_STRING)
    
    def hasElements(self):
        if len(self.cont) > 0:
            return True
        return False

標準出力 Edit

Windows 環境では標準出力が利用できません。一方、Linux などの環境ではシェルから OpenOffice.org を起動すれば標準出力が利用できます。

sys.stdout を適当な I/O オブジェクトと置き換えると Windows 環境でもログを取らずにリアルタイムで標準出力が参照できます。OOoPython/mytools/sstdout


Reload   New Lower page making Edit Freeze Diff Upload Copy Rename   Front page List of pages Search Recent changes Backup   Help   RSS of recent changes