I wrote a small Python program today, to see if a could create a workaround for a problem i have in Java. I’ve written a couple of Java applications that use OpenOffice’s API to create ODF and MS-Word documents. The OpenOffice API that i used in Java is pretty horrible: very verbose, not intuitive. You can’t use intellisense/autocomplete, instead you query interfaces, that you just have to know exist. I documented some examples here: Getting started using openoffice in java, Mailmerge MS-Word template using OpenOffice and Java.
To my surprise, the python api doesn’t require you to use the whole query interface nonsense. Makes you code a lot smaller and more readable.
Here’s an example that replaces database field in a document (similar to the example here: Mailmerge MS-Word template using OpenOffice and Java).
#!/usr/bin/python
import sys
import uno
from os import getcwd
from unohelper import Base, systemPathToFileUrl, absolutize
from com.sun.star.beans import PropertyValue, UnknownPropertyException
from com.sun.star.uno import Exception as UnoException, RuntimeException
localContext = uno.getComponentContext()
resolver = localContext.ServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", localContext )
ctx = resolver.resolve( "uno:socket,host=localhost,port=8100;urp;StarOffice.ComponentContext" )
smgr = ctx.ServiceManager
desktop = smgr.createInstanceWithContext("com.sun.star.frame.Desktop", ctx )
inProps = PropertyValue( "Hidden" , 0 , True, 0 ),
fileUrl = absolutize(systemPathToFileUrl( getcwd() ) ,"letter1.ott")
doc = desktop.loadComponentFromURL( fileUrl , "_blank", 0, inProps )
fields = doc.getTextFields().createEnumeration()
while fields.hasMoreElements():
field = fields.nextElement()
fieldname = field.getPresentation(0)
try:
isDatabaseField = field.getPropertyValue("DataBaseFormat")
except UnknownPropertyException :
isDatabaseField = False
if isDatabaseField:
try:
# this is incorrect usage of insertString
# doc.Text.insertString(field.getAnchor(),"New value for " + fieldname,1)
# this is the correct approach
fieldAnchor = field.getAnchor()
fieldAnchor.Text.insertString(fieldAnchor,"New value for " + fieldname,1)
except RuntimeException, e:
print "RuntimeException while to replacing field: " + e.Message
# save document
outProps = PropertyValue( "Overwrite" , 0 , True, 0 ),
saveUrl = absolutize(systemPathToFileUrl( getcwd() ) ,"letter1.odt")
doc.storeToURL(saveUrl, outProps)
~~Beware of this code though, it throws a RuntimeException when trying to replace a database field in the header of a document. So, in that sense, Python is no better than Java.~~
Update: a reply on the openoffice forum put me on the right track. My usage of insertString was incorrect. I’ve fixed the code above.