You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何使用UNO在OpenOffice/LibreOffice中遍历完整文档并定位图表在文本中的位置

在Java中按显示顺序遍历LibreOffice Writer文档(包含图表/图形)

我最近在写Java代码访问LibreOffice中打开的文档,需要按编辑器显示顺序遍历整个文档,遇到了文本和图形元素无法统一遍历定位的问题,这里分享下我的解决过程:

最初的困境

一开始我用这段代码遍历普通文本内容,能正常获取文本和格式,但完全拿不到文档里的图表:

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();
    // 遍历内联元素获取文本及格式
}

之后我找到了获取图表(及其他图形)的方法,能拿到XShape对象,但没法确定这些图形在文本中的相对位置

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);
    // 拿到了subShape,但不知道它对应文本的哪个位置
}

我尝试通过锚点来定位,用XPropertySet获取了AnchorType(比如TextContentAnchorType.AS_CHARACTER),但找不到能获取具体锚点范围的属性,连anchortextrange属性都没有。另外想装MRI插件排查接口,但找到的版本只支持LibreOffice 3.3,没法在7.1上用。

解决办法

后来我发现,XShape对象其实还实现了XTextContent接口!通过这个接口就能拿到图形在文本中的锚点范围,进而创建文本光标定位位置:

// 在遍历XShape的循环中添加这段代码
XTextContent subContent = UnoRuntime.queryInterface(XTextContent.class, subShape);
XTextRange anchor = subContent.getAnchor();
// 根据锚点创建文本光标
XTextCursor cursor = anchor.getText().createTextCursorByRange(anchor.getStart());
// 向右移动50个字符,验证位置
cursor.goRight((short)50, true);
System.out.println("图形后方的文本内容:" + cursor.getString());

这样就能得到图形对应的文本锚点,通过光标操作就能确定它在文本流中的位置,从而实现按显示顺序统一遍历文档内容。

内容的提问来源于stack exchange,提问作者MTilsted

火山引擎 最新活动