poi-tl 合并 多个 word 文档 为一个(踩坑记录:tips:当合并一次word之后想要在书签指定位置再次合并word需要刷新word书签段落光标信息;问题:明明空间未绑定,)

使用poi-tl,合并word变得十分简单,只需要几行代码

示例如下:


1. pom版本:

     <dependency>
            <groupId>com.deepoove</groupId>
            <artifactId>poi-tl</artifactId>
            <version>1.12.1</version>
        </dependency>

2. 根据路径创建两个word 的document 对象,调用内置的merge() 方法即可以合并两个word 到一起,将documen2 追加到document 最后面。

代码如下:

NiceXWPFDocument document1 = new NiceXWPFDocument(Files.newInputStream(Paths.get("C:\\test\\test1.docx")));
NiceXWPFDocument document2 = new NiceXWPFDocument(Files.newInputStream(Paths.get("C:\\test\\test2.docx")));
document1 = document1.merge(document2);

poi-tl代码如下:
可以将多个word追加到合并当前word的指定位置

    public NiceXWPFDocument merge(NiceXWPFDocument docMerge) throws Exception {
        return merge(Arrays.asList(docMerge), createParagraph().createRun());
    }

    public NiceXWPFDocument merge(List<NiceXWPFDocument> docMerges, XWPFRun run) throws Exception {
        if (null == docMerges || docMerges.isEmpty() || null == run) return this;
        return merge(docMerges.iterator(), run);
    }

    public NiceXWPFDocument merge(Iterator<NiceXWPFDocument> iterator, XWPFRun run) throws Exception {
        XWPFRun newRun = run;
        String paragraphText = ParagraphUtils.trimLine((XWPFParagraph) run.getParent());
        boolean havePictures = ParagraphUtils.havePictures((XWPFParagraph) run.getParent());
        if (!ParagraphUtils.trimLine(run.text()).equals(paragraphText) || havePictures) {
            BodyContainer container = BodyContainerFactory.getBodyContainer(run);
            XWPFParagraph paragraph = container.insertNewParagraph(run);
            newRun = paragraph.createRun();
        }
        return new XmlXWPFDocumentMerge().merge(this, iterator, newRun);
    }

    public NiceXWPFDocument merge(NiceXWPFDocument source, Iterator<NiceXWPFDocument> mergeIterator, XWPFRun run)
            throws Exception {
        CTBody body = source.getDocument().getBody();
        List<String> addParts = createMergeableStrings(source, mergeIterator);
        String[] startEnd = truncatedStartEndXmlFragment(body);

        XWPFParagraph paragraph = (XWPFParagraph) run.getParent();
        CTP mergedContainer = paragraph.getCTP();
        CTP mergedBody = CTP.Factory
                .parse(startEnd[0] + "<w:POITL>" + String.join("", addParts) + "</w:POITL>" + startEnd[1]);
        // instead insert xml-fragment?
        mergedContainer.set(mergedBody);
        String xmlText = truncatedOverlapWP(body);
        body.set(CTBody.Factory.parse(xmlText));
        return source.generate(true);
    }

遇到的问题:多次合并只能追加,不能指定位置连续合并?

事先准备好需要插入的书签位置,当第一次插入后后续需要刷新书签对应段落信息,否则会出现:Method threw 'org.apache.xmlbeans.impl.values.XmlValueDisconnectedException' exception. Cannot evaluate org.openxmlformats.schemas.wordprocessingml.x2006.main.impl.CTPImpl.toString()错误
解决方案:每次合并完word文档 需要刷新书签对应段落信息数据。

2024-6-4 新增

问题:error: 与元素类型 "w:t" 相关联的属性 "xsi:nil" 的前缀 "xsi" 未绑定。
解决代码:

                // 添加命名空间
                org.w3c.dom.Element domNode = (org.w3c.dom.Element) document.getDocument().getBody().getDomNode();
                DocumentHelper.addNamespaceDeclaration(domNode,"xsi","http://www.w3.org/2001/XMLSchema-instance");

  • 14
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
合并多个 Word 文件,你可以使用 poi-tl 提供的方法来实现。以下是一个简单的示例: ```java import org.apache.poi.xwpf.usermodel.*; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import java.io.*; import java.util.List; public class WordMergeExample { public static void main(String[] args) { try { // 创建一个新的空白文档 XWPFDocument mergedDocument = new XWPFDocument(); // 读取第一个 Word 文件 XWPFDocument doc1 = new XWPFDocument(new FileInputStream("file1.docx")); // 复制第一个 Word 文件的内容到合并文档中 copyContent(doc1, mergedDocument); // 读取第二个 Word 文件 XWPFDocument doc2 = new XWPFDocument(new FileInputStream("file2.docx")); // 复制第二个 Word 文件的内容到合并文档中 copyContent(doc2, mergedDocument); // 保存合并后的文档 FileOutputStream outputStream = new FileOutputStream("merged.docx"); mergedDocument.write(outputStream); outputStream.close(); System.out.println("合并完成!"); } catch (IOException | InvalidFormatException e) { e.printStackTrace(); } } private static void copyContent(XWPFDocument sourceDoc, XWPFDocument targetDoc) { List<XWPFParagraph> paragraphs = sourceDoc.getParagraphs(); for (XWPFParagraph paragraph : paragraphs) { targetDoc.createParagraph().createRun().setText(paragraph.getText()); } } } ``` 在上面的示例中,我们首先创建了一个空白的目标文档 `mergedDocument`,然后使用 `copyContent` 方法将每个源文档的内容复制到目标文档中。最后,将目标文档保存为一个新的合并后的 Word 文件。 你需要将示例中的 `"file1.docx"` 和 `"file2.docx"` 替换为你要合并的实际文件路径。根据你的需求,你可以调整代码来处理更多的 Word 文件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小花客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值