UIを立ち上げることなくods
ファイルを書き換える。
成果物
コード
run.sh
soffice --calc --headless "--accept=pipe,name=librepipe;urp;" & { sleep 1 ./run_from_terminal.py jobs kill %% }
run_from_terminal.py
#!/usr/bin/env python3 # -*- coding: utf-8 -*- import uno import unohelper from pythonscript import ScriptContext import os.path def connect_script_context(host='localhost', port='2002', namedpipe=None): UNO_RESOLVER = "com.sun.star.bridge.UnoUrlResolver" UNO_DESKTOP = "com.sun.star.frame.Desktop" localCtx = uno.getComponentContext() localSmgr = localCtx.ServiceManager resolver = localSmgr.createInstanceWithContext(UNO_RESOLVER, localCtx) if namedpipe is None: uno_string = 'uno:socket,host=%s,port=%s;urp;StarOffice.ComponentContext' % (host, port) else: uno_string = 'uno:pipe,name=%s;urp;StarOffice.ComponentContext' % namedpipe ctx = resolver.resolve(uno_string) smgr = ctx.ServiceManager XSCRIPTCONTEXT = ScriptContext(ctx, smgr.createInstanceWithContext(UNO_DESKTOP, ctx), None) return XSCRIPTCONTEXT file = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'test.ods') url = unohelper.systemPathToFileUrl(file) XSCRIPTCONTEXT = connect_script_context(namedpipe='librepipe') desktop = XSCRIPTCONTEXT.getDesktop() doc = desktop.loadComponentFromURL(url, "_blank", 0, ()) sheet = doc.getSheets().getByIndex(0) sheet.getCellByPosition(0,0).Value = 999 doc.store()
解説
.sh
soffice
でLibreOfficeを起動する。その際、バックグラウンドかつ名前付きパイプでデータ仲介する。
シェルにて&
で並列実行する。LibreOfficeを起動したまま、Pythonマクロを実行する。最後に現在の並列実行中ジョブをkillする。
soffice --calc --headless "--accept=pipe,name=librepipe;urp;" & { sleep 1 ./run_from_terminal.py jobs kill %% }
.py
Pythonからマクロを実行するためにはまずScriptContext
のインスタンスを取得する。
run_from_terminal.py
import uno import unohelper from pythonscript import ScriptContext def connect_script_context(host='localhost', port='2002', namedpipe=None): UNO_RESOLVER = "com.sun.star.bridge.UnoUrlResolver" UNO_DESKTOP = "com.sun.star.frame.Desktop" localCtx = uno.getComponentContext() localSmgr = localCtx.ServiceManager resolver = localSmgr.createInstanceWithContext(UNO_RESOLVER, localCtx) if namedpipe is None: uno_string = 'uno:socket,host=%s,port=%s;urp;StarOffice.ComponentContext' % (host, port) else: uno_string = 'uno:pipe,name=%s;urp;StarOffice.ComponentContext' % namedpipe ctx = resolver.resolve(uno_string) smgr = ctx.ServiceManager XSCRIPTCONTEXT = ScriptContext(ctx, smgr.createInstanceWithContext(UNO_DESKTOP, ctx), None) return XSCRIPTCONTEXT XSCRIPTCONTEXT = connect_script_context(namedpipe='librepipe')
connect_script_context
の引数namedpipe
には、シェルのsoffice
コマンドの--accept=pipe,name=
で渡した名前付きパイプと同じ値librepipe
を渡す。
次に、XSCRIPTCONTEXT
からセルに値をセットするまで。
desktop = XSCRIPTCONTEXT.getDesktop() doc = desktop.loadComponentFromURL(url, "_blank", 0, ()) sheet = doc.getSheets().getByIndex(0) sheet.getCellByPosition(0,0).Value = 999
最後に、所定のods
ファイルを開いてから保存する方法。
import os.path file = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'test.ods') url = unohelper.systemPathToFileUrl(file) ... doc.store()
所感
LibreOfficeとマクロをバックグラウンドで起動した。既存のods
ファイルを自動的に変更することができた。
次は指定したパスにods
ファイルを作成するマクロを書きたい。
それにしても、ほぼググってコピペしただけなのでAPIがさっぱりわからない。たぶんココをみればいいんだろうけど。概念がわからない。Desctop
とかComponentContext
とか何なの?
情報源
- https://qiita.com/shota243/items/286ae4083556ae98b611
- http://www7b.biglobe.ne.jp/~whitetiger/ex/liboffice020.html
- https://qiita.com/zanjibar/items/fa4d4c690cd07828d4f9
- https://api.libreoffice.org/docs/idl/ref/interfacecom_1_1sun_1_1star_1_1script_1_1provider_1_1XScriptContext.html
対象環境
- Raspbierry pi 4 Model B
- Raspbian buster 10.0 2019-09-26 ※
- bash 5.0.3(1)-release 学習まとめ
- LibreOffice 6.1.5.2 ※
$ uname -a Linux raspberrypi 4.19.97-v7l+ #1294 SMP Thu Jan 30 13:21:14 GMT 2020 armv7l GNU/Linux