Skip to content Skip to sidebar Skip to footer

How To Call An Existing Libreoffice Python Macro From A Python Script

Currently I call an existing existing LibreOffice macro with this: def OnLOtimestamp(self): try: pid= Popen(['lowriter '''''vnd.sun.star.script:fs2TimeStamp.py$

Solution 1:

Finally, I have a working solution. Ding! Dong!

#!/usr/bin/python3# -*- coding: utf-8 -*-### a python script to run a libreoffice python macro externally#import uno
from com.sun.star.connection import NoConnectException
from com.sun.star.uno  import RuntimeException
from com.sun.star.uno  import Exception
from com.sun.star.lang import IllegalArgumentException
deftest2(*args):
    localContext = uno.getComponentContext()
    localsmgr = localContext.ServiceManager
    resolver =  localsmgr.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", localContext )
    try:
        ctx = resolver.resolve("uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext")
    except NoConnectException as e:
        print ("LibreOffice is not running or not listening on the port given - ("+e.Message+")")
        return
    msp = ctx.getValueByName("/singletons/com.sun.star.script.provider.theMasterScriptProviderFactory")
    sp = msp.createScriptProvider("")
    scriptx = sp.getScript('vnd.sun.star.script:fs2TimeStamp.py$fs2_TimeStamp?language=Python&location=user')
    try:
        scriptx.invoke((), (), ())
    except IllegalArgumentException as e:
        print ("The command given is invalid ( "+ e.Message+ ")")
        returnexcept RuntimeException as e:
        print("An unknown error occurred: " + e.Message)
        returnexcept Exception as e:
        print ("Script error ( "+ e.Message+ ")")

return(None)

test2()

Note: For clarity the existing python script is called fs2TimeStamp.py, it contains 1 (one) function defined as def fs2_TimeStamp(*args): See the line:

scriptx = sp.getScript('vnd.sun.star.script:fs2TimeStamp.py$fs2_TimeStamp?language=Python&location=user')   

and it is stored in $HOME/.config/libreoffice/4/user/Scripts/python

For this solution to work, libreoffice must be running in listening mode, so start libreoffice with a command like:

soffice "--accept=socket,host=127.0.0.1,port=2002,tcpNoDelay=1;urp;"--writer --norestore

OR

nohup soffice "--accept=socket,host=127.0.0.1,port=2002,tcpNoDelay=1;urp;" --writer --norestore &

Alternatively you could use the more direct method (for writer in this example):

lowriter "--accept=socket,host=127.0.0.1,port=2002,tcpNoDelay=1;urp"

OR

nohup lowriter "--accept=socket,host=127.0.0.1,port=2002,tcpNoDelay=1;urp" &

Also note that you must run the script with python3

Solution 2:

This is a simpler and more generic version of the first answer, which was very much slanted to my specific problem, which called a macro, which then talked to another program via TCP before inserting text sent via the TCP connection. This version will run standalone and should be instantly replicable. As before you must start LibreOffice writer in listening mode (see previous answer for options):

lowriter "--accept=socket,host=127.0.0.1,port=2002,tcpNoDelay=1;urp"

This is the external python routine, which must be run with python3:

#!/usr/bin/python3# -*- coding: utf-8 -*-### a python script to run a libreoffice python macro externally# NOTE: for this to run start libreoffice in the following manner# soffice "--accept=socket,host=127.0.0.1,port=2002,tcpNoDelay=1;urp;" --writer --norestore# OR# nohup soffice "--accept=socket,host=127.0.0.1,port=2002,tcpNoDelay=1;urp;" --writer --norestore &#import uno
from com.sun.star.connection import NoConnectException
from com.sun.star.uno  import RuntimeException
from com.sun.star.uno  import Exception
from com.sun.star.lang import IllegalArgumentException
defuno_directmacro(*args):
    localContext = uno.getComponentContext()
    localsmgr = localContext.ServiceManager
    resolver = localsmgr.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", localContext )
    try:
        ctx = resolver.resolve("uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext")
    except NoConnectException as e:
        print ("LibreOffice is not running or not listening on the port given - ("+e.Message+")")
        return
    msp = ctx.getValueByName("/singletons/com.sun.star.script.provider.theMasterScriptProviderFactory")
    sp = msp.createScriptProvider("")
    scriptx = sp.getScript('vnd.sun.star.script:directmacro.py$directmacro?language=Python&location=user')
    try:
        scriptx.invoke((), (), ())
    except IllegalArgumentException as e:
        print ("The command given is invalid ( "+ e.Message+ ")")
        returnexcept RuntimeException as e:
        print("An unknown error occurred: " + e.Message)
        returnexcept Exception as e:
        print ("Script error ( "+ e.Message+ ")")
        print(e)
        returnreturn(None)

uno_directmacro()

This is the LibreOffice python macro directmacro.py which should be located in:

$HOME/.config/libreoffice/4/user/Scripts/python

(assuming use of LibreOffice version 4 here)

The directmacro.py macro:

#!/usr/bin/pythonclassFontSlant():
    from com.sun.star.awt.FontSlant import (NONE, ITALIC,)

defdirectmacro(*args):
#get the doc from the scripting context which is made available to all scripts
    desktop = XSCRIPTCONTEXT.getDesktop()
    model = desktop.getCurrentComponent()
    text = model.Text
    tRange = text.End
    cursor = desktop.getCurrentComponent().getCurrentController().getViewCursor()
    doc = XSCRIPTCONTEXT.getDocument()
    parentwindow = doc.CurrentController.Frame.ContainerWindow

# your cannot insert simple text and text into a table with the same method# so we have to know if we are in a table or not.# oTable and oCurCell will be null if we are not in a table
    oTable = cursor.TextTable
    oCurCell = cursor.Cell
    insert_text = "This is text inserted into a LibreOffice Document\ndirectly from a macro called externally"
    Text_Italic = FontSlant.ITALIC
    Text_None = FontSlant.NONE
    cursor.CharPosture=Text_Italic
    if oCurCell == None: # Are we inserting into a table or not?
        text.insertString(cursor, insert_text, 0)
    else:
        cell = oTable.getCellByName(oCurCell.CellName)
        cell.insertString(cursor, insert_text, False)
    cursor.CharPosture=Text_None
    returnNone

Post a Comment for "How To Call An Existing Libreoffice Python Macro From A Python Script"