オートメーション 
Python スクリプトを OOo 内部で動作させるのではなく外部に置いたスクリプトから OOo に接続して OOo を操作します。
OOo 2.4 を Windows で利用しているときにソケットを通じた接続に失敗します。パイプは使えます。i87894
一応、
import socket
とすると接続できるようです。
環境変数 
OOo 付属の Python ではなく外部の Python を利用するときには幾つかの環境変数を設定しておく必要があります。
Linux 系 OS で本家ビルドの開発版を /opt 以下にインストールした場合には次のようになります。
UNIX 環境では次の環境変数を設定します。
- LD_LIBRARY_PATH: libpyuno.so ファイルサーチ用
/opt/ooo-dev3/program/../basis-link/program:/opt/ooo-dev3/program/../basis-link/ure-link/lib
- URE_BOOTSTRAP: 起動も行うには指定が必要です
vnd.sun.star.pathname:/opt/ooo-dev3/program/fundamentalrc
Windows 環境では PATH に追加します。
- PATH: libpyuno.so ファイルサーチ用
C:\Program Files\OpenOffice.org 3\URE\bin;C:\Program Files\OpenOffice.org 3\Basis\program
- URE_BOOTSTRAP: 起動も行うには指定が必要です
vnd.sun.star.pathname:C:\Program Files\OpenOffice.org 3/program/fundamental.ini
以下は追加の環境変数です。
- UNO_PATH: soffice の実行ファイルがあるディレクトリパス
/opt/ooo-dev3/program
ソケット接続 
Py-UNO では OOo へ TCP/IP 接続して OOo を制御できます。
OOo を次のようなオプションを付けて起動しておかなければいけません。
"-accept=socket,host=localhost,port=2002;urp;StarOffice.ServiceManager"
port=2002 は接続に利用する TCP/IP ポート番号です。
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| 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:
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
|
パイプ接続 
メモリ共有による OOo との接続。OOo を次のようなオプションを付けて起動しておきます。
"-accept=pipe,name=pypipe;urp;StarOffice.ServiceManager"
name=pypipe は使用するパイプ名です。接続時にも同じ名前を使用します。
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| import uno
def connect():
try:
localctx = uno.getComponentContext()
resolver = localctx.ServiceManager.createInstanceWithContext(
"com.sun.star.bridge.UnoUrlResolver",localctx)
ctx = resolver.resolve(
"uno:pipe,name=pypipe;urp;StarOffice.ComponentContext")
except:
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
|
接続方法による違い 
ソケットとパイプ、二つの接続方法の詳細は DevGuide UNO Concepts
を参照してください。
パイプ接続のほうがわずかに早いと書かれています。
次のようなコードで比較してみます。
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| model = desktop.loadComponentFromURL("private:factory/scalc","_default",0,())
model.lockControllers()
model.enableAutomaticCalculation(False)
sheets = model.getSheets()
sheet = sheets.getByIndex(0)
t1 = time.time()
nCols = 100
nRows = 1000
for i in range(nCols):
for j in range(nRows):
sheet.getCellByPosition(i,j).setValue(1.0)
t2 = time.time()
print "Iteration: %s" % (nCols * nRows)
print "Total time: %.3f" % (t2 - t1)
print "An iteration : %.3f" % ((t2 - t1) / (nCols * nRows))
model.unlockControllers()
|
セル 100000 ヶに数値を書き込む処理の結果です。結果は参考程度まで。
接続 | 合計 (秒) | 一回 (ミリ秒) |
ソケット | 265.1 | 265 |
パイプ | 187.9 | 188 |
bootstrap と connection 
起動と接続用。
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
| | from time import sleep
from subprocess import Popen
import uno
import unohelper
from com.sun.star.script.provider import XScriptContext
from com.sun.star.connection import NoConnectException
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 construct_url(connectionType, keys):
if connectionType == "socket":
tcpDelay = keys.get("tcpNoDelay", "0")
host = keys.get("host", "localhost")
port = keys.get("port", "2002")
args = "-accept=socket,host=%s,port=%s,tcpNoDelay=%s;urp;StarOffice.ServiceManager" % (host, port, tcpDelay)
url = "uno:socket,host=%s,port=%s,tcpNoDelay=%s;urp;StarOffice.ComponentContext" % (host, port, tcpDelay)
elif connectionType == "pipe":
pipeName = keys.get("name", "pythonpipe")
args = "-accept=pipe,name=%s;urp;StarOffice.ServiceManager" % pipeName
url = "uno:pipe,name=%s;urp;StarOffice.ComponentContext" % pipeName
else:
print(connectionType)
raise ValueError("unknown connection type: " + connectionType)
return (url, args)
def bootstrap(officePath="soffice", connectionType="socket", **keys):
""" Bootstrapping OpenOffice.org and connect to it. """
if "url" in keys:
url = keys["url"]
else:
url, args = construct_url(connectionType, keys)
ctx = None
for i in range(20):
try:
ctx = connect(url=url)
except NoConnectException:
try:
Popen([officePath, args])
except OSError:
raise Exception("no office executable found: " + officePath)
sleep(1)
if ctx:
break
return ctx
def connect(connectionType="socket", **keys):
""" connect to living OpenOffice.org. """
if "url" in keys:
url = keys["url"]
else:
url, args = construct_url(connectionType, keys)
localctx = uno.getComponentContext()
resolver = localctx.getServiceManager().createInstanceWithContext(
"com.sun.star.bridge.UnoUrlResolver", localctx)
return resolver.resolve(url)
|