Как использовать LibreOffice API (UNO) с Python + Windows? - PullRequest
1 голос
/ 27 апреля 2020

Этот вопрос сосредоточен на Windows + LibreOffice + Python 3.

Я установил LibreOffice (6.3.4.2), также pip install unoconv и pip install unotools (pip install uno - другое не связанной библиотекой), но все равно я получаю эту ошибку после import uno:

ModuleNotFoundError: Нет модуля с именем 'uno'

В более общем смысле и как пример использования UNO, как открыть документ .docx с помощью LibreOffice UNO и экспортировать его в PDF?

Я много раз искал по этому вопросу уже несколько дней, но я не нашел Воспроизводимый пример кода, работающий на Windows:

1 Ответ

2 голосов
/ 27 апреля 2020

Для взаимодействия с LibreOffice запустите экземпляр, прослушивающий сокет. Я не использую COM много, но я думаю, что это эквивалент взаимодействия COM, о котором вы спрашивали. Это проще всего сделать из командной строки или с помощью сценария оболочки, но он также может работать с системным вызовом с использованием временной задержки и подпроцесса.

chdir "%ProgramFiles%\LibreOffice\program\"
start soffice -accept=socket,host=localhost,port=2002;urp;

Далее запустите установку python поставляется с LibreOffice, в котором по умолчанию установлено uno.

"C:\Program Files\LibreOffice\program\python.exe"
>> import uno

Если вместо этого вы используете установку Python на Windows, которая не была поставлена ​​с LibreOffice, то заставьте ее работать с UNO намного сложнее, и я бы не советовал, если вам не нравится хакерство.

Теперь вот весь код. В реальном проекте, вероятно, лучше организовывать в классы, но это упрощенная версия.

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

Наконец, поскольку скорость - проблема, использование прослушивающего экземпляра LibreOffice может быть медленным. Чтобы сделать это быстрее, переместите код в макрос. APSO предоставляет меню для организации Python макросов. Затем вызовите макрос следующим образом:

soffice "vnd.sun.star.script:myscript.py$name_of_maindef?language=Python&location=user"

В макросах получите объекты документа из XSCRIPTCONTEXT, а не из распознавателя.

...