如何使用 UNO 遍历 OpenOffice/LibreOffice 中的整个文档

Posted

技术标签:

【中文标题】如何使用 UNO 遍历 OpenOffice/LibreOffice 中的整个文档【英文标题】:How do I iterate over an entire document in OpenOffice/LibreOffice with UNO 【发布时间】:2021-10-08 18:14:42 【问题描述】:

我正在编写 Java 代码来访问在 Libre Office 中打开的文档。

我现在需要编写一些代码来遍历整个文档,希望与编辑器中显示的顺序相同。

我可以使用这段代码来遍历所有的普通文本:

XComponent writerComponent=xComponentLoader.loadComponentFromURL(loadUrl, "_blank", 0, loadProps);
XTextDocument mxDoc=UnoRuntime.queryInterface(XTextDocument.class, writerComponent);
XText mxDocText=mxDoc.getText();
XEnumerationAccess xParaAccess = (XEnumerationAccess) UnoRuntime.queryInterface(XEnumerationAccess.class, mxDocText);
XEnumeration xParaEnum = xParaAccess.createEnumeration();
Object element = xParaEnum.nextElement();
while (xParaEnum.hasMoreElements()) 
   XEnumerationAccess inlineAccess = (XEnumerationAccess) UnoRuntime.queryInterface(XEnumerationAccess.class, element);
   XEnumeration inline = inlineAccess.createEnumeration();
   // And I can then iterate over this inline element and get all the text and formatting.

但问题是这不包括任何图表对象。

然后我可以使用

XDrawPagesSupplier drawSupplier=UnoRuntime.queryInterface(XDrawPagesSupplier.class, writerComponent);
XDrawPages pages=drawSupplier.getDrawPages();
XDrawPage drawPage=UnoRuntime.queryInterface(XDrawPage.class,page);
            
for(int j=0;j!=drawPage.getCount();j++) 
   Object sub=drawPage.getByIndex(j);
   XShape subShape=UnoRuntime.queryInterface(XShape.class,sub);
   // Now I got my subShape, but how do I know its position, relative to the text.

这给了我所有图表(我猜还有其他数字),但问题是:我如何找出这些图表相对于模型中的文本的位置。以及如何获得代表每个图表的光标?

更新: 我现在正在为我的 XShape 寻找锚点,但 XShape 没有 getAnchor() 方法。

但是如果我使用 XPropertySet prop=UnoRuntime.queryInterface(XPropertySet.class,shape);

我得到了道具类。

然后我调用 prop.getPropertyValue("AnchorType") 这给了我一个锚类型 TextContentAnchorType.AS_CHARACTER

但我就是无法获得锚本身。没有锚或文本范围属性。

顺便说一句:我尝试为 libre office 安装“MRI”,但我能找到的唯一版本是 libreoffice 3.3 作为受支持的版本,并且它不会安装在 7.1 版上

----- 更新 2 ----- 我设法使它工作。原来我的 XShape 也实现了 XTextContent(谢谢 MRI),所以我所要做的就是:

XTextContent subContent=UnoRuntime.queryInterface(XTextContent.class,subShape);
XTextRange anchor=subContent.getAnchor();
XTextCursor cursor = anchor.getText().createTextCursorByRange(anchor.getStart());
cursor.goRight((short)50,true);
System.out.println("String=" + cursor.getString());

这给了我一个指向段落的光标,然后我可以向前/向后移动以找出形状的位置。所以这个 println 调用将打印 XShape 之后的 50 个字符。

【问题讨论】:

锚点将对象固定到特定位置。图表是否锚定到段落或页面?如果是段落,那么它们可以按照7.16.4 中的描述进行枚举。枚举文本并查找 Andrew Pitonyak 宏文档的文本内容。形状是否有方法getAnchor() 或属性AnchorType?我会使用诸如 MRI 之类的内省工具来确定这一点。至于游标,可能类似于表格:oText = oTable.getAnchor().getText(); oCurs = oText.createTextCursor() @JimK 感谢您的帮助。现在我正在寻找我的锚,但 XShape 没有 getAnchor() 方法。查看更新 从github.com/hanya/MRI/releases 下载 MRI 1.3.4。至于您的其余编辑,我将不得不查找如何处理锚定到角色的对象,但您能够弄清楚那部分是件好事。 @JimK 谢谢。我设法使它工作。 (见更新 2)。如果您留下您的评论作为答案,我会接受。 【参考方案1】:

我如何找出这些图表相对于模型中的文本的位置。以及如何获得代表每个图表的光标?

缩略的 cmets

锚点将对象固定到特定位置。形状是否有方法getAnchor() 或属性AnchorType?我会使用诸如 MRI 之类的内省工具来确定这一点。从https://github.com/hanya/MRI/releases 下载 MRI 1.3.4。

就游标而言,可能类似于表格:

oText = oTable.getAnchor().getText()
oCurs = oText.createTextCursor()

OP给出的代码解决方案

XTextContent subContent=UnoRuntime.queryInterface(XTextContent.class,subShape);
XTextRange anchor=subContent.getAnchor();
XTextCursor cursor = anchor.getText().createTextCursorByRange(anchor.getStart());
cursor.goRight((short)50,true);
System.out.println("String=" + cursor.getString());

【讨论】:

以上是关于如何使用 UNO 遍历 OpenOffice/LibreOffice 中的整个文档的主要内容,如果未能解决你的问题,请参考以下文章

如何给Arduino UNO下载Bootloader?

如何通过 UNO 更改文档名称?

如何使用 UNO 获取打开的文档?

如何在 Python + Windows 中使用 LibreOffice API (UNO)?

如何在 (Uno 2.4) 中使用 Microsoft.UI.Xaml.Controls 资源

在 Uno 平台上如何使用 Preferences.Set 命令