转自csdn:https://blog.csdn.net/qq_33465199/article/details/108149652
首先加入依赖
<dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-scratchpad</artifactId> <version>3.16</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>4.1.2</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>4.1.2</version> </dependency>
代码里面有被注释的main方法,可以参考下,直接传入Map对象的参数就生成
word文件内变量名需要{}来包裹,如下图
map的key直接设置为{}内的变量名就行,会自动去匹配 {变量名} ,下面上代码
package com.sjyf.gym.utils; /** * @Title: WordTemplate2.java * @Package: com.highdata.templateTools * @Description: TODO * @author: Juveniless * @date: 2017年11月27日 下午3:23:13 */ import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; import com.sjyf.gym.ex.BusinessException; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.util.Units; import org.apache.poi.xwpf.usermodel.BodyElementType; import org.apache.poi.xwpf.usermodel.Document; import org.apache.poi.xwpf.usermodel.IBodyElement; import org.apache.poi.xwpf.usermodel.PositionInParagraph; import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.apache.poi.xwpf.usermodel.XWPFParagraph; import org.apache.poi.xwpf.usermodel.XWPFRun; import org.apache.poi.xwpf.usermodel.XWPFTable; import org.apache.poi.xwpf.usermodel.XWPFTableCell; import org.apache.poi.xwpf.usermodel.XWPFTableRow; import org.springframework.beans.factory.annotation.Value; /** * * 对docx文件中的文本及表格中的内容进行替换 --模板仅支持对 {key} 标签的替换 * * @ClassName: WordTemplate * @Description: TODO(!!!使用word2013 docx文件) * @author Juveniless * @date: 2017年11月27日 下午3:25:56 * <br>(1)word模板注意页边距的问题,存在问题:比如页边距默认为3cm,画表格时,仍然可以通过 * 拖拽,把表格边框拖动到看起来就像页边距只有1cm的样子,但是实际上此时页边距还是3cm,生成的 * word报表的页边距还是会按照3cm来生成。解决办法,在word文件里,设置好页边距,如果需要表格 * 两边页边距很窄,需要在word里设置页边距窄一点,而不是直接拖动表格边框来实现。 * */ public class WordUtils { 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 WordUtils(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<Map<String, String>> * @author Juveniless * @date 2017年11月27日 下午3:29:27 * @param dataMap * */ public void replaceDocument(Map<String, Object> dataMap,String uploadPath) { 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) { // 处理表格 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; }*/ int row = -1; int cell = -1; for(int i=0;i<table.getRows().size();i++){ List<XWPFTableCell> tableCells2 = table.getRows().get(i).getTableCells(); for (int j = 0; j < tableCells2.size(); j++) { if (tableCells2.get(j).getText().equals("##{foreachTableRow}##")) { row = i; cell = j; break; } } } System.out.println("row:"+row); System.out.println("cell:"+cell); List<XWPFTableCell> tableCells = table.getRows().get(row).getTableCells();// 获取到模板表格第一行,用来判断表格类型 String tableType = tableCells.get(cell).getText(); String dataSource = tableCells.get(cell+1).getText(); System.out.println("读取到数据源:"+dataSource); if (!dataMap.containsKey(dataSource)) { System.out.println("文档中第" + (curT + 1) + "个表格模板数据源缺失"); } @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,uploadPath); } else if ("##{foreachTableRow}##".equals(tableType)) { // System.out.println("循环生成表格内部的行"); addTableInDocFooter1(table, tableDataList, parametersMap, 2,row,cell,uploadPath); } } else if (tableText.indexOf("{") > -1) { // 没有查找到##{foreach标签,查找到了普通替换数据的{}标签,该表格只需要简单替换 addTableInDocFooter(table, null, parametersMap, 3,uploadPath); } else { // 没有查找到任何标签,该表格是一个静态表格,仅需要复制一个即可。 addTableInDocFooter(table, null, null, 0,uploadPath); } 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,uploadPath); 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,String uploadPath) { 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));// 复制模板行文本和样式到新行 } newCreateTable.removeRow(0);// 移除多出来的第一行 document.createParagraph();// 添加回车换行 replaceTable(newCreateTable, map,uploadPath);//替换标签 } } else if (flag == 2) {// 表格表格内部行循环 System.out.println("list:"+list); System.out.println("parametersMap:"+parametersMap); 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; } System.out.println("rowText:"+rowText); System.out.println("i:"+i); } System.out.println("tagRowsIndex:"+tagRowsIndex); /* 复制模板行和标签行之前的行 */ for (int i = 1; i < tagRowsIndex; i++) { XWPFTableRow newCreateRow = newCreateTable.createRow(); CopyTableRow(newCreateRow, TempTableRows.get(i));// 复制行 replaceTableRow(newCreateRow, parametersMap,uploadPath);// 处理不循环标签的替换 } /* 循环生成模板行 */ 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),uploadPath);// 处理标签替换 } /* 复制模板行和标签行之后的行 */ /* 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,uploadPath); } 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();// 添加回车换行 } } /** * 根据 模板表格 和 数据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 addTableInDocFooter1(XWPFTable templateTable, List<Map<String, Object>> list, Map<String, Object> parametersMap, int flag,int row,int cell,String uploadPath) { 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));// 复制模板行文本和样式到新行 } newCreateTable.removeRow(0);// 移除多出来的第一行 document.createParagraph();// 添加回车换行 replaceTable(newCreateTable, map,uploadPath);//替换标签 } } else if (flag == 2) {// 表格表格内部行循环 System.out.println("list:"+list); System.out.println("parametersMap:"+parametersMap); XWPFTable newCreateTable = document.createTable();// 创建新表格,默认一行一列 List<XWPFTableRow> TempTableRows = templateTable.getRows();// 获取模板表格所有行 int tagRowsIndex = 0;// 标签行indexs for (int i = row, size = TempTableRows.size(); i < size; i++) { String rowText = TempTableRows.get(i).getCell(cell).getText();// 获取到表格行的第一个单元格 if (rowText.indexOf("##{foreachRows}##") > -1) { tagRowsIndex = i; break; } System.out.println("rowText:"+rowText); System.out.println("i:"+i); } System.out.println("tagRowsIndex:"+tagRowsIndex); /* 复制模板行和标签行之前的行 */ for (int i = 0; i < tagRowsIndex; i++) { XWPFTableRow newCreateRow = newCreateTable.createRow(); CopyTableRow(newCreateRow, TempTableRows.get(i));// 复制行 replaceTableRow(newCreateRow, parametersMap,uploadPath);// 处理不循环标签的替换 } if (list!=null) { /* 循环生成模板行 */ 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),uploadPath);// 处理标签替换 } } /* 复制模板行和标签行之后的行 */ for (int i = tagRowsIndex + 2; i < TempTableRows.size(); i++) { XWPFTableRow newCreateRow = newCreateTable.createRow(); CopyTableRow(newCreateRow, TempTableRows.get(i));// 复制行 replaceTableRow(newCreateRow, parametersMap,uploadPath);// 处理不循环标签的替换 } newCreateTable.removeRow(0);// 移除多出来的第一行 newCreateTable.removeRow(row);// 移除标签行 if (cell-1>=0&&list!=null) { List<XWPFTableRow> tableName = newCreateTable.getRows(); for (int i = row; i <= list.size()+1; i++) { //对单元格进行合并的时候,要标志单元格是否为起点,或者是否为继续合并 XWPFTableCell cell0 = tableName.get(i).getCell(0); XWPFTableCell cell1 = tableName.get(i + 1).getCell(0); cell1.setText(cell0.getText()); /* CTVMerge vmerge = CTVMerge.Factory.newInstance(); vmerge.setVal(STMerge.RESTART); cell0.getCTTc().getTcPr().setVMerge(vmerge); cell1.getCTTc().getTcPr().setVMerge(vmerge); CTVMerge vmerge1 = CTVMerge.Factory.newInstance(); vmerge1.setVal(STMerge.CONTINUE); cell0.getCTTc().getTcPr().setVMerge(vmerge1); cell1.getCTTc().getTcPr().setVMerge(vmerge1);*/ //tableName.get(i).getTableCells().get(cell-1).getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.RESTART);//这是起点 } } 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,uploadPath); } 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,String uploadPath) { 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,uploadPath); } 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,String uploadPath) { 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(); System.out.println("beginRunIndex:"+beginRunIndex); System.out.println("endRunIndex:"+endRunIndex); 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); System.out.println("value:"+value); System.out.println("value:"+value.length()); if (value.length()>5&&(value.substring(value.length()-4).equals(".jpg")||value.substring(value.length()-4).equals(".png"))) { try { String [] picValues = value.split(","); System.out.println("picValues:"+picValues); for(int i=0;i<picValues.length;i++){ if (picValues[i]!="") { FileInputStream fis = new FileInputStream(new File(uploadPath+"/upload/"+picValues[i])); if (value.substring(picValues[i].length()-4).equals(".jpg")) { insertNewRun.addPicture(fis, Document.PICTURE_TYPE_JPEG, "", Units.toEMU(120), Units.toEMU(140)); } else { insertNewRun.addPicture(fis, Document.PICTURE_TYPE_PNG, "", Units.toEMU(120), Units.toEMU(140)); } if (fis!=null) { fis.close(); } } } } catch (Exception e) { e.printStackTrace(); } } // else if(key.toString().equals("clientSign")){ // FileInputStream fis; // try { // System.out.println("value:"+value); // fis= new FileInputStream(new File(value)); // try { // insertNewRun.addPicture(fis, Document.PICTURE_TYPE_JPEG, "", Units.toEMU(120), Units.toEMU(140)); // } catch (InvalidFormatException e1) { // // TODO Auto-generated catch block // e1.printStackTrace(); // } catch (IOException e1) { // // TODO Auto-generated catch block // e1.printStackTrace(); // } // // if (fis!=null) { // try { // fis.close(); // } catch (IOException e) { // // TODO Auto-generated catch block // e.printStackTrace(); // } // } // } catch (FileNotFoundException e) { // // TODO Auto-generated catch block // e.printStackTrace(); // } // } else { insertNewRun.setText(value); } 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<>();//需要移除的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()); String value = getValueBykey(key.toString(),parametersMap); if (value.length()>5&&(value.substring(value.length()-4).equals(".jpg")||value.substring(value.length()-4).equals(".png"))) { try { String [] picValues = value.split(","); System.out.println("picValues:"+picValues); for(int i=0;i<picValues.length;i++){ if (picValues[i]!="") { FileInputStream fis = new FileInputStream(new File(uploadPath+"/upload/"+picValues[i])); if (value.substring(picValues[i].length()-4).equals(".jpg")) { insertNewRun.addPicture(fis, Document.PICTURE_TYPE_JPEG, "", Units.toEMU(120), Units.toEMU(140)); } else { insertNewRun.addPicture(fis, Document.PICTURE_TYPE_PNG, "", Units.toEMU(120), Units.toEMU(140)); } if (fis!=null) { fis.close(); } } } } catch (Exception e) { e.printStackTrace(); } }else { insertNewRun.setText(value); } // 设置文本 //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=""; textString=beginRunText.substring(0,beginRunText.indexOf("{"))+getValueBykey(key.toString(),parametersMap); System.out.println(textString); // if(key.toString().equals("clientSign")){ // textString = textString.substring(3, textString.length()); // System.out.println(textString); // } System.out.println(textString); if (textString.length()>5&&(textString.substring(textString.length()-4).equals(".jpg")||textString.substring(textString.length()-4).equals(".png"))) { try { String [] picValues = textString.split(","); System.out.println("picValues:"+picValues); for(int i=0;i<picValues.length;i++){ if (picValues[i]!="") { FileInputStream fis = new FileInputStream(new File(uploadPath+"/upload/"+picValues[i])); if (textString.substring(picValues[i].length()-4).equals(".jpg")) { insertNewRun.addPicture(fis, Document.PICTURE_TYPE_JPEG, "", Units.toEMU(100), Units.toEMU(60)); } else { insertNewRun.addPicture(fis, Document.PICTURE_TYPE_PNG, "", Units.toEMU(120), Units.toEMU(140)); } if (fis!=null) { fis.close(); } } } } catch (Exception e) { e.printStackTrace(); } }else { //替换换行符 if (((String) getValueBykey(key.toString(),parametersMap)).indexOf(" ") > 0) { //设置换行 String[] text = getValueBykey(key.toString(),parametersMap).toString().split(" "); // insertNewRun = xWPFParagraph.insertNewRun(0); for (int f = 0; f < text.length; f++) { if (f == 0) { insertNewRun.setText(text[f].trim()); } else { // insertNewRun.addCarriageReturn();//硬回车 // 换行 insertNewRun.addBreak(); insertNewRun.setText(text[f].trim()); } } } else { insertNewRun.setText((String) getValueBykey(key.toString(),parametersMap)); } } //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); if (textString.length()>5&&(textString.substring(textString.length()-4).equals(".jpg")||textString.substring(textString.length()-4).equals(".png"))) { try { String [] picValues = textString.split(","); System.out.println("picValues:"+picValues); for(int i=0;i<picValues.length;i++){ if (picValues[i]!="") { FileInputStream fis = new FileInputStream(new File(uploadPath+"/upload/"+picValues[i])); if (textString.substring(picValues[i].length()-4).equals(".jpg")) { insertNewRun.addPicture(fis, Document.PICTURE_TYPE_JPEG, "", Units.toEMU(120), Units.toEMU(140)); } else { insertNewRun.addPicture(fis, Document.PICTURE_TYPE_PNG, "", Units.toEMU(120), Units.toEMU(140)); } if (fis!=null) { fis.close(); } } } } catch (Exception e) { e.printStackTrace(); } }else { insertNewRun.setText(textString); } //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,uploadPath); }//if 有标签 } public ByteArrayInputStream base64ToFile(String strBase64){ try { // 解码,然后将字节转换为文件 byte[] bytes = Base64.getDecoder().decode(strBase64); // 将字符串转换为byte数组 return copyByte2File(bytes); } catch (Exception ioe) { ioe.printStackTrace(); return null; } } private ByteArrayInputStream copyByte2File(byte [] bytes){ FileOutputStream out = null; try { //转化为输入流 ByteArrayInputStream in = new ByteArrayInputStream(bytes); // //写出文件 // byte[] buffer = new byte[1024]; // // out = new FileOutputStream(file); // // //写文件 // int len = 0; // while ((len = in.read(buffer)) != -1) { // out.write(buffer, 0, len); // 文件写操作 // } return in; } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ try { if(out != null){ out.close(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return null; } /** * 复制表格行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格式 * * @author Juveniless * @date 2017年11月27日 下午3:41:02 * @param newTableCell * 新创建的的单元格 * @param templateTableCell * 模板单元格 * */ 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格式 * * @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,String uploadPath) { List<XWPFTableCell> tableCells = tableRow.getTableCells(); for (XWPFTableCell xWPFTableCell : tableCells) { List<XWPFParagraph> paragraphs = xWPFTableCell.getParagraphs(); for (XWPFParagraph xwpfParagraph : paragraphs) { replaceParagraph(xwpfParagraph, parametersMap,uploadPath); } } } /** * 根据map替换表格中的{key}标签 * @author Juveniless * @date 2017年12月4日 下午2:47:36 * @param xwpfTable * @param parametersMap * */ public void replaceTable(XWPFTable xwpfTable,Map<String, Object> parametersMap,String uploadPath){ 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,uploadPath); } } } } 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 static void createFile(Long resourceId, Map<String, Object> data) { try { FileInputStream file = ResourceUtil.getFile(resourceId); // 加载模板文件 WordUtils template = new WordUtils(file); Map<String, Object> wordDataMap = new HashMap<String, Object>();// 存储报表全部数据 wordDataMap.put("parametersMap", data); // 替换数据 template.replaceDocument(wordDataMap,"D://uploadFiles"); //生成文件 File outputFile = new File("D://20200529_cf6597f2-23e0-46e1-8ce5-340d243cf3051.docx");//改成你本地文件所在目录 FileOutputStream fos = new FileOutputStream(outputFile); template.getDocument().write(fos); file.close(); fos.close(); } catch (Exception e) { throw new BusinessException("生成文件失败"); } } /*public static void main(String[] args) { try { //模版地址 File demoFile = new File("C:\Users\qian\Desktop\temp.docx"); InputStream in = new FileInputStream(demoFile); WordUtils template = new WordUtils(in); Map<String, Object> wordDataMap = new HashMap<String, Object>();// 存储报表全部数据 Map<String, Object> parametersMap = new HashMap<String, Object>();// 存储报表中不循环的数据 parametersMap.put("beginTime", "2020-08-02"); parametersMap.put("providerName", "测试"); parametersMap.put("idispatchingType", "测试"); parametersMap.put("projectName", "测试项目"); parametersMap.put("projectPlace", "测试地点"); parametersMap.put("projectName", "测试项目"); parametersMap.put("team", "张三,王五"); parametersMap.put("workContent", "工作内容"); parametersMap.put("img", "1597416361020.jpg");//图片名称 wordDataMap.put("parametersMap", parametersMap); System.out.println("wordDataMap:" + wordDataMap); // 替换数据 template.replaceDocument(wordDataMap,"D://uploadFiles"); // 输出word内容文件流,提供下载 //生成文件 File outputFile=new File("D://20200529_cf6597f2-23e0-46e1-8ce5-340d243cf3051.docx");//改成你本地文件所在目录 FileOutputStream fos = new FileOutputStream(outputFile); template.getDocument().write(fos); } catch (Exception e) { e.printStackTrace(); } }*/ }