直接上代码

我这里做的有点复杂了,加入了图表以及echarts图表在后台的生成和截取,如果读者需要简单使用的代码,找我要即可,或者自己研究修改这个代码就可使用

public class WordTemplateUtil {
    private static Log logger = LogFactory.getLog(WordTemplateUtil.class);
    private static final String PREFIX = "{";
    private static final String SUFFIX = "}";
    private XWPFDocument document;

    public XWPFDocument getDocument() {
        return document;
    }

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

    /**
     * 初始化模板内容
     *
     * @param inputStream 模板的读取流(docx文件)
     * @throws IOException
     * @author: wj
     * @date: 2018年12月27日
     */
    public WordTemplateUtil(InputStream inputStream) throws IOException {
        logger.info("初始化模板...");
        document = new XWPFDocument(inputStream);
        logger.info("初始化模板结束");
    }

    /**
     * 将处理后的内容写入到输出流中
     *
     * @param outputStream
     * @throws IOException
     */
    public void write(OutputStream outputStream) throws IOException {
        logger.info("开始写出内容...");
        document.write(outputStream);
        logger.info("写出结束");
    }

    /**
     * 根据dataMap对word文件中的标签进行替换; <br><br>
     * !!!!***需要注意dataMap的数据格式***!!!! <br><br>
     * 对于需要替换的普通标签数据标签(不需要循环)-----必须在dataMap中存储一个key为parametersMap的map,
     * 来存储这些不需要循环生成的数据,比如:表头信息,日期,制表人等。 <br><br>
     * 对于需要循环生成的表格数据------key自定义,value为 --ArrayList<Map<String, String>>
     *
     * @param dataMap
     * @author: wj
     * @date: 2018年12月27日
     */
    public void replaceDocument(Map<String, Object> dataMap) {
        if (!dataMap.containsKey("parametersMap")) {
            logger.info("数据源错误--数据源(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) {
                            logger.info("文档中第" + (curT + 1) + "个表格模板错误,模板表格第一行需要设置2个单元格," + "第一个单元格存储表格类型(##{foreachTable}## 或者 ##{foreachTableRow}##),第二个单元格定义数据源。");
                            return;
                        }
                        String tableType = tableCells.get(0).getText();
                        String dataSource = tableCells.get(1).getText();
                        logger.info("读取到数据源:" + dataSource);
                        if (!dataMap.containsKey(dataSource)) {
                            logger.info("文档中第" + (curT + 1) + "个表格模板数据源缺失");
                            return;
                        }
                        @SuppressWarnings("unchecked")
                        List<Map<String, Object>> tableDataList = (List<Map<String, Object>>) dataMap.get(dataSource);
                        if ("##{foreachTable}##".equals(tableType)) {
                            logger.info("循环生成表格");
                            addTableInDocFooter(table, tableDataList, parametersMap, 1);
                        } else if ("##{foreachTableRow}##".equals(tableType)) {
                            logger.info("循环生成表格内部的行");
                            addTableInDocFooter(table, tableDataList, parametersMap, 2);
                        }
                    } else if (tableText.indexOf(PREFIX) > -1) {
                        // 没有查找到##{foreach标签,查找到了普通替换数据的{}标签,该表格只需要简单替换
                        addTableInDocFooter(table, null, parametersMap, 3);
                    } else {
                        // 没有查找到任何标签,该表格是一个静态表格,仅需要复制一个即可。
                        addTableInDocFooter(table, null, null, 0);
                    }
                    curT++;
                }
            } else if (BodyElementType.PARAGRAPH.equals(body.getElementType())) {
                // 处理段落
                logger.info("获取到段落");
                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);
        }
    }

    /**
     * }
     * }
     * }
     * <p>
     * /*根据 模板表格 和 数据list 在word文档末尾生成表格
     *
     * @param templateTable                                    模板表格
     * @param list                                             循环数据集
     * @param parametersMap                                    不循环数据集
     * @param flag(0为静态表格,1为表格整体循环,2为表格内部行循环,3为表格不循环仅简单替换标签即可)
     * @author wj
     * @date 2018 年12月28日
     */
    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();
                CTTbl ctTbl = newCreateTable.getCTTbl();
                ctTbl.getTblPr().set(templateTable.getCTTbl().getTblPr());
                if(templateTable.getCTTbl() != null){
                    CTTblGrid cg = ctTbl.addNewTblGrid();
                    cg.addNewGridCol().set(templateTable.getCTTbl().getTblGrid());
                }
                for (int i = 1; i < templateTableRows.size(); i++) {
                    XWPFTableRow newCreateRow = newCreateTable.createRow();
                    // 复制模板行文本和样式到新行
                    CopyTableRow(newCreateRow, templateTableRows.get(i));
                }
                // 移除多出来的第一行
                newCreateTable.removeRow(0);
                // 添加回车换行
                //document.createParagraph();
                //替换标签
                replaceTable(newCreateTable, map);
            }
        } else if (flag == 2) {
            // 表格表格内部行循环
            XWPFTable newCreateTable = document.createTable();
            CTTbl ctTbl = newCreateTable.getCTTbl();
            ctTbl.getTblPr().set(templateTable.getCTTbl().getTblPr());
            if(templateTable.getCTTbl() != null){
                CTTblGrid cg = ctTbl.addNewTblGrid();
                cg.addNewGridCol().set(templateTable.getCTTbl().getTblGrid());
            }
            // 创建新表格,默认一行一列
            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();
            CTTbl ctTbl = newCreateTable.getCTTbl();
            ctTbl.getTblPr().set(templateTable.getCTTbl().getTblPr());
            if(templateTable.getCTTbl() != null){
                CTTblGrid cg = ctTbl.addNewTblGrid();
                cg.addNewGridCol().set(templateTable.getCTTbl().getTblGrid());
            }
            // 创建新表格,默认一行一列
            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();
            // 添加回车换行
        }
    }

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

    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替换段落元素内的 {**} 标签
     *
     * @param xWPFParagraph
     * @param parametersMap
     * @author: wj
     * @date: 2018年12月27日
     */
    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()) {
            // 标签开始run位置
            int beginRunIndex = xWPFParagraph.searchText(PREFIX, new PositionInParagraph()).getBeginRun();
            // 结束标签
            int endRunIndex = xWPFParagraph.searchText(SUFFIX, new PositionInParagraph()).getEndRun();
            StringBuffer key = new StringBuffer();
            if (beginRunIndex == endRunIndex) {
                // {**}在一个run标签内
                XWPFRun beginRun = runs.get(beginRunIndex);
                String beginRunText = beginRun.text();
                int beginIndex = beginRunText.indexOf(PREFIX);
                int endIndex = beginRunText.indexOf(SUFFIX);
                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));
                    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(PREFIX) + 1, beginRunText.indexOf(SUFFIX)));
                    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(PREFIX);
                if (beginRunText.length() > 1) {
                    key.append(beginRunText.substring(beginIndex + 1));
                }
                //需要移除的run //处理中间的run
                ArrayList<Integer> removeRunList = new ArrayList<>();
                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(SUFFIX);
                //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));
                    //移除原始的run
                    xWPFParagraph.removeRun(beginRunIndex + 1);
                } else {
                    // 该run标签为**{**或者 {** ,替换key后,还需要加上原始key前的文本
                    XWPFRun insertNewRun = xWPFParagraph.insertNewRun(beginRunIndex);
                    insertNewRun.getCTR().setRPr(beginRun.getCTR().getRPr());
                    // 设置文本
                    String textString = beginRunText.substring(0, beginRunText.indexOf(PREFIX)) + getValueBykey(key.toString(), parametersMap);
                    insertNewRun.setText(textString);
                    //移除原始的run
                    xWPFParagraph.removeRun(beginRunIndex + 1);
                }
                //处理结束标签
                if (endRunText.length() == 1) {
                    // run标签内文本只有}
                    XWPFRun insertNewRun = xWPFParagraph.insertNewRun(endRunIndex);
                    insertNewRun.getCTR().setRPr(endRun.getCTR().getRPr());
                    // 设置文本
                    insertNewRun.setText("");
                    //移除原始的run
                    xWPFParagraph.removeRun(endRunIndex + 1);
                } else {
                    // 该run标签为**}**或者 }** 或者**},替换key后,还需要加上原始key后的文本
                    XWPFRun insertNewRun = xWPFParagraph.insertNewRun(endRunIndex);
                    insertNewRun.getCTR().setRPr(endRun.getCTR().getRPr());
                    // 设置文本
                    String textString = endRunText.substring(endRunText.indexOf(SUFFIX) + 1);
                    insertNewRun.setText(textString);
                    //移除原始的run
                    xWPFParagraph.removeRun(endRunIndex + 1);
                } //处理中间的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));
        }
    }

    /**
     * 复制单元格XWPFTableCell格式
     *
     * @param newTableCell      新创建的的单元格
     * @param templateTableCell 模板单元格
     * @author: wj
     * @date: 2018年12月27日
     */
    private void copyTableCell(XWPFTableCell newTableCell, XWPFTableCell templateTableCell) {
        // 列属性
        newTableCell.getCTTc().setTcPr(templateTableCell.getCTTc().getTcPr());
        // 删除目标
        // 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格式
     *
     * @param newParagraph      新创建的的段落
     * @param templateParagraph 模板段落
     * @author: wj
     * @date: 2018年12月27日
     */
    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
     *
     * @param newRun      新创建的的文本节点
     * @param templateRun 模板文本节点
     * @author: wj
     * @date: 2018年12月27日
     */
    private void CopyRun(XWPFRun newRun, XWPFRun templateRun) {
        newRun.getCTR().setRPr(templateRun.getCTR().getRPr());
        // 设置文本
        newRun.setText(templateRun.text());
    }

    /**
     * 根据参数parametersMap对表格的一行进行标签的替换
     *
     * @param tableRow      表格行
     * @param parametersMap 参数map
     * @author: wj
     * @date: 2018年12月27日
     */
    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}标签
     *
     * @param xwpfTable
     * @param parametersMap
     * @author: wj
     * @date: 2018年12月27日
     */
    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);
                }
            }
        }
    }

    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
                logger.info("key:" + key + "***" + e);
                returnValue = "";
            }
        }
        return returnValue;
    }
}

调用

//我这里稍微复杂点,判断了是否有图表,并将写出文件的路径放入集合中返回了
//参数说明:
//String modularPath  模板路径
//Map<String, Object> wordDataMap, 需要替换的变量
//String downLoadPath, 写出路径
//List<String> srcPathsList, 写出的路径集合
//AnalysisReportSql analysisReportSql 我自己封装的对象,读者使用时替换即可
//String echarts 可根据自己是否需要生成echarts图表进行选择,不需要直接该方法参数即可
private static List<String> writeSmallModel(String modularPath, int i, Map<String, Object> wordDataMap, String downLoadPath, List<String> srcPathsList, AnalysisReportSql analysisReportSql,String echarts) throws Exception {
        File file = new File(modularPath);
        log.info(file);
        FileInputStream fileInputStream = new FileInputStream(file);
        WordTemplateUtil template = new WordTemplateUtil(fileInputStream);
        template.replaceDocument(wordDataMap);
        String srcPath = downLoadPath + i + ".docx";
        File outputFile = new java.io.File(srcPath);
        String outFilePath = outputFile.toString().substring(0, outputFile.toString().lastIndexOf(File.separator));
        File file1 = new File(outFilePath);
        //改成你本地文件所在目录
         if (!file1.exists()) {
              file1.mkdirs();
         }
        FileOutputStream fos = new FileOutputStream(outputFile);
        XWPFDocument xwpfDocument = template.getDocument();
        // 替换图表
        XWPFDocument doc = new XWPFDocument(new FileInputStream(file));
        if (wordDataMap.get("chartParam") != null) {
              doCharts(doc, wordDataMap);
              doc.write(fos);
              doc.close();
        } else if (wordDataMap.get("echartsParam") != null) {
              doEcharts(doc, wordDataMap, analysisReportSql,downLoadPath,i,echarts);
              doc.write(fos);
              doc.close();
        } else {
              xwpfDocument.write(fos);
              xwpfDocument.close();
        }
        srcPathsList.add(srcPath);
        fileInputStream.close();
        xwpfDocument.close();
        fos.close();
        return srcPathsList;
    }
 /**
     * 处理echarts图表
     */
    private static XWPFDocument doEcharts(XWPFDocument doc, Map<String, Object> wordDataMap, AnalysisReportSql analysisReportSql,String downLoadPath,int i,String echarts) throws Exception {
        List<AnalysisReportSql> echartsParamList = (List<AnalysisReportSql>)wordDataMap.get("echartsParam");
        return writeEcharts(doc,echarts, downLoadPath, i,echartsParamList.get(0).getChartModule());
    }


    /**
     *出来Echarts图表
     * @return
     */
    private static XWPFDocument writeEcharts(XWPFDocument doc,String echarts,String downLoadPath,int i,String echartOption) throws Exception{
        String datePath = sdf7.format(new Date());
        writeFile(echartOption,echarts + "Phantomjs_echarts/src/main/webapp/js/"+datePath+"/option3.js");
        String JSpath = echarts +"Phantomjs_echarts/src/main/webapp/js/echarts-convert.js";
        String path = downLoadPath + i + ".png";
        // String cmd = "phantomjs " + JSpath + " -options " + echartOption + " -outfile " + path + " -width 1680 -height 500";
        StringBuilder cmd = new StringBuilder();
        cmd.append("phantomjs ").append(JSpath).append(" -infile ").append(echarts).append("Phantomjs_echarts/src/main/webapp/js/").append(datePath).append("/option3.js -outfile ").append(path).append(" -width 550 -height 500");
        log.info("cmd: " + cmd);
        String osName = System.getProperties().getProperty("os.name");
        Process process = null;
        //windows
        if (osName.toLowerCase().startsWith("win")) {
            String[] cmds = {"cmd", "/C", cmd.toString()};
            process = Runtime.getRuntime().exec(cmds);
        } else {
            process = Runtime.getRuntime().exec(cmd.toString());
        }
        log.info("end cmd exec generate png");
        BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream()));
        String line = "";
        while ((line = input.readLine()) != null) {
            log.info(line);
        }
        File file = new File(path);
        FileUtil.delete(echarts + "Phantomjs_echarts/src/main/webapp/js/"+datePath);
        FileInputStream in = new FileInputStream(file);
        BufferedImage image = ImageIO.read(file);
        XWPFParagraph paragraph = doc.createParagraph();
        // 将图片添加到word中
        XWPFRun run = paragraph.createRun();
        run.addPicture(in, org.apache.poi.xwpf.usermodel.Document.PICTURE_TYPE_PNG, path,
                Units.pixelToEMU(image.getWidth()), Units.pixelToEMU(image.getHeight()));
        FileOutputStream fos1 = new FileOutputStream(path);
        doc.write(fos1);
        fos1.close();
        input.close();
        return doc;
    }
    /**
     *
     * options生成文件存储
     */
    private static String writeFile(String options,String dataPath) {
        PrintWriter fileOutputStream = null;
        try {
            /* option写入文本文件 用于执行命令*/
            File writename = new File(dataPath);
            if (!writename.exists()) {
                File dir = new File(writename.getParent());
                dir.mkdirs();
                writename.createNewFile(); //
            }
            fileOutputStream = new PrintWriter(new OutputStreamWriter(new FileOutputStream(writename),"utf-8"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        fileOutputStream.println(options);

        fileOutputStream.close();
        return dataPath;
    }

poi依赖坐标

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

    <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml-schemas –-->
    <dependency>
      <groupId>org.apache.poi</groupId>
      <artifactId>poi-ooxml-schemas</artifactId>
      <version>4.1.0</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-scratchpad –-->
    <dependency>
      <groupId>org.apache.poi</groupId>
      <artifactId>poi-scratchpad</artifactId>
      <version>4.1.0</version>
    </dependency>