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

标题 使用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

图片用XWPFDocument无法实现addPicture,POI自身有bug,会发生已经生成word文档,但office打不开文件,或者图片已经插入word文档,但显示不了,解决方法是自己写一个插入图片的方法,不用addPicture方法,代码如下:

/**
     * insert Picture
     * @param document
     * @param filePath
     * @param inline
     * @param width
     * @param height
     * @throws InvalidFormatException
     * @throws FileNotFoundException
     */
    private static void insertPicture(XWPFDocument document, String filePath,
                              CTInline inline, int width,
                              int height,int format) throws InvalidFormatException, FileNotFoundException {
        document.addPictureData(new FileInputStream(filePath),XWPFDocument.PICTURE_TYPE_PNG);
        int id = document.getAllPictures().size() - 1;
        final int EMU = 9525;
        width *= EMU;
        height *= EMU;
        String blipId = document.addPictureData(new FileInputStream(filePath),format);
        String picXml = getPicXml(blipId, width, height);
        XmlToken xmlToken = null;
        try {
            xmlToken = XmlToken.Factory.parse(picXml);
        } catch (XmlException xe) {
            xe.printStackTrace();
        }
        inline.set(xmlToken);
        inline.setDistT(0);
        inline.setDistB(0);
        inline.setDistL(0);
        inline.setDistR(0);
        CTPositiveSize2D extent = inline.addNewExtent();
        extent.setCx(width);
        extent.setCy(height);
        CTNonVisualDrawingProps docPr = inline.addNewDocPr();
        docPr.setId(id);
        docPr.setName("IMG_" + id);
        docPr.setDescr("IMG_" + id);
    }

    /**
     * get the xml of the picture
     * @param blipId
     * @param width
     * @param height
     * @return
     */
    private static String getPicXml(String blipId, int width, int height) {
        String picXml =
                "" + "" +
                        "   " +
                        "      " +
                        "         " + "             + 0 +
                        "\" name=\"Generated\"/>" + "            " +
                        "         " + "         " +
                        "             + blipId +
                        "\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\"/>" +
                        "            " + "               " +
                        "            " + "         " +
                        "         " + "            " +
                        "               " +
                        "                + width + "\" cy=\"" + height +
                        "\"/>" + "            " +
                        "            " +
                        "               " + "            " +
                        "         " + "      " +
                        "   " + "";
        return picXml;
    }

下面是根据模板生成word文件的具体代码:

/**
     * 根据dataMap对word文件中的标签进行替换; 

* !!!!***需要注意dataMap的数据格式***!!!!

* 对于需要替换的普通标签数据标签(不需要循环)-----必须在dataMap中存储一个key为parametersMap的map, * 来存储这些不需要循环生成的数据,比如:表头信息,日期,制表人等。

* 对于需要循环生成的表格数据------key自定义,value为 --ArrayList<Map<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 (value.endsWith("jpg") || value.endsWith(".png") || value.endsWith(".jpeg")){ int width = Units.toEMU(410); int height = Units.toEMU(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 = value.substring(value.lastIndexOf(".",value.length())); int format = readImageExt(fileExt); //insertNewRun.addPicture(new FileInputStream(value),format,"", Units.toEMU(width),Units.toEMU(height)); // String picId = document.addPictureData(new FileInputStream(value),format); // int id2=document.getAllPackagePictures().size()+1; // // document.createPicture(picId,id2,width,height); //判断图片是否存在 File file = new File(value); if (file.exists()){ CTInline inline = insertNewRun.getCTR().addNewDrawing().addNewInline(); try { insertPicture(document,value,inline,width,height,XWPFDocument.PICTURE_TYPE_JPEG); document.createParagraph();// 添加回车换行 }catch (Exception e){ e.printStackTrace(); } }else { insertNewRun.setText(""); } //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); if (key.indexOf("**foreachimage**")>-1){ List<Map<String,String>> list = (List<Map<String, String>>) parametersMap.get("**foreachimage**"); for (Map<String,String> map:list){ String name = map.get("imageName"); insertNewRun.setText(name); insertNewRun.addBreak(); String image = map.get("image"); int width = Units.toEMU(410); int height = Units.toEMU(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 { //document.createParagraph();// 添加回车换行 String fileExt = textString.substring(textString.lastIndexOf(".",textString.length())); //得到图片格式 int format = readImageExt(fileExt); File file = new File(textString); if (file.exists()) { // String picId = document.addPictureData(new FileInputStream(textString),format); // int id2=document.getAllPackagePictures().size()+1; // // document.createPicture(picId,id2,width,height); CTInline inline = insertNewRun.getCTR().addNewDrawing().addNewInline(); insertPicture(document,textString,inline,width,height,format); }else { insertNewRun.setText(""); } /* insertNewRun.addPicture(new FileInputStream(textString),format,"", Units.toEMU(width),Units.toEMU(height));*/ insertNewRun.addBreak(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }else // 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(textString.endsWith(".png") || textString.endsWith(".jpg") || textString.endsWith(".jpeg")) { int width = Units.toEMU(410); int height = Units.toEMU(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())); //判断图片格式 int format = readImageExt(fileExt); File file = new File(textString); if (file.exists()){ CTInline inline = insertNewRun.getCTR().addNewDrawing().addNewInline(); try { insertPicture(document,textString,inline,width,height,XWPFDocument.PICTURE_TYPE_JPEG); document.createParagraph();// 添加回车换行 }catch (Exception e){ e.printStackTrace(); } document.createParagraph();// 添加回车换行 }else { insertNewRun.setText(""); } //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); } } } } 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; } /** * @description: 判断图片的后缀,得到图片该用哪种格式 * @params: * @return: * @author: fanwj * @Date: 2020/1/14 9:33 */ public int readImageExt(String fileExt) { int format = XWPFDocument.PICTURE_TYPE_PNG; if(fileExt.endsWith(".emf")){ format = XWPFDocument.PICTURE_TYPE_EMF; } else if(fileExt.endsWith(".wmf")){ format = XWPFDocument.PICTURE_TYPE_WMF; } else if(fileExt.endsWith(".pict")) { format = XWPFDocument.PICTURE_TYPE_PICT; } else if(fileExt.endsWith(".jpeg") || fileExt.endsWith(".jpg")) { format = XWPFDocument.PICTURE_TYPE_JPEG; } else if(fileExt.endsWith(".png")) { format = XWPFDocument.PICTURE_TYPE_PNG; } else if(fileExt.endsWith(".dib")) { format = XWPFDocument.PICTURE_TYPE_DIB; } else if(fileExt.endsWith(".gif")) { format = XWPFDocument.PICTURE_TYPE_GIF; } else if(fileExt.endsWith(".tiff")) { format = XWPFDocument.PICTURE_TYPE_TIFF; } else if(fileExt.endsWith(".eps")) { format = XWPFDocument.PICTURE_TYPE_EPS; } else if(fileExt.endsWith(".bmp")) { format = XWPFDocument.PICTURE_TYPE_BMP; } else if(fileExt.endsWith(".wpg")) { format = XWPFDocument.PICTURE_TYPE_WPG; } return format; }

三、自己制作的word模板
Java 使用poi,根据word模板导出word文件_第1张图片

  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.普通的替换文本,在模板中直接加{}

表格整体循环
Java 使用poi,根据word模板导出word文件_第2张图片
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", "[email protected]");
        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", "[email protected]");
        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", "[email protected]");
        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);
    }

你可能感兴趣的:(Java)