利用POI对Word的一些操作(替换段落内容,替换表格里面的变量,页脚插入图片,页眉的关键字替换,多个Word合并)

最近工作上需要实现对word上的一些操作,其中包含:替换段落内容,替换表格里面的变量,页脚插入图片,页眉的关键字替换,多个Word合并等多个功能,已经实现,特此记录。

1. 利用POI实现如下功能:

替换段落内容,替换表格里面的变量,页脚插入图片,页眉的关键字替换,多个Word合并。

2. 相关的jar包

        
        <dependency>
            <groupId>org.apache.poigroupId>
            <artifactId>poiartifactId>
            <version>5.2.3version>
        dependency>
        <dependency>
            <groupId>org.apache.poigroupId>
            <artifactId>poi-ooxmlartifactId>
            <version>5.2.3version>
        dependency>
        <dependency>
            <groupId>org.apache.poigroupId>
            <artifactId>poi-ooxml-schemasartifactId>
            <version>4.1.2version>
        dependency>
        <dependency>
            <groupId>org.apache.poigroupId>
            <artifactId>poi-scratchpadartifactId>
            <version>5.2.3version>
        dependency>

        
        <dependency>
            <groupId>fr.opensagres.xdocreportgroupId>
            <artifactId>org.apache.poi.xwpf.converter.pdfartifactId>
            <version>1.0.6version>
        dependency>

        
        <dependency>
            <groupId>fr.opensagres.xdocreportgroupId>
            <artifactId>xdocreportartifactId>
            <version>2.0.2version>
        dependency>

        
        <dependency>
            <groupId>com.itextpdfgroupId>
            <artifactId>itextpdfartifactId>
            <version>5.5.13.1version>
        dependency>
        
        <dependency>
            <groupId>com.itextpdfgroupId>
            <artifactId>itext-asianartifactId>
            <version>5.2.0version>
        dependency>

        
        <dependency>
            <groupId>com.deepoovegroupId>
            <artifactId>poi-tlartifactId>
            <version>1.9.1version>
        dependency>

3. 工具类(public均为对外提供)


import lombok.extern.log4j.Log4j2;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.Document;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFFooter;
import org.apache.poi.xwpf.usermodel.XWPFHeader;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;
import org.apache.xmlbeans.XmlOptions;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBody;
import org.springframework.stereotype.Component;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author wuk
 * @description: word填充转换工具
 * @menu word填充转换工具
 * @date 2022/9/17 15:43
 */
@Component
@Log4j2
public class WordToPdfUtil {

    /**
     * 替换段落内容 (格式有要求:<> 为三个文本对象)
     */
    public static XWPFDocument doParagraph(Map<String, String> dataMap, XWPFDocument xwpfDocument) {
        if (dataMap != null && dataMap.size() > 0) {
            List<XWPFParagraph> paragraphs = xwpfDocument.getParagraphs();
            for (XWPFParagraph paragraph : paragraphs) {
                replaceInPara(paragraph, dataMap);
            }
        }
        return xwpfDocument;
    }

    /**
     * 替换表格里面的变量
     */
    public static XWPFDocument replaceInTable(Map<String, String> params, XWPFDocument doc) {
        Iterator<XWPFTable> iterator = doc.getTablesIterator();
        XWPFTable table;
        List<XWPFTableRow> rows;
        List<XWPFTableCell> cells;
        List<XWPFParagraph> paras;
        while (iterator.hasNext()) {
            table = iterator.next();
            rows = table.getRows();
            for (XWPFTableRow row : rows) {
                cells = row.getTableCells();
                for (XWPFTableCell cell : cells) {
                    paras = cell.getParagraphs();
                    for (XWPFParagraph para : paras) {
                        replaceInPara(para, params);
                    }
                }
            }
        }
        return doc;
    }

    /**
     * 页脚插入图片
     */
    public static XWPFDocument insertImageInFoot(Map<String, String> dataMap, XWPFDocument doc) throws Exception {

        List<XWPFFooter> footerList = doc.getFooterList();
        InputStream in = new FileInputStream(dataMap.get("${image}"));
        for (XWPFFooter xwpfFooter : footerList) {
            List<XWPFParagraph> listParagraph = xwpfFooter.getListParagraph();
            for (XWPFParagraph xwpfParagraph : listParagraph) {
                List<XWPFRun> runs = xwpfParagraph.getRuns();
                if (CollectionUtils.isNotEmpty(runs)) {
                    XWPFRun run = runs.get(0);
                    run.addPicture(in, Document.PICTURE_TYPE_PNG, "", Units.toEMU(50), Units.toEMU(50));

                }

            }
        }
        in.close();
        return doc;
    }

    /**
     * 页眉的关键字替换
     */
    public static XWPFDocument doParagraphOfHead(Map<String, String> dataMap, XWPFDocument doc) {

        List<XWPFHeader> headerList = doc.getHeaderList();
        for (XWPFHeader xwpfHeader : headerList) {
            List<XWPFParagraph> listParagraph = xwpfHeader.getListParagraph();
            for (XWPFParagraph xwpfParagraph : listParagraph) {
                replaceInPara(xwpfParagraph, dataMap);
            }
        }
        return doc;
    }

    /**
     * 替换段落里面的变量
     *
     * @param para   要替换的段落
     * @param params 参数
     */
    private static void replaceInPara(XWPFParagraph para, Map<String, String> params) {

        Map<Integer, StringBuilder> strMap = new HashMap<>();
        recursionGetStr(para, strMap, params);
    }

    private static void recursionGetStr(XWPFParagraph para, Map<Integer, StringBuilder> strMap,
                                        Map<String, String> params) {
        List<XWPFRun> runs;
        String paragraphText = para.getParagraphText();
        boolean bool = matcher(paragraphText);
        if (bool) {
            runs = para.getRuns();
            int start = -1;
            int end;
            StringBuilder str = new StringBuilder();
            for (int i = 0; i < runs.size(); i++) {
                XWPFRun run = runs.get(i);
                String runText = run.toString();
                if (runText != null) {
                    if (StringUtils.isNotEmpty(runText.trim())) {
                        runText = runText.trim();
                    }
                    if ('<' == runText.charAt(0)) {
                        start = i;
                    }
                    if ((start != -1)) {
                        str.append(runText);
                    }

                    if ('>' == runText.charAt(runText.length() - 1)) {
                        if (start != -1) {
                            end = i;
                            String substring = paragraphText.replace(str, "");
                            if (matcher(substring)) {
                                for (int j = start; j <= end; j++) {
                                    para.removeRun(j);
                                    j--;
                                    end--;
                                }
                                strMap.put(start, str);
                                recursionGetStr(para, strMap, params);
                            } else {
                                for (int j = start; j <= end; j++) {
                                    para.removeRun(j);
                                    j--;
                                    end--;
                                }
                                strMap.put(start, str);
                                break;
                            }

                        }
                    }
                }
            }
            setPara(strMap, para, params);
            strMap.clear();
        }
    }

    private static void setPara(Map<Integer, StringBuilder> strMap, XWPFParagraph para, Map<String, String> params) {
        List<XWPFRun> runs = para.getRuns();
        XWPFRun xwpfRun = null;
        if (CollectionUtils.isNotEmpty(runs)) {
            for (XWPFRun run : runs) {
                if (ObjectUtils.isNotEmpty(run) &&
                        StringUtils.isNotEmpty(run.toString().trim())) {
                    xwpfRun = run;
                    break;
                }
            }
        }
        AtomicInteger i = new AtomicInteger();
        XWPFRun finalXwpfRun = xwpfRun;
        strMap.forEach((start, str) -> {
            i.set(i.get() + 1);
            String text = params.get(str.toString().trim());
            if (StringUtils.isNotEmpty(text)) {
                log.info("被填充的内容包含:{}", text);
                if (i.get() > 1) {
                    start = start + i.get() - 1;
                }
                XWPFRun run = para.insertNewRun(start);
                //设置样式
                if (!ObjectUtils.isEmpty(finalXwpfRun)) {
                    run.setBold(finalXwpfRun.isBold());
                    if (ObjectUtils.isNotEmpty(finalXwpfRun.getColor())) {
                        run.setColor(finalXwpfRun.getColor());
                    }
                    if (ObjectUtils.isNotEmpty(finalXwpfRun.getFontFamily())) {
                        run.setFontFamily(finalXwpfRun.getFontFamily());
                    }
                    if (ObjectUtils.isNotEmpty(finalXwpfRun.getFontSizeAsDouble())) {
                        run.setFontSize(finalXwpfRun.getFontSizeAsDouble());
                    }
                }
                run.setText(text);
            }
        });
    }

    /**
     * 正则匹配字符串
     */
    private static boolean matcher(String str) {
        Pattern pattern = Pattern.compile("\\<([\\u4e00-\\u9fa5]++)\\>", Pattern.CASE_INSENSITIVE);
        Matcher matcher = pattern.matcher(str);
        boolean bool = matcher.find();
        return bool;
    }

    /**
     * 关闭输入流
     */
    public static void close(InputStream is) {
        if (is != null) {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 关闭输出流
     */
    public static void close(OutputStream os) {
        if (os != null) {
            try {
                os.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 多个文档合并
     */
    public static void mergeDoc(List<XWPFDocument> list) throws Exception {

        //默认获取第一个作为模板
        XWPFDocument xmd = list.get(0);
        for (int i = 0; i < list.size() - 1; i++) {
            //相继合并
            mergeWord(xmd, list.get(i + 1));
        }
        xmd.write(new FileOutputStream("F:\\test1.docx"));
    }

    private static XWPFDocument mergeWord(XWPFDocument document, XWPFDocument docDocument2) throws Exception {
        XWPFParagraph p = document.createParagraph();
        //设置分页符
        p.setPageBreak(true);
        CTBody src1Body = document.getDocument().getBody();
        CTBody src2Body = docDocument2.getDocument().getBody();
        XmlOptions optionsOuter = new XmlOptions();
        optionsOuter.setSaveOuter();
        String appendString = src2Body.xmlText(optionsOuter);
        String srcString = src1Body.xmlText();
        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("<"));
        CTBody makeBody = CTBody.Factory.parse(prefix + mainPart + addPart + sufix);
        src1Body.set(makeBody);
        return document;
    }
}

你可能感兴趣的:(后台,替换word段落内容,替换Word表格里面的变量,页脚插入图片,页眉的关键字替换,多个Word合并)