How do I make python uno mailmerge have the same output as manual mailmerge? The uno output files still have field codes in them and hidden paragraphs are not hidden

I’ve got a problem with the mailmerged files created using a python uno script. Running the mailmerge within LibreOffice itself using the mailmerge wizard works as in the hidden fields and other fields in the document are flattened/executed and the resulting document has the correct final flattened output.

In contrast, when run with the code below, what is produced is a series of output documents that still have field codes within them and the hidden paragraphs are still visible. Each document is set to the appropriate row of the mailmerge database, much as I get with the preview in LibreOffice when setting up the Mailmerge. Opening these documents on a different machine, the data does not display as it requires access to the backend database first to obtain the field data.

If in my script I set the SaveFilter to, say “HTML (StarWriter)” or “writer_pdf_export” then it flattens the file, but fails to remove the hidden paragraphs from the output.

Please could you help me to replicate the way LibreOffice does the mailmerge but using the uno python interface?

import uno

def mergeit():
    localContext = uno.getComponentContext()
    resolver = localContext.ServiceManager.createInstanceWithContext(
        "", localContext )
    ctx = resolver.resolve( "uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext" )
    smgr = ctx.ServiceManager
    oMailMerge = smgr.createInstanceWithContext( "",ctx)
    oMailMerge.DocumentURL = "file:////home/user/templates/testtemplate.odt"
    oMailMerge.DataSourceName = "jdbcpostgresmailmerge" #name of data source
    oMailMerge.CommandType = 0     #0 = table name, 1 = query name, 3 = SQL command
    oMailMerge.Command = "public.mailmergedata"               
    oMailMerge.OutputType = 2                                  #1 = printer, 2 = file, 3 = email
    oMailMerge.OutputURL = uno.systemPathToFileUrl("/home/user/output/")
    oMailMerge.SaveFilter = "writer8"
    oMailMerge.FileNameFromColumn = True #get file name from data source column
    oMailMerge.FileNamePrefix = "mergefilename"  #name of data source column
    oMailMerge.SaveAsSingleFile = False        #save as multiple files
    # Do a nasty thing before exiting the python process. In case the
    # last call is a oneway call (e.g. see idl-spec of insertString),
    # it must be forced out of the remote-bridge caches before python
    # exits the process. Otherwise, the oneway call may or may not reach
    # the target object.
    # I do this here by calling a cheap synchronous call (getPropertyValue).

def main():

if __name__ == '__main__':

The system is running LibreOffice on Ubuntu 18 x64

Here is how I start LibreOffice before calling my script:

libreoffice --headless --accept="socket,host=localhost,port=2002;urp;"

This is more of a workaround than a true solution. I wasn’t able to make it work with LibreOffice. However, if I change the calling function:


to pass an empty tuple:


Now it can run it on OpenOffice 4.1.6 as a back-end:

./soffice -headless -accept="socket,host=localhost,port=2002;urp;"

and, unlike with LibreOffice, it functions as expected with outputting html, text and pdf types. It also sort of works outputting writer8 files as it is still exporting field codes but even if the data source isn’t there, it is filling in the correct values and is importantly processing the hidden paragraphs correctly.

An unlikely win for OOo 4.1.6 and a fail for LibreOffice