poi实现多个word文档合并,加超简单分页教程

1.pom包

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

2.合并word工具类

package cn.com.fesco.hpe.config;

import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xwpf.usermodel.BreakType;
import org.apache.poi.xwpf.usermodel.Document;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFPictureData;
import org.apache.xmlbeans.XmlOptions;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBody;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 * 参数1:需要合并的word的文件对象list
 * 参数2:合并之后word存储的全路径file对象
 */
public class MergeDocUtils {


    public static void mergeDoc(List<File> fileList, File newFile) throws Exception {

        OutputStream dest = new FileOutputStream(newFile);
        ArrayList<XWPFDocument> documentList = new ArrayList<XWPFDocument>();
        XWPFDocument doc = null;
        for (int i = 0; i < fileList.size(); i++) {
            FileInputStream in = new FileInputStream(fileList.get(i).getPath());
            OPCPackage open = OPCPackage.open(in);
            XWPFDocument document = new XWPFDocument(open);
            documentList.add(document);
        }



        for (int i = 0; i < documentList.size(); i++) {
            doc = documentList.get(0);
            if (i != 0) {
               //documentList.get(i).createParagraph().setPageBreak(true);//实现了分页效果。//但是会出现在首行为空的情况
               documentList.get(i).createParagraph().createRun().addBreak(BreakType.PAGE);//现了分页效果。使用这种方式不会出现留白的情况
                appendBody(doc, documentList.get(i));
            }
        }
        doc.write(dest);//输出合并之后的文件
    }




    public static void appendBody(XWPFDocument src, XWPFDocument append) throws Exception {
        CTBody src1Body = src.getDocument().getBody();
        CTBody src2Body = append.getDocument().getBody();

        List<XWPFPictureData> allPictures = append.getAllPictures();
        // 记录图片合并前及合并后的ID
        Map<String, String> map = new HashMap();
        for (XWPFPictureData picture : allPictures) {
            String before = append.getRelationId(picture);
            //将原文档中的图片加入到目标文档中
            String after = src.addPictureData(picture.getData(), Document.PICTURE_TYPE_PNG);
            map.put(before, after);
        }

        appendBody(src1Body, src2Body, map);

    }

    private static void appendBody(CTBody src, CTBody append, Map<String, String> map) throws Exception {
        XmlOptions optionsOuter = new XmlOptions();
        optionsOuter.setSaveOuter();
        String appendString = append.xmlText(optionsOuter);

        //去掉追加word内容中的 w:sectPr 标签,确保合成的word中只有一个 w:sectPr 标签对
        //避免合成的word文档打开之后会提示有些内容读不出来,导致文件损坏
        String rgex = "<[\\s]*?w:sectPr[^>]*?>[\\s\\S]*?<[\\s]*?\\/[\\s]*?w:sectPr[\\s]*?>";
        appendString = appendString.replaceAll(rgex, "");

        String srcString = src.xmlText();
        String regex = regex(srcString, "w:sectPr");
        System.out.println(regex);

        String prefix = srcString.substring(0, srcString.indexOf(">") + 1);
        String mainPart = srcString.substring(srcString.indexOf(">") + 1, srcString.lastIndexOf("<"));
        String sufix = srcString.substring(srcString.lastIndexOf("<"));
        String addPart = appendString.substring(appendString.indexOf(">") + 1, appendString.lastIndexOf("<"));

        if (map != null && !map.isEmpty()) {
            //对xml字符串中图片ID进行替换
            for (Map.Entry<String, String> set : map.entrySet()) {
                addPart = addPart.replace(set.getKey(), set.getValue());
            }
        }
        //将两个文档的xml内容进行拼接
        CTBody makeBody = CTBody.Factory.parse(prefix + mainPart + addPart + sufix);

        src.set(makeBody);
    }

    /**
     * 获取指定标签中的内容
     *
     * @param xml
     * @param label
     * @return
     */
    public static String regex(String xml, String label) {
        String context = "";
        // 正则表达式
        String rgex = "<" + label + "[^>]*>((?:(?!<\\/" + label + ">)[\\s\\S])*)<\\/" + label + ">";
        Pattern pattern = Pattern.compile(rgex);// 匹配的模式
        Matcher m = pattern.matcher(xml);
        // 匹配的有多个
        List<String> list = new ArrayList<String>();
        while (m.find()) {
            int i = 1;
            list.add(m.group(i));
            i++;
        }
        if (list.size() > 0) {
            // 输出内容自己定义
            context = String.valueOf(list.size());
        }
        return context;
    }

}

3.代码实例

        //new一个list 模拟要合并的word对象集合
        List<File>docFileList = new ArrayList<>();
        docFileList.add(new File("D:/pdfData/2022-06-23-2c3d300450884b19bb58585d2c4ae518.docx"));
        docFileList.add(new File("D:/pdfData/2022-06-23-4a899305225e4fd8abc7ae154841124c.docx"));

        //合并之后doc存储路径 此处读的配置文件的存储路径 D:/pdfData/
        String docPath = fileUploadConfig.getDocPath();
        //当前日期+UUID作为文件名防止重复
        String fileName = LocalDate.now() + "-" + UUID.randomUUID().toString().replaceAll("-", "");
        //合并之后doc存储路径
        String mergeDocUrl = docPath+fileName+".docx";
        //转成file对象
        File mergeDocFile = new File(mergeDocUrl);

        //合并doc
        MergeDocUtils.mergeDoc(docFileList,mergeDocFile);

        System.out.println("合并word成功");

4.分页问题,我直接读的word模板,填充的数据,下边动态生成的表格

word填充模板,动态生成表格可以看这条poi填充word,动态生成表格+LibreOffice转成pdf_ytqucheng的博客-CSDN博客_poi 动态生成word表格

直接在word模板上需要分页的地方添加分页标识符,

我这里直接在最后一行加的分页标识

下面上图片

 5.效果图

  • 7
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值