如何使用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),但找不到能获取具体锚点范围的属性,连anchor或textrange属性都没有。另外想装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




