This concerns Basic macros. How can I launch python macros from the command line? Libreoffice launches, does not run the macro and does not throw any errors, which is mostly unhelpful.
The answer is rather simple, make them executable and execute them, if it works depends only on their content – you do not need to involve
soffice -blah -spam whatever in any way
the common pattern in python-Scripts to distinguish between “run the Script as itself” and “import only some functionality” is at last in the Scriptfile:
other stuff if __name__ == "__main__": this() that()
in this Case if the script is executed directly it runs only the stuff on module-level and at last the functions
this() and that()
And - sorry - but i have to announce:
If you become familiar with ipython notebook you’ll dont need all that boilerplate in every script!!
Another pattern designed in pythonscript.py for Libreoffice is:
g_exportedScripts = this, that
this pattern make exclusive only the Functions
this and that visible and executable over Libre-GUI
Alright, I figured it out, but this seems to be insanely complex (see my answer bellow)!
Ah, good, thanksI updated the answer.
How would ipython notebooks help? By reusing some of the code? I could do that with pythons files as well, if I needed to, or not? anyway, I am writing only this macro and the code must reside somewhere anyway. Or what am I missing?
You’ll need run the boilerplate only once in the notebook, and after develop some useful parts you put this into Function or Classes …whatever into one “Cell” and put at the Topline of that “Cell” :
%%writefile path/to/your/LO/Scripts/python/yourfilname.py the Rest ....
(ctrl+enter) writes the Cellcontent without 1.Line to the given Path
It seems hackish, but based on this , the following works:
#!/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=some_name;urp;StarOffice.Servicemanager ~/test.ods" """ 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!' """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__": run_all() """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,
This scipt can be run both directly from inside Libreoffice and from the command line (in that case, libreoffice needs to be already running). Something like this works for me:
#!/bin/bash libreoffice "--accept=pipe,name=some_name;urp;StarOffice.Servicemanager" ~/Desktop/test.ods & sleep 3 # we need to wait till libreoffice starts, 3 seconds is more than enough for my computer but it YMMV ~/.config/libreoffice/4/user/Scripts/python/your_macro.py
Do not forget to make this file executable.