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
Karolus
edit:
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!!
Edit 2:
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.