So there are numerous questions how to convert ODT to PDF via command line. I successfully used
soffice --headless --convert-to pdf:"writer_pdf_Export:SelectPdfVersion=1" --outdir outdir testDocument.odt
However my document contains user defined variables that are injected into the text using fields. I would like to set such variable value via command line so that at PDF generation the correct text is contained. I have done similar stuff on MS Word, but how would this work in Writer?
And if it helps, I can move to custom properties instead of variables - but I would still have to set them on the CLI.
What failed for me was
soffice --headless --convert-to "odt:{\"Version\":{\"type\":\"string\",\"value\":\"1.0\"}}" ReadMe.odt
convert /home/queeg/ReadMe.odt -> /home/queeg/ReadMe.odt using filter : {"Version":{"type":"string","value":"1.0"}}
Overwriting: /home/queeg/ReadMe.odt
Error: Please verify input parameters... (SfxBaseModel::impl_store <file:///home/queeg/ReadMe.odt> failed: 0x81a(Error Area:Io Class:Parameter Code:26) ./sfx2/source/doc/sfxbasemodel.cxx:3202 ./sfx2/source/doc/sfxbasemodel.cxx:1775)
This command did not error out but also seemed to have no effect on my document. It did neither set the custom property Version
nor the custom variable Version
:
soffice --headless --convert-to "pdf:draw_pdf_Export:{\“Version\”:{\“type\”:\“string\”,\“value\”:\“draft\”}}" ReadMe.odt
convert /home/queeg/ReadMe.odt -> /home/queeg/ReadMe.pdf using filter : draw_pdf_Export:{\“Version\”:{\“type\”:\“string\”,\“value\”:\“draft\”}}
Overwriting: /home/queeg/ReadMe.pdf
So I found a solution based on https://python-ooo-dev-tools.readthedocs.io/en/latest/index.html that I want to share with others and my future self.
It consists of a python script that can load a document, set user-defined properties and save the document back as ODT, or PDF or any other supported output format.
For installation on a fresh Ubuntu system, run
sudo apt-get install pip3
sudo pip install ooo-dev-tools
Then install this script:
#!/bin/python3
import sys
from ooodev.utils.lo import Lo
from ooodev.utils.info import Info
from com.sun.star.beans import XPropertySet
from com.sun.star.beans import XPropertyAccess
doc = None
def main() -> int:
print (sys.argv)
with Lo.Loader(Lo.ConnectSocket(headless=True)) as loader:
i = 0
while i < len(sys.argv):
arg = sys.argv[i]
match arg:
case "--load":
i=i+1
docname = sys.argv[i]
print("loading " + docname)
doc = Lo.open_doc(fnm=docname, loader=loader)
case "--set":
i=i+1
val = sys.argv[i]
items = val.split("=")
name = items[0]
value = items[1]
print("setting " + name + "=>" + value)
user_props = Info.get_user_defined_props(doc) # XPropertyContainer
ps = Lo.qi(XPropertySet, user_props, True)
try:
ps.setPropertyValue(name, value)
except Exception:
pa = Lo.qi(XPropertyAccess, user_props, True)
names = []
for propertyvalue in pa.getPropertyValues():
names.append(propertyvalue.Name)
print ("Cannot set property '" + name + "'. Known properties are ", names)
return 1
case "--save":
i=i+1
docname = sys.argv[i]
print("saving " + docname)
Lo.save_doc(doc=doc, fnm=docname)
case _:
print (i, sys.argv[i])
i=i+1
return 0
if __name__ == "__main__":
raise SystemExit(main())
Finally run the code like this:
convert.py --load mydoc.odt --set propname=propvalue -save mydoc.pdf
Be aware you can use all the options multiple times and they are evaluated from left to right. That means you can load a document, set multiple properties, save it into two output documents, load the next…