记录java使用POI实现word模板数据填充

一、前言

最近项目遇到个需求,在模板中填充数据,刚开始是用smartBi报表进行填充,输出参数都是必录,无法满足需求。在网上查了很多资料,有些需要把文档转成xml格式修改里面内容,IDEA里面修改要替换的占位符的位置等方式,都不满足需求。

二、JAR包

因为项目要做兼容,我这使用的是3.15的版本,不需要兼容可以选择4.0+版本

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

三、实现代码

package com.fortunes.javamg.common.utils.poi;

import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.*;

import java.io.FileInputStream;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * @version V1.0
 * @Description:Word模板数据填充
 * @Date: 2022/11/16 17:47
 */
public class ReplaceWord {

    /***
     * @Description :替换段落文本
     * @param document docx解析对象
     * @param textMap  需要替换的信息集合
     * @return void
     * @Date 2022/11/17 17:22
     */
    public static void changeText(XWPFDocument document, Map<String, Object> textMap) {
        // 获取段落集合
        Iterator<XWPFParagraph> iterator = document.getParagraphsIterator();
        XWPFParagraph paragraph = null;
        while (iterator.hasNext()) {
            paragraph = iterator.next();
            // 判断此段落是否需要替换
            if (checkText(paragraph.getText())) {
                replaceValue(paragraph, textMap);
            }
        }
    }

    /***
     * @Description :检查文本中是否包含指定的字符(此处为“$”)
     * @param text
     * @return boolean
     * @Date 2022/11/17 17:22
     */
    public static boolean checkText(String text) {
        boolean check = false;
        if (text.contains("$")) {
            check = true;
        }
        return check;
    }

    /**
     * 替换图片
     *
     * @param document
     * @param picData
     * @throws Exception
     */

    public static void changePic(XWPFDocument document, Map<String, Object> picData) throws Exception {
        // 获取段落集合
        Iterator<XWPFParagraph> iterator = document.getParagraphsIterator();
        XWPFParagraph paragraph;
        while (iterator.hasNext()) {
            paragraph = iterator.next();
            // 判断此段落是否需要替换
            String text = paragraph.getText();
            if (checkText(text)) {
                replacePicValue(paragraph, picData);
            }
        }
    }

    /***
     * @Description :替换表格内的文字
     * @param document
     * @param data
     * @return void
     * @Date 2022/11/18 11:29
     */
    public static void changeTableText(XWPFDocument document, Map<String, Object> data) {
        // 获取文件的表格
        Iterator<XWPFTable> tableList = document.getTablesIterator();
        XWPFTable table;
        List<XWPFTableRow> rows;
        List<XWPFTableCell> cells;
        // 循环所有需要进行替换的文本,进行替换
        while (tableList.hasNext()) {
            table = tableList.next();
            if (checkText(table.getText())) {
                rows = table.getRows();
                // 遍历表格,并替换模板
                for (XWPFTableRow row : rows) {
                    cells = row.getTableCells();
                    for (XWPFTableCell cell : cells) {
                        // 判断单元格是否需要替换
                        if (checkText(cell.getText())) {
                            List<XWPFParagraph> paragraphs = cell.getParagraphs();
                            for (XWPFParagraph paragraph : paragraphs) {
                                replaceValue(paragraph, data);
                            }
                        }
                    }
                }
            }
        }
    }

    /***
     * @Description :替换表格内图片
     * @param document
     * @param picData
     * @return void
     * @Date 2022/11/18 11:29
     */
    public static void changeTablePic(XWPFDocument document, Map<String, Object> picData) throws Exception {
        // 获取文件的表格
        Iterator<XWPFTable> tableList = document.getTablesIterator();
        XWPFTable table;
        List<XWPFTableRow> rows;
        List<XWPFTableCell> cells;
        // 循环所有需要进行替换的文本,进行替换
        while (tableList.hasNext()) {
            table = tableList.next();
            if (checkText(table.getText())) {
                rows = table.getRows();
                // 遍历表格,并替换模板
                for (XWPFTableRow row : rows) {
                    cells = row.getTableCells();
                    for (XWPFTableCell cell : cells) {
                        // 判断单元格是否需要替换
                        if (checkText(cell.getText())) {
                            List<XWPFParagraph> paragraphs = cell.getParagraphs();
                            for (XWPFParagraph paragraph : paragraphs) {
                                replacePicValue(paragraph, picData);
                            }
                        }
                    }
                }
            }
        }
    }

    /***
     * @Description :替换内容
     * @param paragraph
     * @param textMap
     * @return void
     * @Date 2022/11/18 11:33
     */
    public static void replaceValue(XWPFParagraph paragraph, Map<String, Object> textMap) {
        XWPFRun run, nextRun;
        String runsText;
        List<XWPFRun> runs = paragraph.getRuns();
        for (int i = 0; i < runs.size(); i++) {
            run = runs.get(i);
            runsText = run.getText(0);
            if (runsText.contains("${") || (runsText.contains("$") && runs.get(i + 1).getText(0).substring(0, 1).equals("{"))) {
                while (!runsText.contains("}")) {
                    nextRun = runs.get(i + 1);
                    runsText = runsText + nextRun.getText(0);
                    //删除该节点下的数据
                    paragraph.removeRun(i + 1);
                }
                Object value = changeValue(runsText, textMap);
                //判断key在Map中是否存在
                if (textMap.containsKey(runsText)) {
                    run.setText(value.toString(), 0);
                } else {
                    //如果匹配不到,则不修改
                    run.setText(runsText, 0);
                }
            }
        }
    }

    /***
     * @Description :替换图片内容
     * @param paragraph
     * @param picData
     * @return void
     * @Date 2022/11/18 11:33
     */
    public static void replacePicValue(XWPFParagraph paragraph, Map<String, Object> picData) throws Exception {
        List<XWPFRun> runs = paragraph.getRuns();
        for (XWPFRun run : runs) {
            Object value = changeValue(run.toString(), picData);
            if (picData.containsKey(run.toString())) {
                //清空内容
                run.setText("", 0);
                FileInputStream is = new FileInputStream((String) value);
                //图片宽度、高度
                int width = Units.toEMU(100), height = Units.toEMU(100);
                //添加图片信息,段落高度需要在模板中自行调整
                run.addPicture(is, XWPFDocument.PICTURE_TYPE_PNG, (String) value, width, height);
            }
        }
    }

    /***
     * @Description :匹配参数
     * @param value
     * @param textMap
     * @return java.lang.Object
     * @Date 2022/11/18 11:33
     */
    public static Object changeValue(String value, Map<String, Object> textMap) {
        Object valu = "";
        for (Map.Entry<String, Object> textSet : textMap.entrySet()) {
            // 匹配模板与替换值 格式${key}
            String key = textSet.getKey();
            if (value.contains(key)) {
                valu = textSet.getValue();
            }
        }
        return valu;
    }
}

四、测试代码

public static void main(String[] args) throws Exception {
    Map<String, Object> data = new HashMap<>();
    Map<String, Object> picData = new HashMap<>();
    data.put("${aab999}", "123456789");
    data.put("${aac003}", "刘毅");
    data.put("${aac147}", "43102119001212109X");
    data.put("${aae004}", "刘毅");
    data.put("${aae005}", "13800000000");
    data.put("${aae013}", "");
    data.put("${aae123}", "刘毅");
    data.put("${aae123_1}", "");
    data.put("${aae123_2}", "");
    data.put("${aae124}", "刘小毅");
    data.put("${aae124_1}", "");
    data.put("${aae124_2}", "");
    picData.put("${aac013}", "C:\\Users\\Liu\\Pictures\\26ed64f74a659d46d6db0fd979bc0142.jpeg");
    operateWord(data, picData);
}

public static void operateWord(Map<String, Object> data, Map<String, Object> picData){
    try {
        FileInputStream is = new FileInputStream("D:\\test.docx");
        XWPFDocument document = new XWPFDocument(is);
        if (data.size() > 0) {
            // 替换掉表格之外的文本(仅限文本)
            ReplaceWord.changeText(document, data);
            // 替换表格内的文本对象
            ReplaceWord.changeTableText(document, data);
        }
        if (picData.size() > 0) {
            // 替换内容图片
            ReplaceWord.changePic(document, picData);
            // 替换表格内的图片对象
            ReplaceWord.changeTablePic(document, picData);
        }
        FileOutputStream out = new FileOutputStream("D:\\test2" + ".docx");
        document.write(out);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

五、模板内容

记录java使用POI实现word模板数据填充_第1张图片

六、效果图

记录java使用POI实现word模板数据填充_第2张图片

你可能感兴趣的:(Java,java,spring)