Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

In python, I do it like this. Firs, I run a bash script that launches a libreoffice instance that I can connect to:

#/bin/bash
libreoffice "--accept=pipe,name=abraxas;urp;StarOffice.Servicemanager" ~/test.ods &
sleep 3 # we need time to connect
# now we check if any other libreoffice instances are already running
# of course, if an instance is opened in between, 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
    ~/.config/libreoffice/4/user/Scripts/python/my_script.py --close-window
  else # it was not running, kill it all
    ~/.config/libreoffice/4/user/Scripts/python/my_script.py --close-office
  fi

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 )
        """It is assumed libreoffice is run like this from a shell:
        libreoffice "--accept=pipe,name=abraxas;urp;StarOffice.Servicemanager ~/test.ods"
        """
        client = resolver.resolve("uno:pipe,"
                        "name=abraxas;" 
                        "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()
    elif cmd_argument == '--close-window':
        oDoc.close(0)

    """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,

In python, I do it like this. Firs, First, I run a bash script that launches a libreoffice instance that I can connect to:

#/bin/bash
libreoffice "--accept=pipe,name=abraxas;urp;StarOffice.Servicemanager" ~/test.ods &
sleep 3 # we need time to connect
# now # First we check if any other libreoffice instances are already running
# of course, if an instance is opened in between, meanwhile, it will be closed    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

ps cax | grep soffice.bin > /dev/null
if [ $? -eq 0 ]; then # libreoffice is running, so just close the window we opened
    ~/.config/libreoffice/4/user/Scripts/python/my_script.py --close-window
  else # it was not running, kill it all
    ~/.config/libreoffice/4/user/Scripts/python/my_script.py --close-office
  fi

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 )
        """It is assumed libreoffice is run like this from a shell:
        libreoffice "--accept=pipe,name=abraxas;urp;StarOffice.Servicemanager ~/test.ods"
        """
        client = resolver.resolve("uno:pipe,"
                        "name=abraxas;" "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()
d.terminate() # this closes all instances, I think
    elif cmd_argument == '--close-window':
        oDoc.close(0)
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,

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

ps cax | grep soffice.bin > /dev/null
if [ $? -eq 0 ]; then # libreoffice is running, so just close the window we opened
    ~/.config/libreoffice/4/user/Scripts/python/my_script.py --close-window
  else # it was not running, kill it all
    ~/.config/libreoffice/4/user/Scripts/python/my_script.py --close-office
  fi

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,