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; } /** * 根据模板生成新word文档 * 判断表格是需要替换还是需要插入,判断逻辑有$为替换,表格无$为插入 * author:hzh * description:改为下载 * * @param inputUrl 模板存放地址 * @param response 新文档存放地址 * @param textMap 需要替换的信息集合 * @param tableList 需要插入的表格信息集合 */ public static boolean changWord(String inputUrl, HttpServletResponse response, 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 OutputStream os = response.getOutputStream(); document.write(os); os.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();//全部参数替换 if (value != null && textSet != null && textSet.getValue() != null) { try { value = value.replace(key, textSet.getValue());//仅替换参数 }catch (Exception e){ System.out.println(e.getMessage()); } } } } //模板未匹配到区域替换为空 if (checkText(value)) { value = ""; } return value; } public static void main(String[] args) { //模板文件地址 String inputUrl = "/.docx"; //新生产的模板文件 String outputUrl = "/.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", "18388888888"); 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); } }