利用POI动态替换word模板中的值

利用POI动态替换word模板中的值

  • 概述
  • 引入依赖
  • 实现代码
  • 效果

概述

在需要使用word模板来动态生成合同、协议等文件时,可以利用Java POI来实现动态替换。
例如一下情况:
利用POI动态替换word模板中的值_第1张图片

引入依赖

下面展示一些 内联代码片

<dependency>
            <groupId>org.apache.poigroupId>
            <artifactId>poiartifactId>
            <version>3.9version>
        dependency>
        <dependency>
            <groupId>org.apache.poigroupId>
            <artifactId>poi-ooxmlartifactId>
            <version>3.9version>
        dependency>

实现代码

public void aucLotDownLoad(HttpServletResponse response) {
        SimpleDateFormat dateFormater = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            //获取模板文件的目录地址
            String fileDir = new File("C:\\Users\\issuser\\Documents").getCanonicalPath();
            //获取模板文件
            File demoFile = new File(fileDir + "/template.docx");

            FileInputStream in = new FileInputStream(demoFile);
            XWPFDocument hdt = new XWPFDocument(in);
            //替换读取到的word模板内容的指定字段
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("firstParty", "123");
            map.put("secondParty", "456");
            map.put("date", dateFormater.format(new Date()));
            replaceParams(hdt,map);
            //此处为表格中数据
            Map<String, Object> tableMap = new HashMap<String, Object>();
            tableMap.put("position","pe");
            tableMap.put("workTime","20");
            tableMap.put("wages",12345);
            replaceTableParams(hdt,tableMap);
            //!!若还有其他表格则继续按以上格式生成对应关键字的map做替换。
            
            //输出word内容文件流,提供下载
            response.setContentType("application/vnd.ms-word;charset=utf-8");
            response.setCharacterEncoding("utf-8");
            response.addHeader("Cache-Control", "no-cache");

            String fileName = "文件名";
            // Content-disposition属性设置成以附件方式进行下载
            // URLEncoder.encode解决中文名乱码(attachment;filename=中文文件名)
            try {
                response.setHeader("Content-disposition", "attachment;filename="+ URLEncoder.encode(fileName, "UTF-8")+".docx");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }

            try {
                OutputStream outputStream = response.getOutputStream();
                outputStream.flush();
                hdt.write(outputStream);
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

以下为函数方法,可直接复制使用(转于https://www.cnblogs.com/faxi/p/15143820.html)

/**
     * 替换段落里面的变量
     *
     * @param doc    要替换的文档
     * @param params 参数
     */
    private static void replaceParams(XWPFDocument doc, Map<String, Object> params) {
        Iterator<XWPFParagraph> iterator = doc.getParagraphsIterator();
        XWPFParagraph paragraph;
        while (iterator.hasNext()) {
            paragraph = iterator.next();
            replaceParam(paragraph, params);
        }
    }

    /**
     * @param doc        docx解析对象
     * @param params     需要替换的信息集合
     * @param tableIndex 第几个表格
     * @param tableList  需要插入的表格信息集合
     */
    public static void changeTable(XWPFDocument doc, Map<String, Object> params, int tableIndex, List<String[]> tableList) {
        //获取表格对象集合
        List<XWPFTable> tables = doc.getTables();
        //获取第一个表格   根据实际模板情况 决定去第几个word中的表格
        XWPFTable table = tables.get(tableIndex);
        //替换表格中的参数
        replaceTableParams(doc, params);
        //在表格中插入数据
        insertTable(table, tableList);
    }

    /**
     * 替换表格里面的变量
     *
     * @param doc    要替换的文档
     * @param params 参数
     */
    private static void replaceTableParams(XWPFDocument doc, Map<String, Object> params) {
        Iterator<XWPFTable> iterator = doc.getTablesIterator();
        XWPFTable table;
        List<XWPFTableRow> rows;
        List<XWPFTableCell> cells;
        List<XWPFParagraph> paras;
        while (iterator.hasNext()) {
            table = iterator.next();
            //判断表格是需要替换还是需要插入,判断逻辑有$为替换,表格无$为插入
            if (matcher(table.getText()).find()) {
                rows = table.getRows();
                for (XWPFTableRow row : rows) {
                    cells = row.getTableCells();
                    for (XWPFTableCell cell : cells) {
                        paras = cell.getParagraphs();
                        for (XWPFParagraph para : paras) {
                            replaceParam(para, params);
                        }
                    }
                }
            }

        }
    }

    /**
     * 为表格插入行数,此处不处理表头,所以从第二行开始
     *
     * @param table     需要插入数据的表格
     * @param tableList 插入数据集合
     */
    private static void insertTable(XWPFTable table, List<String[]> tableList) {
        //创建与数据一致的行数
        for (int i = 0; i < tableList.size(); i++) {
            table.createRow();
        }
        int length = table.getRows().size();
        for (int i = 1; i < length; i++) {
            XWPFTableRow newRow = table.getRow(i);
            List<XWPFTableCell> cells = newRow.getTableCells();
            for (int j = 0; j < cells.size(); j++) {
                XWPFTableCell cell = cells.get(j);
                cell.setText(tableList.get(i - 1)[j]);
            }
        }
    }

    /**
     * 替换段落里面的变量
     *
     * @param paragraph 要替换的段落
     * @param params    参数
     */
    private static void replaceParam(XWPFParagraph paragraph, Map<String, Object> params) {
        List<XWPFRun> runs;
        Matcher matcher;
        String runText = "";

        if (matcher(paragraph.getParagraphText()).find()) {
            runs = paragraph.getRuns();
            int j = runs.size();
            for (int i = 0; i < j; i++) {
                runText += runs.get(0).toString();
                //保留最后一个段落,在这段落中替换值,保留段落样式
                if (!((j - 1) == i)) {
                    paragraph.removeRun(0);
                }
            }
            matcher = matcher(runText);
            if (matcher.find()) {
                while ((matcher = matcher(runText)).find()) {
                    runText = matcher.replaceFirst(String.valueOf(params.get(matcher.group(1))));
                }
                runs.get(0).setText(runText, 0);
            }
        }

    }

    /**
     * 正则匹配字符串
     *
     * @param str
     * @return
     */
    private static Matcher matcher(String str) {
        Pattern pattern = Pattern.compile("\\$\\{(.+?)\\}", Pattern.CASE_INSENSITIVE);
        Matcher matcher = pattern.matcher(str);
        return matcher;
    }

效果

利用POI动态替换word模板中的值_第2张图片

在word 2007及以后使用的是.docx格式,使用此处的XWPFDocument 即可,若是03版本的.doc格式,则需要换成HWPFDocument。
主要方法如下:

String fileDir = new File(base.getFile(), "../../../../../../doc/").getCanonicalPath();
//获取模板文件
File demoFile=new File(fileDir + "/1.doc");

FileInputStream in = new FileInputStream(demoFile);
HWPFDocument hdt = new HWPFDocument(in);
//替换读取到的word模板内容的指定字段
Range range = hdt.getRange();
Map<String, String> map = new HashMap<String, String>();
map.put("$PMBD$", goodsName);
map.put("$PMKSSJ$", dateFormater.format(startTime));
map.put("$MSRHP$", brandNo);
map.put("$PMCJJ$", numberToHanZiUtility.number2CNMontrayUnit(dealPrice));
map.put("$PMYJ$", numberToHanZiUtility.number2CNMontrayUnit(clientCommison));
map.put("$HJ$", numberToHanZiUtility.number2CNMontrayUnit(totalPrice));
map.put("$HJXX$", totalPrice + "");
map.put("$PMJSSJ$", dateFormater.format(endTime));
for (Map.Entry<String,String> entry:map.entrySet()) {
range.replaceText(entry.getKey(),entry.getValue());

可参考https://www.cnblogs.com/mr-wuxiansheng/p/6131494.html

你可能感兴趣的:(笔记,java,poi)