Java 使用poi,根据word模板导出word文件

一笑奈何 提交于 2020-01-17 02:56:32

标题 使用poi导出word文件

项目需求:需要将数据按照一定的格式导出成word文档。文本替换,表格循环(表格内部行循环,整个表格循环),插入图片等。

参考连接:https://blog.csdn.net/u012775558/article/details/79678701
在该博客的基础上加入了插入图片,换行显示等功能。

一、首先引入jar包
        <!--    导出word需要用的包      -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>4.0.1</version>
        </dependency>

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>4.0.1</version>
        </dependency>

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml-schemas</artifactId>
            <version>4.0.1</version>
        </dependency>
二、工具类WordTemplate
package com.example.demo1.util;

import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblBorders;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcBorders;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STBorder;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @ClassName:WordTemplate
 * @Description: TODO
 * @Author: fanwj
 * @Date: 2019/12/20 13:44
 */

public class WordTemplate {

    private XWPFDocument document;

    public XWPFDocument getDocument() {
        return document;
    }

    public void setDocument(XWPFDocument document) {
        this.document = document;
    }

    /**
     * 初始化模板内容
     *
     * @author Juveniless
     * @date 2017年11月27日 下午3:59:22
     * @param inputStream
     *            模板的读取流(docx文件)
     * @throws IOException
     *
     */

    public WordTemplate(InputStream inputStream) throws IOException {
        document = new XWPFDocument(inputStream);
    }

    /**
     * 将处理后的内容写入到输出流中
     *
     * @param outputStream
     * @throws IOException
     */

    public void write(OutputStream outputStream) throws IOException {
        document.write(outputStream);
    }





    /**
     * 根据dataMap对word文件中的标签进行替换; <br><br>
     * !!!!***需要注意dataMap的数据格式***!!!! <br><br>
     * 对于需要替换的普通标签数据标签(不需要循环)-----必须在dataMap中存储一个key为parametersMap的map,
     * 来存储这些不需要循环生成的数据,比如:表头信息,日期,制表人等。 <br><br>
     * 对于需要循环生成的表格数据------key自定义,value为 --ArrayList&lt;Map&lt;String, String>>
     * @author Juveniless
     * @date 2017年11月27日 下午3:29:27
     * @param dataMap
     *
     */
    public void replaceDocument(Map<String, Object> dataMap) {
        if (!dataMap.containsKey("parametersMap")) {
            System.out.println("数据源错误--数据源(parametersMap)缺失");
            return;
        }
        @SuppressWarnings("unchecked")
        Map<String, Object> parametersMap = (Map<String, Object>) dataMap
                .get("parametersMap");

        List<IBodyElement> bodyElements = document.getBodyElements();// 所有对象(段落+表格)
        int templateBodySize = bodyElements.size();// 标记模板文件(段落+表格)总个数

        int curT = 0;// 当前操作表格对象的索引
        int curP = 0;// 当前操作段落对象的索引
        for (int a = 0; a < templateBodySize; a++) {
            IBodyElement body = bodyElements.get(a);
            if (BodyElementType.TABLE.equals(body.getElementType())) {// 处理表格
                XWPFTable table = body.getBody().getTableArray(curT);

                List<XWPFTable> tables = body.getBody().getTables();
                table = tables.get(curT);
                if (table != null) {

                    // 处理表格
                    List<XWPFTableCell> tableCells = table.getRows().get(0).getTableCells();// 获取到模板表格第一行,用来判断表格类型
                    String tableText = table.getText();// 表格中的所有文本

                    if (tableText.indexOf("##{foreach") > -1) {
                        // 查找到##{foreach标签,该表格需要处理循环
                        if (tableCells.size() != 2
                                || tableCells.get(0).getText().indexOf("##{foreach") < 0
                                || tableCells.get(0).getText().trim().length() == 0) {
                            System.out
                                    .println("文档中第"
                                            + (curT + 1)
                                            + "个表格模板错误,模板表格第一行需要设置2个单元格,"
                                            + "第一个单元格存储表格类型(##{foreachTable}## 或者 ##{foreachTableRow}##),第二个单元格定义数据源。");
                            return;
                        }

                        String tableType = tableCells.get(0).getText();
                        String dataSource = tableCells.get(1).getText();
                        System.out.println("读取到数据源:"+dataSource);
                        if (!dataMap.containsKey(dataSource)) {
                            System.out.println("文档中第" + (curT + 1) + "个表格模板数据源缺失");
                            return;
                        }
                        @SuppressWarnings("unchecked")
                        List<Map<String, Object>> tableDataList = (List<Map<String, Object>>) dataMap
                                .get(dataSource);
                        //整个表格循环
                        if ("##{foreachTable}##".equals(tableType)) {
                            // System.out.println("循环生成表格");
                            addTableInDocFooter(table, tableDataList, parametersMap, 1);

                            //整个内行循环
                        } else if ("##{foreachTableRow}##".equals(tableType)) {
                            // System.out.println("循环生成表格内部的行");
                            addTableInDocFooter(table, tableDataList, parametersMap, 2);
                        }

                    } else if (tableText.indexOf("{") > -1) {
                        // 没有查找到##{foreach标签,查找到了普通替换数据的{}标签,该表格只需要简单替换
                        addTableInDocFooter(table, null, parametersMap, 3);
                    } else {
                        // 没有查找到任何标签,该表格是一个静态表格,仅需要复制一个即可。
                        addTableInDocFooter(table, null, null, 0);
                    }
                    curT++;

                }
            } else if (BodyElementType.PARAGRAPH.equals(body.getElementType())) {// 处理段落
                // System.out.println("获取到段落");
                XWPFParagraph ph = body.getBody().getParagraphArray(curP);
                if (ph != null) {
                    // htmlText = htmlText+readParagraphX(ph);
                    addParagraphInDocFooter(ph, null, parametersMap, 0);

                    curP++;
                }
            }

        }
        // 处理完毕模板,删除文本中的模板内容
        for (int a = 0; a < templateBodySize; a++) {
            document.removeBodyElement(0);
        }

    }

    /**
     * 根据 模板表格 和 数据list 在word文档末尾生成表格
     * @author Juveniless
     * @date 2017年12月6日 上午10:12:05
     * @param templateTable 模板表格
     * @param list   循环数据集
     * @param parametersMap  不循环数据集
     * @param flag   (0为静态表格,1为表格整体循环,2为表格内部行循环,3为表格不循环仅简单替换标签即可)
     *
     */

    public void addTableInDocFooter(XWPFTable templateTable, List<Map<String, Object>> list,
                                    Map<String, Object> parametersMap, int flag) {

        if (flag == 1) {// 表格整体循环
            for (Map<String, Object> map : list) {
                List<XWPFTableRow> templateTableRows = templateTable.getRows();// 获取模板表格所有行
                XWPFTable newCreateTable = document.createTable();// 创建新表格,默认一行一列
                for (int i = 1; i < templateTableRows.size(); i++) {
                    XWPFTableRow newCreateRow = newCreateTable.createRow();
                    CopyTableRow(newCreateRow, templateTableRows.get(i));// 复制模板行文本和样式到新行

                    /*表格复制时,边框不显示*/
                    for (int j = 0; j < newCreateRow.getTableCells().size(); j++) {
                        CTTcBorders tblBorders = newCreateRow.getCell(j).getCTTc().getTcPr().addNewTcBorders();
                        tblBorders.addNewLeft().setVal(STBorder.NIL);
                        tblBorders.addNewRight().setVal(STBorder.NIL);
                        tblBorders.addNewBottom().setVal(STBorder.NIL);
                        tblBorders.addNewTop().setVal(STBorder.NIL);
                        newCreateRow.getCell(j).getCTTc().getTcPr().setTcBorders(tblBorders);
                    }
                }

                newCreateTable.removeRow(0);// 移除多出来的第一行
                document.createParagraph();// 添加回车换行
                replaceTable(newCreateTable, map);//替换标签
            }

        } else if (flag == 2) {// 表格表格内部行循环
            XWPFTable newCreateTable = document.createTable();// 创建新表格,默认一行一列
            List<XWPFTableRow> TempTableRows = templateTable.getRows();// 获取模板表格所有行
            int tagRowsIndex = 0;// 标签行indexs
            for (int i = 0, size = TempTableRows.size(); i < size; i++) {
                String rowText = TempTableRows.get(i).getCell(0).getText();// 获取到表格行的第一个单元格
                if (rowText.indexOf("##{foreachRows}##") > -1) {
                    tagRowsIndex = i;
                    break;
                }
            }

            /* 复制模板行和标签行之前的行 */

            for (int i = 1; i < tagRowsIndex; i++) {
                XWPFTableRow newCreateRow = newCreateTable.createRow();
                CopyTableRow(newCreateRow, TempTableRows.get(i));// 复制行
                replaceTableRow(newCreateRow, parametersMap);// 处理不循环标签的替换
            }

            /* 循环生成模板行 */
            XWPFTableRow tempRow = TempTableRows.get(tagRowsIndex + 1);// 获取到模板行
            for (int i = 0; i < list.size(); i++) {
                XWPFTableRow newCreateRow = newCreateTable.createRow();
                CopyTableRow(newCreateRow, tempRow);// 复制模板行
                replaceTableRow(newCreateRow, list.get(i));// 处理标签替换
            }

            /* 复制模板行和标签行之后的行 */
            for (int i = tagRowsIndex + 2; i < TempTableRows.size(); i++) {
                XWPFTableRow newCreateRow = newCreateTable.createRow();
                CopyTableRow(newCreateRow, TempTableRows.get(i));// 复制行
                replaceTableRow(newCreateRow, parametersMap);// 处理不循环标签的替换
            }
            newCreateTable.removeRow(0);// 移除多出来的第一行
            document.createParagraph();// 添加回车换行

        } else if (flag == 3) {
            //表格不循环仅简单替换标签
            List<XWPFTableRow> templateTableRows = templateTable.getRows();// 获取模板表格所有行
            XWPFTable newCreateTable = document.createTable();// 创建新表格,默认一行一列
            for (int i = 0; i < templateTableRows.size(); i++) {
                XWPFTableRow newCreateRow = newCreateTable.createRow();
                CopyTableRow(newCreateRow, templateTableRows.get(i));// 复制模板行文本和样式到新行
            }
            newCreateTable.removeRow(0);// 移除多出来的第一行
            document.createParagraph();// 添加回车换行
            replaceTable(newCreateTable, parametersMap);

        } else if (flag == 0) {
            List<XWPFTableRow> templateTableRows = templateTable.getRows();// 获取模板表格所有行
            XWPFTable newCreateTable = document.createTable();// 创建新表格,默认一行一列
            for (int i = 0; i < templateTableRows.size(); i++) {
                XWPFTableRow newCreateRow = newCreateTable.createRow();
                CopyTableRow(newCreateRow, templateTableRows.get(i));// 复制模板行文本和样式到新行
            }
            newCreateTable.removeRow(0);// 移除多出来的第一行
            document.createParagraph();// 添加回车换行
        }

    }






    /**
     * 根据 模板段落 和 数据 在文档末尾生成段落
     *
     * @author Juveniless
     * @date 2017年11月27日 上午11:49:42
     * @param templateParagraph
     *            模板段落
     * @param list
     *            循环数据集
     * @param parametersMap
     *            不循环数据集
     * @param flag
     *            (0为不循环替换,1为循环替换)
     *
     */

    public void addParagraphInDocFooter(XWPFParagraph templateParagraph,
                                        List<Map<String, String>> list, Map<String, Object> parametersMap, int flag) {

        if (flag == 0) {
            XWPFParagraph createParagraph = document.createParagraph();
            // 设置段落样式
            createParagraph.getCTP().setPPr(templateParagraph.getCTP().getPPr());
            // 移除原始内容
            for (int pos = 0; pos < createParagraph.getRuns().size(); pos++) {
                createParagraph.removeRun(pos);
            }
            // 添加Run标签
            for (XWPFRun s : templateParagraph.getRuns()) {
                XWPFRun targetrun = createParagraph.createRun();
                CopyRun(targetrun, s);
            }

            replaceParagraph(createParagraph, parametersMap);

        } else if (flag == 1) {
            // 暂无实现
        }

    }




    /**
     * 根据map替换段落元素内的{**}标签
     * @author Juveniless
     * @date 2017年12月4日 下午3:09:00
     * @param xWPFParagraph
     * @param parametersMap
     *
     */


    public void replaceParagraph(XWPFParagraph xWPFParagraph, Map<String, Object> parametersMap) {
        List<XWPFRun> runs = xWPFParagraph.getRuns();
        String xWPFParagraphText = xWPFParagraph.getText();
        String regEx = "\\{.+?\\}";
        Pattern pattern = Pattern.compile(regEx);
        Matcher matcher = pattern.matcher(xWPFParagraphText);//正则匹配字符串{****}

        if (matcher.find()) {
            // 查找到有标签才执行替换
            int beginRunIndex = xWPFParagraph.searchText("{", new PositionInParagraph()).getBeginRun();// 标签开始run位置
            int endRunIndex = xWPFParagraph.searchText("}", new PositionInParagraph()).getEndRun();// 结束标签
            StringBuffer key = new StringBuffer();

            if (beginRunIndex == endRunIndex) {
                // {**}在一个run标签内
                XWPFRun beginRun = runs.get(beginRunIndex);
                String beginRunText = beginRun.text();

                int beginIndex = beginRunText.indexOf("{");
                int endIndex = beginRunText.indexOf("}");
                int length = beginRunText.length();

                if (beginIndex == 0 && endIndex == length - 1) {
                    // 该run标签只有{**}
                    XWPFRun insertNewRun = xWPFParagraph.insertNewRun(beginRunIndex);
                    insertNewRun.getCTR().setRPr(beginRun.getCTR().getRPr());
                    // 设置文本
                    key.append(beginRunText.substring(1, endIndex));
                    String value = getValueBykey(key.toString(),parametersMap);
                    if (isImage(value)==true){
                        int height = Units.toEMU(200);
                        int width = Units.toEMU(410);
                        String heightKey;
                        String imageWidth;
                        if (key.indexOf("**")>-1){
                            //截取**号
                            String key1 = key.toString().replaceAll("\\*","");
                            heightKey = getValueBykey(key1+"Height",parametersMap);
                            imageWidth = getValueBykey(key1+"Width",parametersMap);
                        }else {
                            String widthKey = key.toString()+"Width";
                            imageWidth = getValueBykey(widthKey,parametersMap);
                            heightKey = getValueBykey(key.toString()+"Height",parametersMap);
                        }
                        if (imageWidth!=null && imageWidth.length()>0){
                            width = Integer.parseInt(imageWidth);
                        }
                        if (heightKey!=null && heightKey.length()>0){
                            height = Integer.parseInt(heightKey);
                        }
                        try {
                            String fileExt = value.substring(value.lastIndexOf(".",value.length()));
                            int format = readImageExt(fileExt);
                            insertNewRun.addPicture(new FileInputStream(value),format,"", Units.toEMU(width),Units.toEMU(height));
                            document.createParagraph();// 添加回车换行
                            //insertNewRun.addBreak();
                        } catch (Exception e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }else {
                        insertNewRun.setText(getValueBykey(key.toString(),parametersMap));
                    }
                    xWPFParagraph.removeRun(beginRunIndex + 1);
                } else {
                    // 该run标签为**{**}** 或者 **{**} 或者{**}**,替换key后,还需要加上原始key前后的文本
                    XWPFRun insertNewRun = xWPFParagraph.insertNewRun(beginRunIndex);
                    insertNewRun.getCTR().setRPr(beginRun.getCTR().getRPr());
                    // 设置文本
                    key.append(beginRunText.substring(beginRunText.indexOf("{")+1, beginRunText.indexOf("}")));
                    String textString=beginRunText.substring(0, beginIndex) + getValueBykey(key.toString(),parametersMap)
                            + beginRunText.substring(endIndex + 1);

                    insertNewRun.setText(textString);
                    xWPFParagraph.removeRun(beginRunIndex + 1);
                }

            }else {
                // {**}被分成多个run
                //先处理起始run标签,取得第一个{key}值
                XWPFRun beginRun = runs.get(beginRunIndex);
                String beginRunText = beginRun.text();
                int beginIndex = beginRunText.indexOf("{");
                if (beginRunText.length()>1  ) {
                    key.append(beginRunText.substring(beginIndex+1));
                }
                ArrayList<Integer> removeRunList = new ArrayList<Integer>();//需要移除的run
                //处理中间的run
                for (int i = beginRunIndex + 1; i < endRunIndex; i++) {
                    XWPFRun run = runs.get(i);
                    String runText = run.text();
                    key.append(runText);
                    removeRunList.add(i);
                }

                // 获取endRun中的key值
                XWPFRun endRun = runs.get(endRunIndex);
                String endRunText = endRun.text();
                int endIndex = endRunText.indexOf("}");
                //run中**}或者**}**
                if (endRunText.length()>1 && endIndex!=0) {
                    key.append(endRunText.substring(0,endIndex));
                }
                //*******************************************************************
                //取得key值后替换标签

                //先处理开始标签
                if (beginRunText.length()==2 ) {
                    // run标签内文本{
                    XWPFRun insertNewRun = xWPFParagraph.insertNewRun(beginRunIndex);
                    insertNewRun.getCTR().setRPr(beginRun.getCTR().getRPr());
                    // 设置文本
                    insertNewRun.setText(getValueBykey(key.toString(),parametersMap));
                    xWPFParagraph.removeRun(beginRunIndex + 1);//移除原始的run
                }else {
                    // 该run标签为**{**或者 {** ,替换key后,还需要加上原始key前的文本
                    XWPFRun insertNewRun = xWPFParagraph.insertNewRun(beginRunIndex);
                    insertNewRun.getCTR().setRPr(beginRun.getCTR().getRPr());
                    // 设置文本
                    String textString=beginRunText.substring(0,beginRunText.indexOf("{"))+getValueBykey(key.toString(),parametersMap);
                        //	System.out.println(">>>>>"+textString);
                        //分行处理,案例:虽然你可能找不到对象@但你还是可以每天面向对象编程啊!
                        //上面那句话会从@哪那里分行,@后面的内容会显示在下一行
                        if(textString.contains("@")) {
                            String[] textStrings = textString.split("@");
                            for(int i = 0; i < textStrings.length;i++)
                            {
                                //System.out.println(">>>>>textStrings>>"+textStrings[i]);
                                insertNewRun.setText(textStrings[i]);
                                //insertNewRun.addCarriageReturn();
                                insertNewRun.addBreak();//换行
                            }
                         //图片
                        } else if(isImage(textString)==true) {
                            int width = Units.toEMU(410);
                            int height = Units.toEMU(200);
                            //可以设置图片的长,宽,比如在map中,图片的key为 **image**,  那只要设备imageWidth就是当前图片的长度,设置imageHeight就是图片的宽
                            //不设置的话默认值为410,200
                            String heightKey;
                            String imageWidth;
                            if (key.indexOf("**")>-1){
                                //截取**号
                                String key1 = key.toString().replaceAll("\\*","");
                                imageWidth = getValueBykey(key1+"Width",parametersMap);
                                heightKey = getValueBykey(key1+"Height",parametersMap);
                            }else {
                                String widthKey = key.toString()+"Width";
                                imageWidth = getValueBykey(widthKey,parametersMap);
                                heightKey = getValueBykey(key.toString()+"Height",parametersMap);
                            }
                            if (imageWidth!=null && imageWidth.length()>0){
                                width = Integer.parseInt(imageWidth);
                            }
                            if (heightKey!=null && heightKey.length()>0){
                                height = Integer.parseInt(heightKey);
                            }
                            try {
                                String fileExt = textString.substring(textString.lastIndexOf(".",textString.length()));
                                //写入图片
                                insertNewRun.addPicture(new FileInputStream(textString),readImageExt(fileExt),"", Units.toEMU(width),Units.toEMU(height));
                                document.createParagraph();// 添加回车换行
                                //insertNewRun.addBreak();
                            } catch (Exception e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                        } else {
                            insertNewRun.setText(textString);
                        }
                    xWPFParagraph.removeRun(beginRunIndex + 1);//移除原始的run
                }

                //处理结束标签
                if (endRunText.length()==1 ) {
                    // run标签内文本只有}
                    XWPFRun insertNewRun = xWPFParagraph.insertNewRun(endRunIndex);
                    insertNewRun.getCTR().setRPr(endRun.getCTR().getRPr());
                    // 设置文本
                    insertNewRun.setText("");
                    xWPFParagraph.removeRun(endRunIndex + 1);//移除原始的run

                }else {
                    // 该run标签为**}**或者 }** 或者**},替换key后,还需要加上原始key后的文本
                    XWPFRun insertNewRun = xWPFParagraph.insertNewRun(endRunIndex);
                    insertNewRun.getCTR().setRPr(endRun.getCTR().getRPr());
                    // 设置文本
                    String textString=endRunText.substring(endRunText.indexOf("}")+1);
                    insertNewRun.setText(textString);
                    xWPFParagraph.removeRun(endRunIndex + 1);//移除原始的run
                }

                //处理中间的run标签
                for (int i = 0; i < removeRunList.size(); i++) {
                    XWPFRun xWPFRun = runs.get(removeRunList.get(i));//原始run
                    XWPFRun insertNewRun = xWPFParagraph.insertNewRun(removeRunList.get(i));
                    insertNewRun.getCTR().setRPr(xWPFRun.getCTR().getRPr());
                    insertNewRun.setText("");
                    xWPFParagraph.removeRun(removeRunList.get(i) + 1);//移除原始的run
                }

            }// 处理${**}被分成多个run

            replaceParagraph( xWPFParagraph, parametersMap);

        }//if 有标签

    }

    /**
     * 复制表格行XWPFTableRow格式
     *
     * @param target
     *            待修改格式的XWPFTableRow
     * @param source
     *            模板XWPFTableRow
     */
    private void CopyTableRow(XWPFTableRow target, XWPFTableRow source) {

        int tempRowCellsize = source.getTableCells().size();// 模板行的列数
        for (int i = 0; i < tempRowCellsize - 1; i++) {
            target.addNewTableCell();// 为新添加的行添加与模板表格对应行行相同个数的单元格
        }
        // 复制样式
        target.getCtRow().setTrPr(source.getCtRow().getTrPr());
        // 复制单元格
        for (int i = 0; i < target.getTableCells().size(); i++) {
            copyTableCell(target.getCell(i), source.getCell(i));

            //判断表格是否是无边框的
            CTTblBorders tcBorders = source.getTable().getCTTbl().getTblPr().getTblBorders();
            if (tcBorders!=null){
                CTTcBorders tblBorders = target.getCell(i).getCTTc().getTcPr().addNewTcBorders();
                if (tcBorders.getBottom()!=null && tcBorders.getBottom().getVal().toString().equals("none")
                        && tcBorders.getTop()!=null && tcBorders.getTop().getVal().toString().equals("none")
                        && tcBorders.getLeft()!=null && tcBorders.getLeft().getVal().toString().equals("none")
                        && tcBorders.getRight()!=null && tcBorders.getRight().getVal().toString().equals("none")){
                    //判断底部的border是否为空
                    CTTcBorders ctTblBorders = source.getCell(i).getCTTc().getTcPr().getTcBorders();
                    if (ctTblBorders!=null && ctTblBorders.getBottom()!=null && !ctTblBorders.getBottom().getVal().toString().equals("none")){
                        tblBorders.addNewBottom().setVal(STBorder.SINGLE);
                    }else {
                        tblBorders.addNewBottom().setVal(STBorder.NIL);
                    }
                    if (ctTblBorders!=null && ctTblBorders.getTop()!=null && !ctTblBorders.getTop().getVal().toString().equals("none")){
                        tblBorders.addNewTop().setVal(STBorder.SINGLE);
                    }else {
                        tblBorders.addNewTop().setVal(STBorder.NIL);
                    }
                    tblBorders.addNewRight().setVal(STBorder.NIL);
                    tblBorders.addNewLeft().setVal(STBorder.NIL);

                    target.getCell(i).getCTTc().getTcPr().setTcBorders(tblBorders);
                }
            }
        }
    }

    /**
     * 复制单元格XWPFTableCell格式
     *
     * @author Juveniless
     * @date 2017年11月27日 下午3:41:02
     * @param newTableCell
     *            新创建的的单元格
     * @param templateTableCell
     *            模板单元格
     *
     */

    private void copyTableCell(XWPFTableCell newTableCell, XWPFTableCell templateTableCell) {
        //得到表格边框属性
        CTTcBorders tblBorders = templateTableCell.getCTTc().getTcPr().getTcBorders();

        // 列属性
        newTableCell.getCTTc().setTcPr(templateTableCell.getCTTc().getTcPr());
        //复制表格边框属性
        newTableCell.getCTTc().getTcPr().setTcBorders(tblBorders);
        // 删除目标 targetCell 所有文本段落
        for (int pos = 0; pos < newTableCell.getParagraphs().size(); pos++) {
            newTableCell.removeParagraph(pos);
        }
        // 添加新文本段落
        for (XWPFParagraph sp : templateTableCell.getParagraphs()) {
            XWPFParagraph targetP = newTableCell.addParagraph();
            copyParagraph(targetP, sp);
        }
    }

    /**
     * 复制文本段落XWPFParagraph格式
     *
     * @author Juveniless
     * @date 2017年11月27日 下午3:43:08
     * @param newParagraph
     *            新创建的的段落
     * @param templateParagraph
     *            模板段落
     *
     */

    private void copyParagraph(XWPFParagraph newParagraph, XWPFParagraph templateParagraph) {
        // 设置段落样式
        newParagraph.getCTP().setPPr(templateParagraph.getCTP().getPPr());
        // 添加Run标签
        for (int pos = 0; pos < newParagraph.getRuns().size(); pos++) {
            newParagraph.removeRun(pos);

        }
        for (XWPFRun s : templateParagraph.getRuns()) {
            XWPFRun targetrun = newParagraph.createRun();
            CopyRun(targetrun, s);
        }

    }

    /**
     * 复制文本节点run
     * @author Juveniless
     * @date 2017年11月27日 下午3:47:17
     * @param newRun
     *            新创建的的文本节点
     * @param templateRun
     *            模板文本节点
     *
     */
    private void CopyRun(XWPFRun newRun, XWPFRun templateRun) {
        newRun.getCTR().setRPr(templateRun.getCTR().getRPr());
        // 设置文本
        newRun.setText(templateRun.text());
    }

    /**
     * 根据参数parametersMap对表格的一行进行标签的替换
     *
     * @author Juveniless
     * @date 2017年11月23日 下午2:09:24
     * @param tableRow
     *            表格行
     * @param parametersMap
     *            参数map
     *
     */
    public void replaceTableRow(XWPFTableRow tableRow, Map<String, Object> parametersMap) {

        List<XWPFTableCell> tableCells = tableRow.getTableCells();
        for (XWPFTableCell xWPFTableCell : tableCells) {
            List<XWPFParagraph> paragraphs = xWPFTableCell.getParagraphs();
            for (XWPFParagraph xwpfParagraph : paragraphs) {

                replaceParagraph(xwpfParagraph, parametersMap);
            }
        }

    }

    /**
     * 根据map替换表格中的{key}标签
     * @author Juveniless
     * @date 2017年12月4日 下午2:47:36
     * @param xwpfTable
     * @param parametersMap
     *
     */
    public void replaceTable(XWPFTable xwpfTable, Map<String, Object> parametersMap){
        List<XWPFTableRow> rows = xwpfTable.getRows();
        for (XWPFTableRow xWPFTableRow : rows ) {
            List<XWPFTableCell> tableCells = xWPFTableRow.getTableCells();
            for (XWPFTableCell xWPFTableCell : tableCells ) {
                List<XWPFParagraph> paragraphs2 = xWPFTableCell.getParagraphs();
                for (XWPFParagraph xWPFParagraph : paragraphs2) {
                    replaceParagraph(xWPFParagraph, parametersMap);
                }
            }
        }
    }

    /**
     * @description: 获取指定键(key)所对应的值(value)
     * @params: 
     * @return: 
     * @author: fanwj
     * @Date: 2020/1/16 16:01
     */
    private String getValueBykey(String key, Map<String, Object> map) {
        String returnValue="";
        if (key != null) {
            try {
                returnValue=map.get(key)!=null ? map.get(key).toString() : "";
            } catch (Exception e) {
                // TODO: handle exception
                System.out.println("key:"+key+"***"+e);
                returnValue="";
            }

        }
        return returnValue;
    }

    public boolean isImage(String textString){
        return textString.endsWith(".emf") || textString.endsWith(".wmf") || textString.endsWith(".pict")
                || textString.endsWith(".jpeg") || textString.endsWith(".jpg") || textString.endsWith(".png")
                || textString.endsWith(".dib") || textString.endsWith(".gif") || textString.endsWith(".tiff")
                || textString.endsWith(".eps") || textString.endsWith(".bmp") || textString.endsWith(".wpg");
    }
    /**
     * @description: 判断图片的后缀,得到图片该用哪种格式
     * @params:
     * @return:
     * @author: fanwj
     * @Date: 2020/1/14 9:33
     */
    public int readImageExt(String fileExt) {
        int format = Document.PICTURE_TYPE_PNG;
        if(fileExt.endsWith(".emf")){
            format = Document.PICTURE_TYPE_EMF;
        } else if(fileExt.endsWith(".wmf")){
            format = Document.PICTURE_TYPE_WMF;
        } else if(fileExt.endsWith(".pict")) {
            format = Document.PICTURE_TYPE_PICT;
        } else if(fileExt.endsWith(".jpeg") || fileExt.endsWith(".jpg")) {
            format = Document.PICTURE_TYPE_JPEG;
        } else if(fileExt.endsWith(".png")) {
            format = Document.PICTURE_TYPE_PNG;
        } else if(fileExt.endsWith(".dib")) {
            format = Document.PICTURE_TYPE_DIB;
        } else if(fileExt.endsWith(".gif")) {
            format = Document.PICTURE_TYPE_GIF;
        } else if(fileExt.endsWith(".tiff")) {
            format = Document.PICTURE_TYPE_TIFF;
        } else if(fileExt.endsWith(".eps")) {
            format = Document.PICTURE_TYPE_EPS;
        } else if(fileExt.endsWith(".bmp")) {
            format = Document.PICTURE_TYPE_BMP;
        } else if(fileExt.endsWith(".wpg")) {
            format = Document.PICTURE_TYPE_WPG;
        }
        return format;
    }
}

三、自己制作的word模板
在这里插入图片描述

  1. 如果表格内要循环数据,则表格第一行需要有两列,第一个单元格必须填写
    ##{foreachTableRow}##,第二列单元格填写要替换的List集合名称,这里是subProjects
  2. **##{foreachRows}##**在哪一行,那么表格将从这一行开始循环生成数据。
  3. 图片:拟制后就是模板中图片格式,要有**号,map的key值也需要星号,如
parametersMap.put("**image**","/1.jpeg"); //图片
//图片的key值去掉**,加上Width,Height可以设置图片的大小
 parametersMap.put("imageWidth",100);
 //表格中图片大小
parametersMap.put("imageHeight",50);

4.普通的替换文本,在模板中直接加{}

表格整体循环
在这里插入图片描述
1.表格整体循环,第一行需要两个单元格,第一个单元格写**##{foreachTable}##**,第二个单元格写需要替换的List集合名称
2.其他需要替换的数据用标签代替即可

三、测试类
  public static void main(String[] args) throws IOException{
        Map<String, Object> wordDataMap = new HashMap<String, Object>();// 存储报表全部数据
        Map<String, Object> parametersMap = new HashMap<String, Object>();// 存储报表中不循环的数据

        parametersMap.put("name","XX项目");

        parametersMap.put("testName","XX试验任务");

        parametersMap.put("code","GH07822");

        parametersMap.put("taskCode","JKL/19S7");

        parametersMap.put("testHost","张三");

        parametersMap.put("examiner","lisi");

        parametersMap.put("description","sjjALjjskaaaaaaaa");

        parametersMap.put("referUsers","无望,上课时");

        parametersMap.put("equipment","设备1");

        parametersMap.put("files","记录表");

        parametersMap.put("time","2020-01-7");


        List<Map<String, Object>> images = new ArrayList<Map<String, Object>>();
        Map<String, Object> map1=new HashMap<>();
        map1.put("imageName", "图1:曲线图");
        map1.put("**imagePath**", "/1.jpeg");
        map1.put("imageDesc", "12121@qq.com");
        map1.put("imagePathWidth",100);
        map1.put("imagePathHeight",50);

        Map<String, Object> map2=new HashMap<>();
        map2.put("imageName", "图2:");
        map2.put("**imagePath**", "/1.jpeg");
        map2.put("imageDesc", "45445@qq.com");
        map2.put("imagePathWidth",100);
        map2.put("imagePathHeight",50);

        Map<String, Object> map3=new HashMap<>();
        map3.put("imageName", "图3:设备运行温度变化图");
        map3.put("**imagePath**", "/2.jpeg");
        map3.put("imageDesc", "6767@qq.com");
        map3.put("imagePathWidth",100);
        map3.put("imagePathHeight",50);

        parametersMap.put("imagePathWidth",100);
        parametersMap.put("imagePathHeight",50);

        images.add(map1);
        images.add(map2);
        images.add(map3);

        wordDataMap.put("parametersMap",parametersMap);
        wordDataMap.put("images",images);


        File file = new File("/prorecord.docx");//改成你本地文件所在目录


        // 读取word模板
        FileInputStream fileInputStream = new FileInputStream(file);
        WordTemplate template = new WordTemplate(fileInputStream);

        // 替换数据
        template.replaceDocument(wordDataMap);


        //生成文件
        File outputFile=new File("/输出.docx");//改成你本地文件所在目录
        FileOutputStream fos  = new FileOutputStream(outputFile);
        template.getDocument().write(fos);
    }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!