当前位置: 首页 > 知识库问答 >
问题:

Apache POI:从Word模板文件中完全删除图表

尉迟明辉
2023-03-14
PackagePart packagePartChart = xWPFChart.getPackagePart();

PackagePart packagePartWordDoc = xWPFDocument.getPackagePart();
OPCPackage packageWordDoc = packagePartWordDoc.getPackage();

// iterate over all relations the chart has and remove them
for (PackageRelationship chartrelship : packagePartChart.getRelationships()) {
    String partname = chartrelship.getTargetURI().toString();
    PackagePart part = packageWordDoc.getPartsByName(Pattern.compile(partname)).get(0);
    packageWordDoc.removePart(part);
    packagePartChart.removeRelationship(chartrelship.getId());
}

// now remove the chart itself from the word doc                           
Method removeRelation = POIXMLDocumentPart.class.getDeclaredMethod("removeRelation", POIXMLDocumentPart.class); 
removeRelation.setAccessible(true); 
removeRelation.invoke(xWPFDocument, xWPFChart);
    null

有人知道这里会出什么问题吗?

共有1个答案

艾璞瑜
2023-03-14

事实上,找到正确的段落保存图表是一项挑战。最后,为了简单起见,我添加了一个一行/一列占位符表,其中有一个带有文本的单元格,比方说“目标字串”,就在图表的前面。通过下面的函数,我定位这个表的BodyElementID:

private Integer iBodyElementIterator (XWPFDocument wordDoc,String targetWordString) {
    Iterator<IBodyElement> iter = wordDoc.getBodyElementsIterator();
    Integer bodyElementID = null;
    while (iter.hasNext()) {
       IBodyElement elem = iter.next();
       bodyElementID = wordDoc.getBodyElements().indexOf(elem);
       if (elem instanceof XWPFParagraph) {

           XWPFParagraph paragraph = (XWPFParagraph) elem;
           for (XWPFRun runText : paragraph.getRuns()) {
                String text = runText.getText(0);                               
               Core.getLogger("WordExporter").trace("Body Element ID:  " + bodyElementID + " Text: " + text);
                if (text != null && text.equals(targetWordString)) {                        
                    break;                          
                }
            }

       } else if (elem instanceof XWPFTable) {
           if (((XWPFTable) elem).getRow(0) != null && ((XWPFTable) elem).getRow(0).getCell(0) != null) {
                // the first cell holds the name via the template
                String tableTitle = ((XWPFTable) elem).getRow(0).getCell(0).getText();
                if (tableTitle.equals(targetWordString)) {
                    break;
                }
                Core.getLogger("WordExporter").trace("Body Element ID:  " + bodyElementID + " Text: " + tableTitle);
           } else {
               Core.getLogger("WordExporter").trace("Body Element ID:  " + bodyElementID + " Table removed!");
           }

       }
       else {
           Core.getLogger("WordExporter").trace("Body Element ID:  " + bodyElementID + " Text: ?");
       }
    }
    return bodyElementID;
}

在代码的主要部分,我调用这个函数来定位表,然后首先删除图表(ID+1),然后删除表(ID)

int elementIDToBeRemoved = iBodyElementIterator(xWPFWordDoc,targetWordString);

xWPFWordDoc.removeBodyElement(elementIDToBeRemoved + 1);
xWPFWordDoc.removeBodyElement(elementIDToBeRemoved);

它需要按这个顺序排列,因为一旦删除中间的一个数字,ID就会重新排序,因此首先删除表意味着图表原则上会得到该ID。

 类似资料:
  • 我卸载了以前版本的Node.js(0.8.11),从Node.js网站下载了最新的0.10.24并安装了它。但是,在运行之后,它仍然表明我运行的是V0.8.11。很明显,卸载过程中留下了一些东西,这导致我在试图通过NPM添加模块时出现了各种各样的错误。我在OSX和Linux上见过解决方案,但在Windows上找不到任何解决方案。我运行的是Windows 7 64位。

  • 问题内容: 我从不同的文件夹中删除了詹金斯所有目录。但是,当我访问URL时,仍然显示jenkins登录。 我想完全卸载jenkins。已经尝试了许多来自Internet的命令,但是服务器上仍然有jenkins。 我只有通过腻子进行命令行访问,因此我尝试通过命令删除jenkins。 问题答案: 如果您的詹金斯人以服务而不是进程的形式运行,则应先使用 停止后,您可以按照与Linux风格相对应的命令按照

  • 问题内容: 我卸载了先前版本的node.js(0.8.11),并从node.js网站下载了最新版本0.10.24并进行了安装。但是,运行后,仍然表明我正在运行v0.8.11。显然,在卸载过程中遗留了一些东西,这导致我在尝试通过npm添加模块时遇到各种错误。我已经看到了针对OSX和Linux的解决方案,但找不到Windows的任何东西。我正在运行Windows 7 64位。 问题答案: 如何从Win

  • 我正在尝试创建一个包含多列的word文档。这样做(而不是使用表)的原因是,数据将跨越多个页面,在添加到新页面之前,我只能用列填充整个页面。 可以用ApachePOI实现吗?谢谢

  • 问题内容: 我回来时在Ubuntu上安装了Docker,但是当我尝试删除Docker时,系统中仍然存在。我遵循了这个https://stackoverflow.com/a/31313851/2340159,但是没有用。 问题答案: 显然,我正在使用的系统具有 docker-ce 而不是Docker。因此,在命令下运行即可达到目的。

  • 我无法使用ApachePOI删除docx文件中的所有注释。有没有其他方法可以使用docx4j api删除注释?