package platform.common.util; import org.apache.poi.POIXMLDocument; import org.apache.poi.xwpf.usermodel.*; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.net.URLEncoder; import java.util.*; /** * @author kevin * @since 2019/9/3 4:10 PM */ public class BokeWordUtils { private XWPFDocument document; /** * 构造函数 * @param inputUrl * @param tableList */ public BokeWordUtils (String inputUrl, List tableList){ this(inputUrl, new HashMap<>(), tableList); } public BokeWordUtils (String inputUrl, Map textMap, List tableList){ try { System.out.println("===============开始读取word模版==================="); System.out.println(Thread.currentThread().getName() + "\t 模版路径:" + inputUrl); document = new XWPFDocument(POIXMLDocument.openPackage(inputUrl)); //解析替换文本段落对象 changeText(document, textMap); //解析替换表格对象 changeTable(document, textMap, tableList); System.out.println("生成完成!"); } catch (IOException e) { e.printStackTrace(); } } /** * 根据模板生成新word文档 * 判断表格是需要替换还是需要插入,判断逻辑有$为替换,表格无$为插入 * @param inputUrl 模板存放地址 * @param outputUrl 新文档存放地址 * @param textMap 需要替换的信息集合 * @param tableList 需要插入的表格信息集合 */ public static boolean changWord(String inputUrl, String outputUrl, Map textMap, List tableList) { //模板转换默认成功 boolean changeFlag = true; try { //获取docx解析对象 XWPFDocument document = new XWPFDocument(POIXMLDocument.openPackage(inputUrl)); //解析替换文本段落对象 BokeWordUtils.changeText(document, textMap); //解析替换表格对象 BokeWordUtils.changeTable(document, textMap, tableList); //生成新的word File file = new File(outputUrl); FileOutputStream stream = new FileOutputStream(file); document.write(stream); stream.close(); System.out.println("成功生成!"); } catch (IOException e) { e.printStackTrace(); changeFlag = false; } return changeFlag; } /** * 输出到客户端 * @param fileName 输出文件名 */ public BokeWordUtils write(HttpServletResponse response, String fileName) throws IOException{ response.reset(); response.setContentType("application/octet-stream; charset=utf-8"); response.setHeader("Content-Disposition", "attachment; filename="+ URLEncoder.encode(fileName, "UTF-8")); write(response.getOutputStream()); return this; } /** * 输出数据流 * @param os 输出数据流 */ public BokeWordUtils write(OutputStream os) throws IOException{ document.write(os); return this; } /** * 替换段落文本 * @param document docx解析对象 * @param textMap 需要替换的信息集合 */ public static void changeText(XWPFDocument document, Map textMap){ //获取段落集合 List paragraphs = document.getParagraphs(); for (XWPFParagraph paragraph : paragraphs) { //判断此段落时候需要进行替换 String text = paragraph.getText(); if(checkText(text)){ List runs = paragraph.getRuns(); for (XWPFRun run : runs) { //替换模板原来位置 // run.setText(changeValue(run.toString(), textMap),0); String textValue = changeValue(run.toString(), textMap); run.setText(textValue,0); } } } } /** * 替换表格对象方法 * @param document docx解析对象 * @param textMap 需要替换的信息集合 * @param tableList 需要插入的表格信息集合 */ public static void changeTable(XWPFDocument document, Map textMap, List tableList){ //获取表格对象集合 List tables = document.getTables(); for (int i = 0; i < tables.size(); i++) { //只处理行数大于等于2的表格,且不循环表头 XWPFTable table = tables.get(i); //判断表格是需要替换还是需要插入,判断逻辑有$为替换,表格无$为插入 if(checkText(table.getText())){ List rows = table.getRows(); //遍历表格,并替换模板 eachTable(rows, textMap); }else{ insertTable(table, tableList); } } } /** * 遍历表格 * @param rows 表格行对象 * @param textMap 需要替换的信息集合 */ public static void eachTable(List rows ,Map textMap){ for (XWPFTableRow row : rows) { List cells = row.getTableCells(); for (XWPFTableCell cell : cells) { //判断单元格是否需要替换 if(checkText(cell.getText())){ List paragraphs = cell.getParagraphs(); for (XWPFParagraph paragraph : paragraphs) { List runs = paragraph.getRuns(); for (XWPFRun run : runs) { run.setText(changeValue(run.toString(), textMap),0); } } } } } } /** * 为表格插入数据,行数不够添加新行 * @param table 需要插入数据的表格 * @param tableList 插入数据集合 */ public static void insertTable(XWPFTable table, List tableList){ //创建行,根据需要插入的数据添加新行,不处理表头 for(int i = 0; i < tableList.size(); i++){ XWPFTableRow row =table.createRow(); List cells = row.getTableCells(); for(int j = 0; j < cells.size(); j++){ XWPFTableCell cell = cells.get(j); cell.setText(tableList.get(i)[j]); } } //遍历表格插入数据 // List rows = table.getRows(); // for(int i = 1; i < rows.size(); i++){ // XWPFTableRow newRow = table.getRow(i); // List cells = newRow.getTableCells(); // for(int j = 0; j < cells.size(); j++){ // XWPFTableCell cell = cells.get(j); // cell.setText(tableList.get(i-1)[j]); // } // } } /** * 判断文本中时候包含$ * @param text 文本 * @return 包含返回true,不包含返回false */ public static boolean checkText(String text){ boolean check = false; if(text.indexOf("$")!= -1){ check = true; } return check; } /** * 匹配传入信息集合与模板 * @param value 模板需要替换的区域 * @param textMap 传入信息集合 * @return 模板需要替换区域信息集合对应值 */ public static String changeValue(String value, Map textMap){ Set> textSets = textMap.entrySet(); for (Map.Entry textSet : textSets) { //匹配模板与替换值 格式${key} String key = "${"+textSet.getKey()+"}"; if(value.indexOf(key)!= -1){ // value = textSet.getValue();//全部参数替换 value = value.replace(key, textSet.getValue());//仅替换参数 } } //模板未匹配到区域替换为空 if(checkText(value)){ value = ""; } return value; } public static void main(String[] args) { //模板文件地址 String inputUrl = "/Users/xikaiwen/Downloads/annex6.docx"; //新生产的模板文件 String outputUrl = "/Users/xikaiwen/Downloads/annex6_new.docx"; Map testMap = new HashMap(); testMap.put("name", "小明"); testMap.put("sex", "男"); testMap.put("age", "18"); testMap.put("address", "北京市"); testMap.put("neirong", "好的内容"); testMap.put("xuehao", "88888888"); testMap.put("companyName", "软通"); testMap.put("bigName", "项目大类"); testMap.put("smileName", "项目大类-小类"); testMap.put("phone", "18051103927"); testMap.put("date", DateUtil.getTimeString(new Date())); List tableList = new ArrayList<>(); tableList.add(new String[]{"1","1mm","1开开","1uu", "5", "6", "7", "8", "9"}); tableList.add(new String[]{"2","1mm","1开开","1uu", "5", "6", "7", "8", "9"}); tableList.add(new String[]{"3","1mm","1开开","1uu", "5", "6", "7", "8", "9"}); tableList.add(new String[]{"4","1mm","1开开","1uu", "5", "6", "7", "8", "9"}); tableList.add(new String[]{"5","1mm","1开开","1uu", "5", "6", "7", "8", "9"}); tableList.add(new String[]{"6","1mm","1开开","1uu", "5", "6", "7", "8", "9"}); tableList.add(new String[]{"7","1mm","1开开","1uu", "5", "6", "7", "8", "9"}); // tableList.add(new String[]{"2","2密码","2B","基金C"}); // tableList.add(new String[]{"3","3看看","3B","基看C"}); // tableList.add(new String[]{"4","4累了","4B","4谁说的"}); BokeWordUtils.changWord(inputUrl, outputUrl, testMap, tableList); } }