
1 public class WordTest2 { 2 public static void main(String[] args) { 3 4 /** 此Map存放动态替换的内容,key-Word中定义的变量,value-要替换的内容 **/ 5 Map map = Maps.newHashMap(); 6 map.put("CL_XT_zlContractNo", "55555556444444888544"); 7 map.put("LOAN_memberName", "小赵"); 8 map.put("LOAN_certNo", "1234568524545"); 9 map.put("LOAN_address", "重庆市沙坪坝积极"); 10 map.put("LOAN_mobileNo", "110110110"); 11 map.put("LOAN_memberName", "张三"); 12 map.put("LOAN_certNo", "510254545488445"); 13 map.put("LOAN_address", "四川省锦州达到"); 14 map.put("LOAN_mobileNo", "023-5854555"); 15 map.put("GUARANTEE_guaPersonName", "李四"); 16 17 /** 此Map存放动态 批量生产Word中表格的内容 **/ 18 List<String[]> tableDataList = new ArrayList<String[]>(); 19 tableDataList.add(new String[] { "应还款日", "应还本金", "应付利息", "应还(付)总额" }); 20 tableDataList.add(new String[] { "2018-01-01", "23", "0.2", "111" }); 21 tableDataList.add(new String[] { "2018-01-02", "233", "0.2", "123" }); 22 tableDataList.add(new String[] { "2018-01-03", "2333", "0.2", "321" }); 23 tableDataList.add(new String[] { "2018-01-04", "2333", "0.2", "321" }); 24 tableDataList.add(new String[] { "2018-01-05", "2333", "0.2", "321" }); 25 tableDataList.add(new String[] { "2018-01-06", "2333", "0.2", "321" }); 26 tableDataList.add(new String[] { "2018-01-07", "2333", "0.2", "321" }); 27 28 String localTemplateTmpPath = "E:\new\TestWord.docx"; 29 String newContractLocalPath = "E:\new\TestWord2.docx"; 30 31 WordUtil.changWord(localTemplateTmpPath, newContractLocalPath, map, tableDataList); 32 33 } 34 }
核心代码:
public class WordUtil { /** * 根据模板生成新word文档 * 判断表格是需要替换还是需要插入,判断逻辑有$为替换,表格无$为插入 * * @param inputUrl 模板存放地址 * @param outputUrl 新文档存放地址 * @param textMap 需要替换的信息集合 * @param tableList 需要插入的表格信息集合 * @return 成功返回true, 失败返回false */ public static boolean changWord(String inputUrl, String outputUrl, Map<String, String> textMap, List<String[]> tableList) { // 模板转换默认成功 boolean changeFlag = true; try { // 获取docx解析对象 XWPFDocument document = new XWPFDocument(POIXMLDocument.openPackage(inputUrl)); // 解析替换文本段落对象 WordUtil.changeText(document, textMap); // 解析替换表格对象 WordUtil.changeTable2(document, textMap, tableList); // 生成新的word File file = new File(outputUrl); FileOutputStream stream = new FileOutputStream(file); document.write(stream); stream.close(); } catch (Exception e) { e.printStackTrace(); changeFlag = false; } return changeFlag; } /** * 替换段落文本 * * @param document docx解析对象 * @param textMap 需要替换的信息集合 */ public static void changeText(XWPFDocument document, Map<String, String> textMap) { // 获取段落集合 List<XWPFParagraph> paragraphs = document.getParagraphs(); Set<String> keySet = textMap.keySet(); changeParagraph(textMap, paragraphs, keySet); // 获取表格对象集合 List<XWPFTable> tables = document.getTables(); for (XWPFTable table : tables) { List<XWPFParagraph> paras; int rcount = table.getNumberOfRows(); for (int j = 0; j < rcount; j++) { XWPFTableRow row = table.getRow(j); List<XWPFTableCell> cells = row.getTableCells(); for (XWPFTableCell cell : cells) { paras = cell.getParagraphs(); changeParagraph(textMap, paras, keySet); } } } } private static void changeParagraph(Map<String, String> textMap, List<XWPFParagraph> paragraphs, Set<String> keySet) { reBuildParagraph2(textMap, paragraphs, keySet); } private static void reBuildParagraph2(Map<String, String> textMap, List<XWPFParagraph> paragraphs, Set<String> keySet) { for (XWPFParagraph paragraph : paragraphs) { /** * 此处For循环的思路: * 将原来的XWPFParagraph中的多个XWPFRun转化成一个XWPFRun,如此做的好处是不会改变原Word的格式 * 如果直接通过XWPFParagraph获取文本内容,再进行赋值,会改变原有的Word的格式 */ String paragraphText = paragraph.getText(); for (String key : keySet) { String regex = "\$\{" + key + "\}"; Pattern pattern = Pattern.compile(regex); Matcher matcher = pattern.matcher(paragraphText); while (matcher.find()) { List<XWPFRun> runs = paragraph.getRuns(); StringBuffer sb = new StringBuffer(""); for (XWPFRun run : runs) { int testPosition = run.getTextPosition(); String text = run.getText(testPosition); if (StringUtils.isNotBlank(text)) { sb.append(text); } } String newText = sb.toString(); int runLength = runs.size(); for (int i = runLength - 1; i >= 0; i--) { if (i == 0) { runs.get(i).setText(newText, 0); } else { paragraph.removeRun(i); if (runLength > 1) { runLength = runLength - 1; } } } } } /** * 此处的思路: * 转换后的XWPFParagraph只会存在一个XWPFRun,并保留了原Word的格式 * 将XWPFRun按照正则进行截取成多个XWPFRun;(具体实现是,将原有的XWPFRun拆分成多个,删除原有的XWPFRun,再将拆分后的XWPFRun创建到原XWPFParagraph) * 如此做的目的是:对Word中定义的变量(例如:${abc})进行格式操作,比如添加下划线 */ List<XWPFRun> runs = paragraph.getRuns(); List<String> list = Lists.newArrayList(); if (runs.size() > 0) { XWPFRun run = runs.get(0); int testPosition = run.getTextPosition(); String text = run.getText(testPosition); String regex2 = "\$\{\w*\}"; String[] strs = text.split(regex2); String totalStr = ""; if (strs.length == 1) { if (text.contains("${")) { list.add(strs[0]); String regexStr = text.substring(strs[0].length()); list.add(regexStr); paragraph.removeRun(0); } } else { if (strs.length > 1) { for (int i = 0; i < strs.length; i++) { String splitStr = strs[i]; totalStr = totalStr + splitStr; String regexStr = ""; list.add(strs[i]); if (i + 1 < strs.length) { regexStr = text.substring(totalStr.length(), text.indexOf(strs[i + 1], totalStr.length())); } list.add(regexStr); totalStr = totalStr + regexStr; } paragraph.removeRun(0); } } for (int i = 0; i < list.size(); i++) { XWPFRun newRun = paragraph.createRun(); newRun.setText(list.get(i)); } /** * 此处的思路: * 获取转换后的XWPFParagraph上的多个XWPFRun * 将XWPFRun按照正则进行文本内容替换(动态替换) */ List<XWPFRun> newRuns = paragraph.getRuns(); for (XWPFRun newRun : newRuns) { int position = newRun.getTextPosition(); String newText = newRun.getText(position); for (String key : keySet) { String regex = "\$\{" + key + "\}"; Pattern pattern = Pattern.compile(regex); if (null != pattern && StringUtil.isNotBlank(newText)) { Matcher matcher = pattern.matcher(newText); while (matcher.find()) { String replaceText = newText.replaceAll(regex, textMap.get(key)); replaceText = " " + replaceText + " "; newRun.setText(replaceText, 0); newRun.setUnderline(UnderlinePatterns.SINGLE); } } } } } } } /** * 替换表格对象方法 * * @param document docx解析对象 * @param textMap 需要替换的信息集合 * @param tableList 需要插入的表格信息集合 */ public static void changeTable2(XWPFDocument document, Map<String, String> textMap, List<String[]> tableList) { // 获取表格对象集合 List<XWPFTable> tables = document.getTables(); for (int i = 0; i < tables.size(); i++) { // 只处理行数大于等于2的表格,且不循环表头 XWPFTable table = tables.get(i); // 表头 String[] tableHeads = tableList.get(0); String tableHead = ""; for (int a = 0; a < tableHeads.length; a++) { tableHead = tableHead + tableHeads[a]; } String templateTableHead = table.getText().replaceAll(" ", "").replaceAll(" ", ""); System.out.println(templateTableHead.contains(tableHead)); if (templateTableHead.contains(tableHead)) { // 创建20行7列 int rows = tableList.size(); int cols = tableList.get(0).length; for (int l = 1; l < rows; l++) { XWPFTableRow targetRow = table.insertNewTableRow(l + 1); targetRow.getCtRow().setTrPr(table.getRow(l).getCtRow().getTrPr()); List<XWPFTableCell> cellList = table.getRow(l).getTableCells(); XWPFTableCell targetCell = null; for (XWPFTableCell sourceCell : cellList) { targetCell = targetRow.addNewTableCell(); targetCell.getCTTc().setTcPr(sourceCell.getCTTc().getTcPr()); targetCell.getParagraphs().get(0).getCTP().setPPr(sourceCell.getParagraphs().get(0).getCTP().getPPr()); } XWPFTableRow row = table.getRow(l); for (int j = 0; j < cols; j++) { // 设置单元格内容 row.getCell(j).setText(tableList.get(l)[j]); } } } } } }