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