问题
This question is focused on Windows + LibreOffice + Python 3.
I've installed LibreOffice (6.3.4.2), also
pip install unoconv
and pip install unotools
(pip install uno
is another unrelated library), but still I get this error after import uno
:
ModuleNotFoundError: No module named 'uno'
More generally, and as an example of use of UNO, how to open a .docx document with LibreOffice UNO and export it to PDF?
I've searched extensively on this since a few days, but I haven't found a reproducible sample code working on Windows:
headless use of
soffice.exe
, see my question+answer Headless LibreOffice very slow to export to PDF on Windows (6 times slow than on Linux) and the notes on the answer: it "works" withsoffice.exe --headless ...
but something closer to a COM interaction (Component Object Model) would be useful for many applications, thus this question hereRelated forum post, and LibreOffice: Programming with Python Scripts, but the way uno should be installed on Windows, with Python, is not detailed; also Detailed tutorial regarding LibreOffice to Python macro writing, especially for Calc
I've also tried this (unsuccessfully): Getting python to import uno / pyuno:
import os os.environ["URE_BOOTSTRAP"] = r"vnd.sun.star.pathname:C:\Program Files\LibreOffice\program\fundamental.ini" os.environ["PATH"] += r";C:\Program Files\LibreOffice\program" import uno
回答1:
In order to interact with LibreOffice, start an instance listening on a socket. I don't use COM much, but I think this is the equivalent of the COM interaction you asked about. This can be done most easily on the command line or using a shell script, but it can also work with a system call using a time delay and subprocess.
chdir "%ProgramFiles%\LibreOffice\program\"
start soffice -accept=socket,host=localhost,port=2002;urp;
Next, run the installation of python that comes with LibreOffice, which has uno
installed by default.
"C:\Program Files\LibreOffice\program\python.exe"
>> import uno
If instead you are using an installation of Python on Windows that was not shipped with LibreOffice, then getting it to work with UNO is much more difficult, and I would not recommend it unless you enjoy hacking.
Now, here is all the code. In a real project, it's probably best to organize into classes, but this is a simplified version.
import os
import uno
from com.sun.star.beans import PropertyValue
def createProp(name, value):
prop = PropertyValue()
prop.Name = name
prop.Value = value
return prop
localContext = uno.getComponentContext()
resolver = localContext.ServiceManager.createInstanceWithContext(
"com.sun.star.bridge.UnoUrlResolver", localContext)
ctx = resolver.resolve(
"uno:socket,host=localhost,port=2002;urp;"
"StarOffice.ComponentContext")
smgr = ctx.ServiceManager
desktop = smgr.createInstanceWithContext(
"com.sun.star.frame.Desktop", ctx)
dispatcher = smgr.createInstanceWithContext(
"com.sun.star.frame.DispatchHelper", ctx)
filepath = r"C:\Users\JimStandard\Desktop\Untitled 1.docx"
fileUrl = uno.systemPathToFileUrl(os.path.realpath(filepath))
uno_args = (
createProp("Minimized", True),
)
document = desktop.loadComponentFromURL(
fileUrl, "_default", 0, uno_args)
uno_args = (
createProp("FilterName", "writer_pdf_Export"),
createProp("Overwrite", False),
)
newpath = filepath[:-len("docx")] + "pdf"
fileUrl = uno.systemPathToFileUrl(os.path.realpath(newpath))
try:
document.storeToURL(fileUrl, uno_args) # Export
except ErrorCodeIOException:
raise
try:
document.close(True)
except CloseVetoException:
raise
Finally, since speed is a concern, using a listening instance of LibreOffice can be slow. To do this faster, move the code into a macro. APSO provides a menu to organize Python macros. Then call the macro like this:
soffice "vnd.sun.star.script:myscript.py$name_of_maindef?language=Python&location=user"
In macros, obtain the document objects from XSCRIPTCONTEXT
rather than the resolver.
来源:https://stackoverflow.com/questions/61457120/how-to-use-libreoffice-api-uno-with-python-windows