Skip to content

Instantly share code, notes, and snippets.

@JannieT
Last active April 27, 2023 14:39
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save JannieT/6fee66dc821fd0fe6af68063920149f0 to your computer and use it in GitHub Desktop.
Environment for scripting LibreOffice with Python
import uno
import sys
def createUnoService(id):
ctx = getContext()
return ctx.ServiceManager.createInstanceWithContext(id, ctx)
def getContext():
# get the uno component context from the PyUNO runtime
localContext = uno.getComponentContext()
# create the UnoUrlResolver
resolver = localContext.ServiceManager.createInstanceWithContext(
"com.sun.star.bridge.UnoUrlResolver", localContext )
# connect to the running office
return resolver.resolve( "uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext" )
def getDesktop():
ctx = getContext()
# get the central desktop object
return ctx.ServiceManager.createInstanceWithContext( "com.sun.star.frame.Desktop",ctx)
def getFrame():
desktop = getDesktop()
return desktop.getCurrentFrame();
def getModel():
desktop = getDesktop()
# access the current writer document
return desktop.getCurrentComponent()
def lastException2String():
(excType,excInstance,excTraceback) = sys.exc_info()
ret = str(excType) + ": "+str(excInstance) + "\n" + \
uno._uno_extract_printable_stacktrace( excTraceback )
return ret
def printInterfaces(obj):
"""
Thanks to Jamie Boyle https://documenthacker.wordpress.com
"""
text = str(obj)
interfacesBlock = [z for z in text.split(' ') if z.startswith('supportedInterfaces=')][0]
interfaceNames = []
for longName in interfacesBlock[interfacesBlock.find('{')+1:interfacesBlock.find('}')].split(','):
interfaceName = longName[longName .rfind('.')+1:]
if interfaceName[0]=='X':
interfaceName = interfaceName[1:]
interfaceNames.append(interfaceName)
interfaceNames.sort() #Sort all the names alphabetically
for interfaceName in interfaceNames:
if interfaceName[0]=='X':
print(interfaceName[1:])
else:
print(interfaceName)
def printObjectProperties(obj):
#Get the properties
properties = list(obj.getPropertySetInfo().getProperties())
#Sort alphabetically by name
properties.sort(key = lambda x:x.Name)
longest_len = max([len(z.Name) for z in properties])
for property in properties:
print(property.Name.ljust(longest_len)+' -'+str(property.Type))
from zipfile import ZipFile
import shutil
import sys
import os
if len(sys.argv) < 3:
print("Usage: {} scriptfile hostdocument".format(sys.argv[0]))
exit()
MACRO_FILE = sys.argv[1]
DOCUMENT_FILE = sys.argv[2]
MANIFEST_PATH = 'META-INF/manifest.xml';
EMBED_PATH = 'Scripts/python/' + MACRO_FILE;
hasMeta = False
with ZipFile(DOCUMENT_FILE) as bundle:
# grab the manifest
manifest = []
for rawLine in bundle.open('META-INF/manifest.xml'):
line = rawLine.decode('utf-8');
if MACRO_FILE in line:
hasMeta = True
if ('</manifest:manifest>' in line) and (hasMeta == False):
for path in ['Scripts/','Scripts/python/', EMBED_PATH]:
manifest.append('<manifest:file-entry manifest:media-type="application/binary" manifest:full-path="{}"/>'.format(path))
manifest.append(line)
# remove the manifest and script file
with ZipFile(DOCUMENT_FILE + '.tmp', 'w') as tmp:
for item in bundle.infolist():
buffer = bundle.read(item.filename)
if (item.filename not in [MANIFEST_PATH, EMBED_PATH]):
tmp.writestr(item, buffer)
# os.replace(DOCUMENT_FILE + '.tmp', DOCUMENT_FILE); python 3.3+
os.remove(DOCUMENT_FILE);
shutil.move(DOCUMENT_FILE + '.tmp', DOCUMENT_FILE)
with ZipFile(DOCUMENT_FILE, 'a') as bundle:
bundle.write(MACRO_FILE, EMBED_PATH)
bundle.writestr(MANIFEST_PATH, ''.join(manifest))
print("Added the script {} to {}".format(MACRO_FILE, DOCUMENT_FILE))
#!/usr/bin/env bash
PROJECT_FOLDER="/Users/jannie/Workshop/speng"
SAMPLE_FOLDER="/Applications/LibreOffice.app/Contents/Resources/Scripts/python"
TEMPLATE_FOLDER="~/Library/Application\ Support/LibreOffice/4/user/template"
SCRIPT="scriptlight.py"
HOSTING_DOCUMENT="se.ott"
usage () {
echo "Usage: speng (start|run <function>|deploy|open)"
}
case "$1" in
start)
/Applications/LibreOffice.app/Contents/MacOS/soffice --writer --accept="socket,host=localhost,port=2002;urp;StarOffice.ServiceManager"
;;
run)
/Applications/LibreOffice.app/Contents/MacOS/python -c "import scriptlight; scriptlight.$2()"
;;
deploy)
cd $PROJECT_FOLDER
python push_macro.py $SCRIPT $HOSTING_DOCUMENT
;;
open)
edit . $SAMPLE_FOLDER
;;
*)
# test if script is sourced
if [[ $0 = ${BASH_SOURCE} ]] ; then
usage
else
cd $PROJECT_FOLDER
fi
;;
esac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment