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

本文介绍使用poi-tl合并多个Word文档的方法,只需几行代码,通过创建document对象并调用merge()方法即可合并。同时分享了遇到的问题及解决方案,如多次合并指定位置需刷新书签段落信息,还提及2024年6月4日新增问题及解决代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用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");

### 使用 poi-tl 合并多个 Word 文档 在处理多个 Word 文档合并操作时,`poi-tl` 提供了一种简便的方式来进行此操作。通过创建 `Document` 对象,并利用其内置方法实现文档间的合并。 对于简单的两份文档合并,可以根据路径创建两个 `Document` 对象,随后调用对象上的 `merge()` 方法完成合并过程,使第二个文档的内容追加至第一个文档末尾[^1]: ```java import com.deepoove.poi.XWPFTemplate; import org.apache.poi.xwpf.usermodel.XWPFDocument; public class MergeDocuments { public static void main(String[] args) throws Exception { XWPFDocument document1 = new XWPFDocument(new FileInputStream("path/to/document1.docx")); XWPFDocument document2 = new XWPFDocument(new FileInputStream("path/to/document2.docx")); // 将document2合并到document1中 document1.merge(document2); FileOutputStream out = new FileOutputStream("merged_document.docx"); document1.write(out); out.close(); document1.close(); document2.close(); } } ``` 然而,在实际应用过程中可能会遇到更复杂的需求场景,比如希望将新内容插入特定书签位置而非简单地附加于文件结尾处。针对这种情况,则需先定位目标书签再执行相应逻辑以确保数据放置正确无误。 此外,如果涉及到批量多文件连续拼接的情况,建议采用循环读取待处理文件列表的形式逐步累积最终输出版本;同时注意资源管理(如及时关闭流),以免造成不必要的内存占用或其他异常状况发生。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小花客

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

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

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

打赏作者

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

抵扣说明:

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

余额充值