这两天研究了一下 LibreOffice 的 API 用法,在 Python 下做了一些实验,分享如下。
首先,从您的 LibreOffice 安装位置带参数运行 soffice.bin,如下(注意该命令会一直保持运行,可通过Ctrl+C结束运行):
$ /opt/libreofficedev7.1/program/soffice.bin "--accept=socket,host=localhost,port=2002;urp;"
然后,将如下Python代码保存到某个位置,假设文件名为hello_world.py:
import uno
from com.sun.star.beans import PropertyValue
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)
''' 1. 创建空白文档
'''
model = desktop.loadComponentFromURL("private:factory/swriter", "_blank", 0, ())
text = model.Text
cursor = text.createTextCursor()
# 参考:https://api.libreoffice.org/docs/idl/ref/interfacecom_1_1sun_1_1star_1_1text_1_1XSimpleText.html
text.insertString( cursor, "Hello World", 0)
text.insertControlCharacter(cursor, uno.getConstantByName("com.sun.star.text.ControlCharacter.PARAGRAPH_BREAK"), 0)
text.insertString( cursor, "Hello World 2", 0)
''' 2. 通过 PropertyValue 之 FilterName 设置要保存的文档类型
若没有指定,则采用默认文档类型(不会根据文件名后缀判断)
PropertyValue的参数和属性,请参考:https://api.libreoffice.org/docs/idl/ref/structcom_1_1sun_1_1star_1_1beans_1_1PropertyValue.html
也可以通过这个选项来将文档导出为PDF或者图像。
完整的FilterName名称,可在LibreOffice源代码的 filter/source/config/fragments/filters 目录下找到。
比如:writer8.xcu中为 node oor:name="writer8",则ODF Text Document格式的API名称为 writer8
常见的:
writer8.xcu -> "writer8"
writer_pdf_Export.xcu -> "writer_pdf_Export"
MS_Word_2007_XML.xcu -> "MS Word 2007 XML"
'''
arg_odt = PropertyValue()
arg_odt.Name = "FilterName"
arg_odt.Value = "writer8"
arg_docx = PropertyValue()
arg_docx.Name = "FilterName"
arg_docx.Value = "MS Word 2007 XML"
arg_pdf = PropertyValue()
arg_pdf.Name = "FilterName"
arg_pdf.Value = "writer_pdf_Export"
''' 3. 通过 PropertyValue 设置其他保存选项
'''
# 比如,可以指定保存再打开后显示在文件 -> 属性中的文档标题:
arg_title = PropertyValue()
arg_title.Name = "DocumentTitle"
arg_title.Value = "Hello World"
# 再比如,可以给文档设置密码:
arg_pw = PropertyValue()
arg_pw.Name = "Password"
arg_pw.Value = "123456"
# 可以设置哪些PropertyValue,取决于你要将这些参数传递给谁。
# 如下面所示,我们需要传递给model.storeToURL。storeToURL可以接受的PropertyValue范围,请参考:
# https://api.libreoffice.org/docs/idl/ref/servicecom_1_1sun_1_1star_1_1document_1_1MediaDescriptor.html
''' 4. 保存文件
'''
# 首先需要将各个选项参数连接成一个 tuple.此处我们分四个不同的组合:
# 第一个用于保存为开放文档格式ODT,
# 第二个用于保存为微软的OOXML格式DOCX,
# 第三个用于导出为PDF,
# 第四个用于保存为带密码的开放文档格式ODT。
args_odt = (arg_odt, arg_title)
args_docx = (arg_docx, arg_title)
args_pdf = (arg_pdf, )
args_odt_protected = (arg_odt, arg_title, arg_pw)
# 文件的保存路径。注意是file:///形式的路径
file_path_odt = "file:///home/suokunlong/tmp/hello_world.odt"
file_path_docx = "file:///home/suokunlong/tmp/hello_world.docx"
file_path_pdf = "file:///home/suokunlong/tmp/hello_world.pdf"
file_path_odt_protected = "file:///home/suokunlong/tmp/hello_world_protected.odt"
# 保存
model.storeToURL(file_path_odt, args_odt)
model.storeToURL(file_path_docx, args_docx)
model.storeToURL(file_path_pdf, args_pdf)
model.storeToURL(file_path_odt_protected, args_odt_protected)
# 关闭文档(注意此时您通过命令行运行的 libreoffice 管道进程并不会通过以下代码关闭)
model.dispose()
最后,新建一个命令行窗口,通过以下命令用位于 LibreOffice 安装路径下的python解释器(注意不是您系统自身安装的python)来运行这段 hello_world.py 代码:
$ /opt/libreofficedev7.1/program/python ./hello_world.py
此时,你定义的保存路径下会生成四个文件:一个ODT文件,一个DOCX文件,一个PDF文件,还有一个受密码保护的ODT文件。
以上代码在Fedora 32下测试通过,使用的是最新的 LibreOffice 7.1分支构建版本。
以上示例是通过创建空白文档,然后对该空白文档进行操作的。当然,您可以修改代码,从而先读入现有的文档,然后进行后续操作。读文档时,只需要将上述完整代码中的以下代码:
model = desktop.loadComponentFromURL("private:factory/swriter", "_blank", 0, ())
修改为:(注意尖括号里的内容)
model = desktop.loadComponentFromURL(<文件路径>, "_blank", 0, <通过PropertyValue构造的打开文件的参数选项,比如FilterName, Password等>)
有任何问题,欢迎留言探讨。
发表回复