package com.lf.server.helper; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.poi.xwpf.usermodel.*; import org.openxmlformats.schemas.wordprocessingml.x2006.main.*; import java.io.*; import java.util.List; import java.util.Map; import java.util.Set; /** * Word帮助类 * * @author WWW * @date 2024-03-21 */ public class WordHelper { private final static Log log = LogFactory.getLog(WordHelper.class); /** * 通过word模板生成word的主方法 * https://blog.csdn.net/qq_46112324/article/details/128156675 */ public static void generateWord(String inputFile, String outPutFile, Map textMap, List tableList) { FileInputStream inputStream = null; FileOutputStream outputStream = null; try { inputStream = new FileInputStream(inputFile); outputStream = new FileOutputStream(outPutFile); // 获取docx解析对象 XWPFDocument document = new XWPFDocument(inputStream); // 处理所有文段数据,除了表格 if (null != textMap && textMap.size() > 0) { handleParagraphs(document, textMap); //changeText(document, textMap); } // 解析替换表格对象 if (null != tableList && tableList.size() > 0) { handleTable(document, textMap, tableList); //changeTable(document, textMap, tableList); } // 写入数据 document.write(outputStream); document.close(); } catch (Exception ex) { log.error(ex.getMessage(), ex); } finally { try { if (outputStream != null) { outputStream.close(); } if (inputStream != null) { inputStream.close(); } } catch (Exception e) { log.error(e.getMessage(), e); } } } /** * 替换表格对象方法 * * @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++) { XWPFTable table = tables.get(i); if (table.getRows().size() > 1) { // 判断表格是需要替换还是需要插入,判断逻辑有$为替换,表格无$为插入 if (!checkText(table.getText())) { insertTable(table, tableList); } } } } /** * 替换段落文本 * * @param document docx解析对象 * @param textMap 需要替换的信息集合 */ public static void changeText(XWPFDocument document, Map textMap) { // 获取段落集合 List tables = document.getTables(); for (XWPFTable table : tables) { if (checkText(table.getText())) { List rows = table.getRows(); for (XWPFTableRow row : rows) { List tableCells = row.getTableCells(); for (XWPFTableCell cell : tableCells) { if (checkText(cell.getText())) { List paragraphs = cell.getParagraphs(); for (XWPFParagraph paragraph : paragraphs) { // 判断此段落时候需要进行替换 String text = paragraph.getText(); if (checkText(text)) { List runs = paragraph.getRuns(); for (XWPFRun run : runs) { // 替换模板原来位置 if (checkText(run.toString())) { run.setText(changeValue(paragraph.getText(), textMap), 0); } else { run.setText("", 0); } } } } } } } } } } /** * 判断文本中时候包含$ * * @param text 文本 * @return 包含返回true, 不包含返回false */ public static boolean checkText(String text) { boolean check = false; if (text.contains("$")) { 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 (key.contains(value)) { value = textSet.getValue(); } } return value; } /** * 为表格插入数据,行数不够添加新行 * * @param table 需要插入数据的表格 * @param tableList 插入数据集合 */ public static void insertTable(XWPFTable table, List tableList) { // 记录需要插入的第一行 int start = -1; for (int i = 0; i < table.getRows().size(); i++) { for (int j = 0; j < table.getRows().get(i).getTableCells().size(); j++) { if ("".equals(table.getRows().get(i).getTableCells().get(j).getText())) { start = i; break; } } } // 创建行,根据需要插入的数据添加新行 if (start != -1) { for (int i = 1; i < tableList.size(); i++) { insertRow(table, start, start + i); } } // 遍历表格插入数据 List rows = table.getRows(); for (int i = start; i < rows.size(); i++) { List cells = rows.get(i).getTableCells(); for (int j = 0; j < table.getRow(start).getTableCells().size(); j++) { XWPFTableCell cell = cells.get(j); cell.setText(tableList.get(0)[j]); } tableList.remove(0); } } /** * 为表格插入数据,行数不够添加新行 * * @param table 需要插入数据的表格 * @param copyRowIndex 复制行号 * @param newRowIndex 新行号 */ public static void insertRow(XWPFTable table, int copyRowIndex, int newRowIndex) { // 在表格中指定的位置新增一行 XWPFTableRow targetRow = table.insertNewTableRow(newRowIndex); // 获取需要复制行对象 XWPFTableRow copyRow = table.getRow(copyRowIndex); // 复制行对象 targetRow.getCtRow().setTrPr(copyRow.getCtRow().getTrPr()); //或许需要复制的行的列 List copyCells = copyRow.getTableCells(); // 复制列对象 XWPFTableCell targetCell = null; for (XWPFTableCell copyCell : copyCells) { targetCell = targetRow.addNewTableCell(); targetCell.getCTTc().setTcPr(copyCell.getCTTc().getTcPr()); if (copyCell.getParagraphs() != null && copyCell.getParagraphs().size() > 0) { targetCell.getParagraphs().get(0).getCTP().setPPr(copyCell.getParagraphs().get(0).getCTP().getPPr()); if (copyCell.getParagraphs().get(0).getRuns() != null && copyCell.getParagraphs().get(0).getRuns().size() > 0) { XWPFRun cellR = targetCell.getParagraphs().get(0).createRun(); cellR.setBold(copyCell.getParagraphs().get(0).getRuns().get(0).isBold()); } } } } /** * 处理所有文段数据,除了表格 */ public static void handleParagraphs(XWPFDocument xwpfDocument, Map insertTextMap) { for (XWPFParagraph paragraph : xwpfDocument.getParagraphs()) { String text = paragraph.getText(); if (isReplacement(text)) { for (XWPFRun run : paragraph.getRuns()) { // 判断带有 ${} 的run run.setText(matchesValue(run.text(), insertTextMap), 0); } } } } /** * 处理表格数据方法 */ public static void handleTable(XWPFDocument xwpfDocument, Map map, List addList) { List tables = xwpfDocument.getTables(); for (XWPFTable table : tables) { List rows = table.getRows(); if (rows.size() < 2) { continue; } if (isReplacement(table.getText())) { if (null == map || map.isEmpty()) { continue; } replaceData(rows, map); } else { insertData(table, addList); } } } /** * 替换数据 */ private static void replaceData(List rows, Map map) { for (XWPFTableRow row : rows) { List tableCells = row.getTableCells(); for (XWPFTableCell tableCell : tableCells) { if (isReplacement(tableCell.getText())) { List paragraphs = tableCell.getParagraphs(); for (XWPFParagraph paragraph : paragraphs) { List runs = paragraph.getRuns(); for (XWPFRun run : runs) { run.setText(matchesValue(tableCell.getText(), map), 0); } } } } } } /** * 插入数据 */ private static void insertData(XWPFTable table, List addList) { for (int i = 1, c = addList.size(); i < c; i++) { table.createRow(); } List oldCells = table.getRow(1).getTableCells(); List rowList = table.getRows(); for (int i = 0, c = addList.size(); i < c; i++) { XWPFTableRow xwpfTableRow = rowList.get(i + 1); List tableCells = xwpfTableRow.getTableCells(); for (int j = 0; j < tableCells.size(); j++) { XWPFTableCell oldCell = oldCells.get(j); XWPFTableCell newCell = tableCells.get(j); if (0 == i) { // newCell.setText(addList.get(i)[j]) setCellText(newCell, addList.get(i)[j]); } else { setCellText(oldCell, newCell, addList.get(i)[j]); } } } } /** * 设置单元格文本 */ private static void setCellText(XWPFTableCell cell, String text) { List paragraphs = cell.getParagraphs(); for (XWPFParagraph paragraph : paragraphs) { List runs = paragraph.getRuns(); for (XWPFRun run : runs) { run.setText(text, 0); } } } /** * 有${}的值匹配出替换的数据,没有${}就返回原来的数据 * * @param wordValue ${...} 带${}的变量 * @param map 存储需要替换的数据 * @return java.lang.String */ public static String matchesValue(String wordValue, Map map) { for (String s : map.keySet()) { String s1 = "${" + s + "}"; /*if (s1.equals(wordValue)) { wordValue = map.get(s); }*/ if (wordValue.contains(s1)) { wordValue = wordValue.replace(s1, map.get(s)); } } return wordValue; } /** * 测试是否包含需要替换的数据 */ public static boolean isReplacement(String text) { return text.contains("${"); } /** * 复制模板行的属性 */ private static void setCellText(XWPFTableCell tmpCell, XWPFTableCell cell, String text) { CTTc cttc2 = tmpCell.getCTTc(); CTTcPr ctPr2 = cttc2.getTcPr(); CTTc cttc = cell.getCTTc(); CTTcPr ctPr = cttc.addNewTcPr(); if (ctPr2.getTcW() != null) { ctPr.addNewTcW().setW(ctPr2.getTcW().getW()); } if (ctPr2.getVAlign() != null) { ctPr.addNewVAlign().setVal(ctPr2.getVAlign().getVal()); } if (ctPr2.getTcBorders() != null) { ctPr.setTcBorders(ctPr2.getTcBorders()); } XWPFParagraph tmpP = tmpCell.getParagraphs().get(0); XWPFParagraph cellP = cell.getParagraphs().get(0); XWPFRun tmpR = null; if (tmpP.getRuns() != null && tmpP.getRuns().size() > 0) { tmpR = tmpP.getRuns().get(0); } XWPFRun cellR = cellP.createRun(); cellR.setText(text); // 复制字体信息 copyFontInfo(cellR, tmpR); // 复制段落信息 cellP.setAlignment(tmpP.getAlignment()); cellP.setVerticalAlignment(tmpP.getVerticalAlignment()); cellP.setBorderBetween(tmpP.getBorderBetween()); cellP.setBorderBottom(tmpP.getBorderBottom()); cellP.setBorderLeft(tmpP.getBorderLeft()); cellP.setBorderRight(tmpP.getBorderRight()); cellP.setBorderTop(tmpP.getBorderTop()); cellP.setPageBreak(tmpP.isPageBreak()); if (tmpP.getCTP() != null && tmpP.getCTP().getPPr() != null) { CTPPr tmpPpr = tmpP.getCTP().getPPr(); CTPPr cellPpr = cellP.getCTP().getPPr() != null ? cellP.getCTP().getPPr() : cellP.getCTP().addNewPPr(); // 复制段落间距信息 copySpacing(tmpPpr, cellPpr); // 复制段落缩进信息 copyParagraph(tmpPpr, cellPpr); } } /** * 复制字体信息 */ private static void copyFontInfo(XWPFRun cellR, XWPFRun tmpR) { if (tmpR == null) { return; } if (!cellR.isBold()) { cellR.setBold(tmpR.isBold()); } cellR.setItalic(tmpR.isItalic()); cellR.setUnderline(tmpR.getUnderline()); cellR.setColor(tmpR.getColor()); cellR.setTextPosition(tmpR.getTextPosition()); if (tmpR.getFontSize() != -1) { cellR.setFontSize(tmpR.getFontSize()); } if (tmpR.getFontFamily() != null) { cellR.setFontFamily(tmpR.getFontFamily()); } if (tmpR.getCTR() != null) { if (tmpR.getCTR().isSetRPr()) { CTRPr tmpRpr = tmpR.getCTR().getRPr(); if (tmpRpr.isSetRFonts()) { CTFonts tmpFonts = tmpRpr.getRFonts(); CTRPr cellRpr = cellR.getCTR().isSetRPr() ? cellR.getCTR().getRPr() : cellR.getCTR().addNewRPr(); CTFonts cellFonts = cellRpr.isSetRFonts() ? cellRpr.getRFonts() : cellRpr.addNewRFonts(); cellFonts.setAscii(tmpFonts.getAscii()); cellFonts.setAsciiTheme(tmpFonts.getAsciiTheme()); cellFonts.setCs(tmpFonts.getCs()); cellFonts.setCstheme(tmpFonts.getCstheme()); cellFonts.setEastAsia(tmpFonts.getEastAsia()); cellFonts.setEastAsiaTheme(tmpFonts.getEastAsiaTheme()); cellFonts.setHAnsi(tmpFonts.getHAnsi()); cellFonts.setHAnsiTheme(tmpFonts.getHAnsiTheme()); } } } } /** * 复制段落间距信息 */ private static void copySpacing(CTPPr tmpPpr, CTPPr cellPpr) { CTSpacing tmpSpacing = tmpPpr.getSpacing(); if (tmpSpacing != null) { CTSpacing cellSpacing = cellPpr.getSpacing() != null ? cellPpr.getSpacing() : cellPpr.addNewSpacing(); if (tmpSpacing.getAfter() != null) { cellSpacing.setAfter(tmpSpacing.getAfter()); } if (tmpSpacing.getAfterAutospacing() != null) { cellSpacing.setAfterAutospacing(tmpSpacing.getAfterAutospacing()); } if (tmpSpacing.getAfterLines() != null) { cellSpacing.setAfterLines(tmpSpacing.getAfterLines()); } if (tmpSpacing.getBefore() != null) { cellSpacing.setBefore(tmpSpacing.getBefore()); } if (tmpSpacing.getBeforeAutospacing() != null) { cellSpacing.setBeforeAutospacing(tmpSpacing .getBeforeAutospacing()); } if (tmpSpacing.getBeforeLines() != null) { cellSpacing.setBeforeLines(tmpSpacing.getBeforeLines()); } if (tmpSpacing.getLine() != null) { cellSpacing.setLine(tmpSpacing.getLine()); } if (tmpSpacing.getLineRule() != null) { cellSpacing.setLineRule(tmpSpacing.getLineRule()); } } } /** * 复制段落缩进信息 */ private static void copyParagraph(CTPPr tmpPpr, CTPPr cellPpr) { CTInd tmpInd = tmpPpr.getInd(); if (tmpInd != null) { CTInd cellInd = cellPpr.getInd() != null ? cellPpr.getInd() : cellPpr.addNewInd(); if (tmpInd.getFirstLine() != null) { cellInd.setFirstLine(tmpInd.getFirstLine()); } if (tmpInd.getFirstLineChars() != null) { cellInd.setFirstLineChars(tmpInd.getFirstLineChars()); } if (tmpInd.getHanging() != null) { cellInd.setHanging(tmpInd.getHanging()); } if (tmpInd.getHangingChars() != null) { cellInd.setHangingChars(tmpInd.getHangingChars()); } if (tmpInd.getLeft() != null) { cellInd.setLeft(tmpInd.getLeft()); } if (tmpInd.getLeftChars() != null) { cellInd.setLeftChars(tmpInd.getLeftChars()); } if (tmpInd.getRight() != null) { cellInd.setRight(tmpInd.getRight()); } if (tmpInd.getRightChars() != null) { cellInd.setRightChars(tmpInd.getRightChars()); } } } }