Java poi word模板填充数据、复制行删除行

该博客主要介绍如何使用Java的POI库来实现Word文档模板的数据动态替换。内容包括替换段落、表格中的变量,以及处理列表格式的数据。示例代码详细展示了如何遍历文档中的段落、表格,并根据预定义的模板变量进行替换,以生成填充后的Word文档。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Java poi word模板填充数据

1、明细表格式 ${list_xxxxx} 普通格式 ${xxxxxx}

2、replaceInTable方法中 table.removeRow(2); 第三行是明细数据的第一行

工具类

public class WordOperationUtil {


    public void replaceWordContext(XWPFDocument doc, List<Map<String, Object>> params) throws InvalidFormatException, IOException, XmlException {
        replaceInHeader(doc, params);
        replaceInTable(doc, params);
        replaceInPara(doc, params);

    }


    /**
     * 替换段落里面的变量
     *
     * @param para   要替换的段落
     * @param params 参数
     * @throws FileNotFoundException
     * @throws InvalidFormatException
     */
    public void replaceInPara(XWPFParagraph para, List<Map<String, Object>> params) throws InvalidFormatException, FileNotFoundException {


        if (this.matcher(para.getParagraphText()).find()) {
            List<XWPFRun> runs = para.getRuns();
            if (runs.size() == 0) {
                return;
            }
            String text = "";

            for (int i = 0; i < runs.size(); i++) {
                text += runs.get(i).text();
            }
            for (int i = 1; i < runs.size(); i++) {
                para.removeRun(i);
            }

            String outStr = getStrings(text, params.get(0));
            XWPFRun runX = para.getRuns().get(0);
            runX.setText(outStr, 0);


        }
    }

    /**
     * 替换段落里面的变量
     *
     * @param para   要替换的段落
     * @param params 参数
     * @throws FileNotFoundException
     * @throws InvalidFormatException
     */
    public void replaceInParaList(XWPFParagraph para, String params) throws InvalidFormatException, FileNotFoundException {

        List<XWPFRun> runs = para.getRuns();
        if (runs.size() == 0) {
            return;
        }
        for (int i = 1; i < runs.size(); i++) {
            para.removeRun(i);
            i--;
        }
        XWPFRun runX = para.getRuns().get(0);
        runX.setText(params, 0);
    }


    public String getStrings(String inStr, Map<String, Object> mapvalue) {
        String outStr = inStr;
        String regex = "\\$\\{(.*?)\\}";//qq(.*?)qq//\\@(.*?)\\@
        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(inStr);
        while (m.find()) {
            String ppStr = m.group(0);
            String ppReslutStr = m.group(1);
            outStr = strReplaceAll(outStr, ppStr, getMapValue(mapvalue, ppReslutStr));
        }
        return outStr;
    }


    public Map<String, Object> getListStrings(String inStr) {
        Map<String, Object> outMap = new HashMap<>();
        boolean out = false;

        String regex = "\\$\\{list_(.*?)\\}";//qq(.*?)qq//\\@(.*?)\\@
        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(inStr);
        while (m.find()) {
            String ppReslutStr = m.group(1);

            out = true;
            outMap.put("filedName", ppReslutStr);
        }
        outMap.put("issuccess", out);
        return outMap;
    }


    private String getMapValue(Map<String, Object> mapvalue, String key) {
        String outStr = key;
        if (mapvalue.containsKey(key)) {
            outStr = mapvalue.get(key).toString();
        }
        return outStr;
    }

    private String strReplaceAll(String inStr, String target, String replacement) {
        String outStr = inStr;
        outStr = inStr.replace(target, replacement);
        if (outStr.contains(target)) {
            outStr = strReplaceAll(outStr, target, replacement);
        }
        return outStr;

    }


    /**
     * 替换表格里面的变量
     *
     * @param doc    要替换的文档
     * @param params 参数
     * @throws FileNotFoundException
     * @throws InvalidFormatException
     */
    public void replaceInTable(XWPFDocument doc, List<Map<String, Object>> params) throws InvalidFormatException, IOException, XmlException {
        List<XWPFTable> xwpfTables = doc.getTables();
        for (XWPFTable table : xwpfTables) {
            replaceInTable(table, params);
        }
    }

    public void replaceInTable(XWPFTable table, List<Map<String, Object>> params) throws InvalidFormatException, IOException, XmlException {
        String text = table.getText();
        boolean islist = (boolean) getListStrings(text).get("issuccess");
        int i = 0;
        List<XWPFTableRow> rows = table.getRows();
        List<String> fileds = new ArrayList<>();


        if (islist) {
            for (int t = 0; t < rows.size(); t++) {
                XWPFTableRow row = rows.get(t);
                List<XWPFTableCell> cells = row.getTableCells();
                for (XWPFTableCell cell : cells) {
                    String cellText = cell.getText();
                    boolean isListFiledName = (boolean) getListStrings(cellText).get("issuccess");
                    if (isListFiledName) {
                        String filedName = (String) getListStrings(cellText).get("filedName");
                        fileds.add(filedName);
                        i++;
                    }

                }
                if (i > 0) {
                    break;
                }
            }


            for (int j = 0; j < params.size(); j++) {
                //XWPFTableRow row = rows.get(j + 1);
                //XmlObject copy = row.getCtRow().copy();
                //table.addRow(new XWPFTableRow((CTRow) copy, table));
                //复制表头行的样式
                CTRow ctrow = CTRow.Factory.parse(table.getRow(2).getCtRow().newInputStream());//重点行

                XWPFTableRow newrow = new XWPFTableRow(ctrow, table);
                List<XWPFTableCell> cells = newrow.getTableCells();
                int t = 0;
                for (XWPFTableCell cell : cells) {
                    List<XWPFParagraph> paras = cell.getParagraphs();
                    String value = "";
                    for (XWPFParagraph para : paras) {

                        value = params.get(j).get(fileds.get(t)).toString();
                        replaceInParaList(para, value);
                    }
                    //cell.setText(value,0);
                    t++;
                }
                table.addRow(newrow);
            }
            table.removeRow(2);


        } else {
            for (XWPFTableRow row : rows) {
                List<XWPFTableCell> cells = row.getTableCells();
                for (XWPFTableCell cell : cells) {
                    List<XWPFParagraph> paras = cell.getParagraphs();
                    for (XWPFParagraph para : paras) {
                        this.replaceInPara(para, params);
                    }
                }
            }

        }


    }


    /**
     * 替换段落里面的变量
     *
     * @param doc    要替换的文档
     * @param params 参数
     * @throws FileNotFoundException
     * @throws InvalidFormatException
     */
    public void replaceInPara(XWPFDocument doc, List<Map<String, Object>> params) throws InvalidFormatException, FileNotFoundException {
        Iterator<XWPFParagraph> iterator = doc.getParagraphsIterator();
        while (iterator.hasNext()) {
            XWPFParagraph para = iterator.next();
            this.replaceInPara(para, params);
        }
    }

    public void replaceInHeader(XWPFDocument doc, List<Map<String, Object>> params) throws InvalidFormatException, IOException, XmlException {
        List<XWPFHeader> pageHeaders = doc.getHeaderList();
        for (XWPFHeader pageHeader : pageHeaders) {
            List<XWPFParagraph> paragraphs = pageHeader.getParagraphs();
            List<XWPFTable> tables = pageHeader.getTables();

            for (XWPFParagraph paragraph : paragraphs) {
                this.replaceInPara(paragraph, params);
            }
            for (XWPFTable table : tables) {
                this.replaceInTable(table, params);
            }

        }
    }


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

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

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

    /****************************************************************没用到************************************************************/
    /**
     * 替换段落里面的变量
     *
     * @param para   要替换的段落
     * @param params 参数
     * @throws FileNotFoundException
     * @throws InvalidFormatException
     */
    public void replaceInPara0(XWPFParagraph para, Map<String, Object> params) throws InvalidFormatException, FileNotFoundException {


        if (this.matcher(para.getParagraphText()).find()) {


            List<XWPFRun> runs = para.getRuns();

            for (int i = 0; i < runs.size(); i++) {
                XWPFRun run = runs.get(i);
                String runText = run.text();
                if (matcher(runText).find()) {
                    String outStr = getStrings(runText, params);

                    run.setText(outStr, 0);

                    //XWPFRun runX = para.createRun();
                    //runX.setText(outStr);
                    //setTextStyle(  runX, run);
                }

                //para.removeRun(i);
            }

        }
    }

    private void setTextStyle(XWPFRun runX, XWPFRun replace) {

        runX.setCapitalized(replace.isCapitalized());//我也不知道这个属性做啥的
        runX.setTextPosition(replace.getTextPosition());//这个相当于设置行间距的,此元素指定文本应为此运行在关系到周围非定位文本的默认基线升降的量。不是真正意义上的行间距
        runX.setStrike(replace.isStrike());//---设置删除线的,坑人!!!
        runX.setStrikeThrough(replace.isStrikeThrough());//也是设置删除线,可能有细微的区别吧
        runX.setEmbossed(replace.isEmbossed());//变的有重影(变黑了一点)
        runX.setDoubleStrikethrough(replace.isDoubleStrikeThrough());//设置双删除线
        runX.setColor(replace.getColor());//---设置字体颜色
        runX.setFontFamily(replace.getFontFamily());
        //runX.setFontFamily("cursive");//---设置ASCII(0 - 127)字体样式
        runX.setBold(replace.isBold());//加粗
        runX.setFontSize(replace.getFontSize());//---字体大小
        runX.setImprinted(replace.isImprinted());//感觉与setEmbossed(true)类似,有重影
        runX.setItalic(replace.isItalic());//---文本会有倾斜,是一种字体?
        runX.setShadow(replace.isShadowed());//---文本会变粗有重影,与前面两个有重影效果的方法感觉没什么区别
        runX.setSmallCaps(replace.isSmallCaps());//---改变了  英文字母  的格式
        runX.setSubscript(replace.getSubscript());//---valign垂直对齐的
        runX.setUnderline(replace.getUnderline());//--填underline type设置下划线

    }

    /**
     * 替换段落里面的变量
     *
     * @param para   要替换的段落
     * @param params 参数
     * @throws FileNotFoundException
     * @throws InvalidFormatException
     */
    public void replaceInPara2(XWPFParagraph para, Map<String, Object> params) throws InvalidFormatException, FileNotFoundException {


        if (this.matcher(para.getParagraphText()).find()) {
            List<XWPFRun> runs = para.getRuns();

            String text = "";
            for (int i = 0; i < runs.size(); i++) {
                text += runs.get(i).toString();
            }

            String outStr = getStrings(text, params);
            if (text.contains("$")) {
                Object[] runArr = runs.toArray();
                int $Index = 0;
                for (int j = 0; j < runArr.length; j++) {
                    if (runArr[j].toString().contains("$")) {
                        $Index = j;
                        break;
                    }
                }
                int startIn = $Index;
                while (startIn < runs.size()) {
                    para.removeRun(startIn);
                }
                para.createRun().setText(outStr);
            }
        }
    }


}

2、方法调用

public static void main(String[] args) throws IOException, InvalidFormatException, XmlException {
        List<Map<String, Object>> maplists =new ArrayList<>();
        Map<String, Object> params0 = new HashMap<>();
         
        params0.put("orderno", "1");
        

        maplists.add(params0);

 

        InputStream is   = new FileInputStream(new File("C:\\Users\\xxxxx\\Desktop\\word\\temp.docx"));
        XWPFDocument doc= new XWPFDocument(is);
        WordOperationUtil   wordOperationUtil = new WordOperationUtil();
        wordOperationUtil.replaceWordContext(doc, maplists);

        //此处不指定下载目录,默认到用户本地的下载文件下
        OutputStream os = new FileOutputStream(new File("C:\\Users\\xxxx\\Desktop\\word\\temp2.docx"));
        doc.write(os);
        wordOperationUtil.close(os);
        wordOperationUtil.close(is);
        os.flush();
        os.close();
        System.out.println("word成功生成");
        //String inStr ="${list_eeertyyu}rrfvvrfrf${list_tttt}kkkkkk${list_cddddddddd}";
        //getListStrings(  inStr,new HashMap<>());
    }

模板格式

模板图片

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值