使用Apache POI替换word文档的内容

问题描述 投票:0回答:1

我正在使用 Apache POI(版本 5.2.2)Java 库来替换 Word 文档中的文本占位符。我的任务之一是替换/编辑矩形中的文本。我正在使用下面的代码,它成功地工作了,我面临的唯一问题是,如果我要更改或编辑文档中的其他段落的文本,那么它会给出异常。下面给出了代码和异常。

更改文本框内容的代码:

private void replacePlaceholdersWithInAShape(XWPFParagraph paragraph) throws XmlException {

XmlCursor cursor = paragraph.getCTP().newCursor();
            cursor.selectPath("declare namespace w='http://schemas.openxmlformats.org/wordprocessingml/2006/main' .//*/w:txbxContent/w:p/w:r");
            List<XmlObject> ctrsintxtbx = new ArrayList<XmlObject>();
            while(cursor.hasNextSelection()) {
                cursor.toNextSelection();
                XmlObject obj = cursor.getObject();
                ctrsintxtbx.add(obj);
            }
            for (XmlObject obj : ctrsintxtbx) {
                CTR ctr = CTR.Factory.parse(obj.xmlText());
                XWPFRun bufferrun = new XWPFRun(ctr, (IRunBody)paragraph);
                String text = bufferrun.getText(0);
                if (text != null && !text.equalsIgnoreCase("")) {
                    if(text.contains("[{project_number}]")) {    
                        System.out.println("contains project number");
                        text = text.replace("[{project_number}]", "test");
                        bufferrun.setText("test", 0);
                    } else {                    
                        bufferrun.setText(text, 0);
                    }
                }
                obj.set(bufferrun.getCTR());
            }
}

成功编辑文本框/形状中的文本后用于更改段落文本的代码

protected void replaceParagraphPlaceholders(String paraText, XWPFParagraph paragraph, String key, String value, Map<String, Object> fields) {

    //paragraph text's empty and null check.
    String paragraphText = paragraph.getText();
    if(paragraphText!=""&&paragraphText!=null) {
        if(paragraph.getRuns().size()<=1) {
            String runText = "Sample text";
            paragraph.getRuns().get(0).setText(runText, 0);
        }
    }
}

上述代码在更改段落文本时出现的异常如下。

java.util.ConcurrentModificationException: Document changed during select
    at org.apache.xmlbeans.impl.xpath.xmlbeans.XmlbeansXPathEngine.next(XmlbeansXPathEngine.java:100)
    at org.apache.xmlbeans.impl.store.Cursor._toSelection(Cursor.java:749)
    at org.apache.xmlbeans.impl.store.Cursor._getSelectionCount(Cursor.java:764)
    at org.apache.xmlbeans.impl.store.Cursor.notifyChange(Cursor.java:697)
    at org.apache.xmlbeans.impl.store.Locale.notifyChange(Locale.java:995)
    at org.apache.xmlbeans.impl.store.Cur.moveChars(Cur.java:1772)
    at org.apache.xmlbeans.impl.store.Cur.moveNodeContents(Cur.java:2016)
    at org.apache.xmlbeans.impl.store.Cur.moveNodeContents(Cur.java:1986)
    at org.apache.xmlbeans.impl.store.Xobj.store_text(Xobj.java:1833)
    at org.apache.xmlbeans.impl.values.XmlObjectBase.set_String(XmlObjectBase.java:1106)
    at org.apache.xmlbeans.impl.values.XmlObjectBase.setStringValue(XmlObjectBase.java:1774)
    at org.apache.poi.xwpf.usermodel.XWPFRun.setText(XWPFRun.java:363)
    at net.sharesuite.formletter.builder.poibuilder.docx.PoiDocxBuilder.replaceParagraphPlaceholders(PoiDocxBuilder.java:596)
    at net.sharesuite.formletter.builder.poibuilder.docx.PoiDocxBuilder.lambda$1(PoiDocxBuilder.java:205)
    at java.base/java.util.ArrayList$Itr.forEachRemaining(ArrayList.java:1003)
    at java.base/java.util.Collections$UnmodifiableCollection$1.forEachRemaining(Collections.java:1061)
    at net.sharesuite.formletter.builder.poibuilder.docx.PoiDocxBuilder.createFormLetterFile(PoiDocxBuilder.java:175)
    at net.sharesuite.formletter.service.impl.FormLetterServiceImpl.createFormLetter(FormLetterServiceImpl.java:42)
    at net.sharesuite.test.formletter.DocumentTest.testNLBLFormletter(DocumentTest.java:646)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:93)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:40)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:529)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:756)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:452)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)

一旦使用 XMLObject 更改文档文本,文档段落等中的其他更改就会导致上述异常。

java apache-poi docx apache-poi-4
1个回答
0
投票

改变

XmlCursor cursor = paragraph.getCTP().newCursor();
        cursor.selectPath("declare namespace w='http://schemas.openxmlformats.org/wordprocessingml/2006/main' .//*/w:txbxContent/w:p/w:r");
        List<XmlObject> ctrsintxtbx = new ArrayList<XmlObject>();

XmlObject[] ctrsintxtbx = paragraph.getCTP().selectPath("declare namespace w='http://schemas.openxmlformats.org/wordprocessingml/2006/main' .//*/w:txbxContent/w:p/w:r");
© www.soinside.com 2019 - 2024. All rights reserved.