In python, I do it like this. First, I run a bash script that launches a libreoffice instance that I can connect to:
#/bin/bash
# First we check if any other libreoffice instances are already running
# of course, if an instance is opened meanwhile, it will be closed.
ps cax | grep soffice.bin > /dev/null
if [ $? -eq 0 ]; then # libreoffice is running, so just close the window we opened
arg="--close-window"
else # it was not running, kill it all
arg="--close-office"
fi
libreoffice "--accept=pipe,name=some_name;urp;StarOffice.Servicemanager" ~/test.ods &
sleep 3 # we need time to connect
~/.config/libreoffice/4/user/Scripts/python/vytvor_fakturu.py $arg
Credit for checking if the process is running goes here.
my_script.py is then (largely based on this) like this:
#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""In Libreoffice 4, python3 is default, so this script needs to be python3 too
Unicode is just good practise.
I guess this line is different on Windows."""
import uno
from pythonscript import ScriptContext
import sys
def connect_to_office():
"""We connect to libreoffice only when run externally.
If that is the case, XSCRIPTCONTEXT is not in global scope."""
if not 'XSCRIPTCONTEXT' in globals():
localContext = uno.getComponentContext()
resolver = localContext.ServiceManager.createInstanceWithContext(
'com.sun.star.bridge.UnoUrlResolver', localContext )
client = resolver.resolve("uno:pipe,"
"name=some_name;"
"urp;"
"StarOffice.ComponentContext")
global XSCRIPTCONTEXT
XSCRIPTCONTEXT = ScriptContext(client, None, None)
"""this is the macro that would be run firectly from libreoffice"""
def run_all():
connect_to_office()
oDoc = XSCRIPTCONTEXT.getDocument()
"""I assume a calc file here, this prints Hello world to cell A1"""
oSheet = oDoc.CurrentController.ActiveSheet
oCell = oSheet.getCellRangeByName("A1")
oCell.String = 'Hello world!'
if cmd_argument == '--close-office':
oDoc.close(0) # if we do not close the document first, libreoffice will ask if we want to save changes
d = XSCRIPTCONTEXT.getDesktop()
d.terminate() # this closes all instances, I think
elif cmd_argument == '--close-window':
oDoc.close(0) # this just closes the document we connected to but soffice.bin will continue to run
"""Libreoffice allows to run functions as macros, but in a script
executed from a shell, any function needs to be run, but we must
make sure it is not run twice in case it is run directly
from libreoffice."""
if __name__ == "__main__":
if len(sys.argv) > 1: # do not throw exceptions when the script is run without arguments
run_all(sys.argv[1])
"""Make only this macro visible to libreoffice UI.
I.e., it hides connecto_to_office macro.
The comma at the end is important."""
g_exportedScripts = run_all,