|
@@ -0,0 +1,101 @@
|
|
|
+package com.yaoyicloud.tools;
|
|
|
+
|
|
|
+import java.io.FileNotFoundException;
|
|
|
+import java.io.FileOutputStream;
|
|
|
+import java.io.IOException;
|
|
|
+import java.util.List;
|
|
|
+
|
|
|
+import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
|
|
|
+import org.apache.poi.xwpf.usermodel.IBodyElement;
|
|
|
+import org.apache.poi.xwpf.usermodel.XWPFDocument;
|
|
|
+import org.apache.poi.xwpf.usermodel.XWPFParagraph;
|
|
|
+import org.apache.poi.xwpf.usermodel.XWPFPicture;
|
|
|
+import org.apache.poi.xwpf.usermodel.XWPFPictureData;
|
|
|
+import org.apache.poi.xwpf.usermodel.XWPFRun;
|
|
|
+import org.apache.poi.xwpf.usermodel.XWPFTable;
|
|
|
+import org.openxmlformats.schemas.drawingml.x2006.main.CTBlip;
|
|
|
+import org.openxmlformats.schemas.drawingml.x2006.main.CTBlipFillProperties;
|
|
|
+import org.openxmlformats.schemas.drawingml.x2006.picture.CTPicture;
|
|
|
+
|
|
|
+import com.deepoove.poi.xwpf.XWPFStructuredDocumentTag;
|
|
|
+
|
|
|
+public final class DocxUtil {
|
|
|
+
|
|
|
+ public static void mergeDocx(XWPFDocument target, List<XWPFDocument> sources, String outputPath)
|
|
|
+ throws InvalidFormatException, FileNotFoundException, IOException {
|
|
|
+ mergeDocx(target, sources, outputPath, true);
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * 只更新target的内容,全局设定(fonts, styles, custom items)都使用target docx
|
|
|
+ */
|
|
|
+ public static void mergeDocx(XWPFDocument target, List<XWPFDocument> sources, String outputPath,
|
|
|
+ boolean clearTargetBody) throws InvalidFormatException, FileNotFoundException, IOException {
|
|
|
+ if (clearTargetBody) {
|
|
|
+ target.getDocument().unsetBody();
|
|
|
+ target.getDocument().addNewBody();
|
|
|
+ }
|
|
|
+ for (XWPFDocument source : sources) {
|
|
|
+ appendSourceContent(target, source);
|
|
|
+ }
|
|
|
+
|
|
|
+ try (FileOutputStream out = new FileOutputStream(outputPath)) {
|
|
|
+ target.write(out);
|
|
|
+ target.close();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void appendSourceContent(XWPFDocument target, XWPFDocument source) throws InvalidFormatException {
|
|
|
+ for (IBodyElement element : source.getBodyElements()) {
|
|
|
+ if (element instanceof XWPFParagraph) {
|
|
|
+ appendParagraph(target, (XWPFParagraph) element);
|
|
|
+ } else if (element instanceof XWPFTable) {
|
|
|
+ appendTable(target, (XWPFTable) element);
|
|
|
+ } else if (element instanceof XWPFStructuredDocumentTag) {
|
|
|
+ // todo: 目录,自定义标签等
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void appendTable(XWPFDocument target, XWPFTable oldTable) {
|
|
|
+ XWPFTable newTable = target.createTable();
|
|
|
+ newTable.getCTTbl().set(oldTable.getCTTbl().copy());
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void appendParagraph(XWPFDocument target, XWPFParagraph oldParagraph) throws InvalidFormatException {
|
|
|
+ // Remove additional blank page
|
|
|
+ // if (i == doc1.getBodyElements().size() - 1
|
|
|
+ // && oldParagraph.isPageBreak()
|
|
|
+ // && StrUtil.isBlank(oldParagraph.getText())) {
|
|
|
+ // continue;
|
|
|
+ // }
|
|
|
+
|
|
|
+ // Copy Picture
|
|
|
+ for (int i = 0; i < oldParagraph.getRuns().size(); i++) {
|
|
|
+ XWPFRun oldRun = oldParagraph.getRuns().get(i);
|
|
|
+
|
|
|
+ // Check if the run has embedded images
|
|
|
+ List<XWPFPicture> pictures = oldRun.getEmbeddedPictures();
|
|
|
+ for (int j = 0; j < pictures.size(); j++) {
|
|
|
+ XWPFPictureData picData = pictures.get(j).getPictureData();
|
|
|
+
|
|
|
+ // copy picture
|
|
|
+ // String fileName = picData.getFileName();
|
|
|
+ String newRelationId = target.addPictureData(picData.getData(), picData.getPictureType());
|
|
|
+
|
|
|
+ // update image rId to the new run
|
|
|
+ // 注意这里用新文件的rId更新了旧文件的Run,然后复制旧文件的XML到新文件
|
|
|
+ // 如果直接编辑新文件需要在复制XML后重新生成XWPFParagraph对象,才能正确反映更新的XML数据
|
|
|
+ CTPicture ctPic = pictures.get(j).getCTPicture();
|
|
|
+ CTBlipFillProperties bill = ctPic.getBlipFill();
|
|
|
+ CTBlip blip = bill.getBlip();
|
|
|
+ blip.setEmbed(newRelationId);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // Copy Xml content
|
|
|
+ XWPFParagraph newParagraph = target.createParagraph();
|
|
|
+ newParagraph.getCTP().set(oldParagraph.getCTP().copy());
|
|
|
+ }
|
|
|
+
|
|
|
+}
|