package com.ots.common.utils.poi.consultation; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.xwpf.usermodel.IBodyElement; 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.apache.xmlbeans.XmlCursor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.Assert; import org.springframework.util.ResourceUtils; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.InputStream; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; public class DynWordUtils { private final Logger logger = LoggerFactory.getLogger(DynWordUtils.class); private XWPFParagraph oldParagraph; private Map paramMap; int n = 0; boolean isTable = false; XWPFDocument templateDoc; final int DEFAULT_FONT_SIZE = 10; private int currentRowIndex; public static void process(Map paramMap, String templatePaht, String outPath) { DynWordUtils dynWordUtils = new DynWordUtils(); dynWordUtils.setParamMap(paramMap); dynWordUtils.createWord(templatePaht, outPath); } public void createWord(String templatePath, String outPath) { try (FileOutputStream outStream = new FileOutputStream(outPath)) { InputStream inputStream = new FileInputStream(ResourceUtils.getFile(templatePath)); templateDoc = new XWPFDocument(OPCPackage.open(inputStream)); parseTemplateWord(); templateDoc.write(outStream); } catch (Exception e) { StackTraceElement[] stackTrace = e.getStackTrace(); String className = stackTrace[0].getClassName(); String methodName = stackTrace[0].getMethodName(); int lineNumber = stackTrace[0].getLineNumber(); logger.error("错误:第:{}行, 类名:{}, 方法名:{}", lineNumber, className, methodName); throw new RuntimeException(e.getCause().getMessage()); } } public void parseTemplateWord() throws Exception { List elements = templateDoc.getBodyElements(); for (; n < elements.size(); n++) { IBodyElement element = elements.get(n); if (element instanceof XWPFParagraph) { XWPFParagraph paragraph = (XWPFParagraph) element; oldParagraph = paragraph; if (paragraph.getParagraphText().isEmpty()) { continue; } delParagraph(paragraph); } else if (element instanceof XWPFTable) { isTable = true; XWPFTable table = (XWPFTable) element; delTable(table, paramMap); isTable = false; } } } private void delParagraph(XWPFParagraph paragraph) throws Exception { List runs = oldParagraph.getRuns(); StringBuilder sb = new StringBuilder(); for (XWPFRun run : runs) { String text = run.getText(0); if (text == null) { continue; } sb.append(text); run.setText("", 0); } Placeholder(paragraph, runs, sb); } public void changeValue(XWPFRun currRun, String placeholder, Map paramMap) throws Exception { String placeholderValue = placeholder; if (paramMap == null || paramMap.isEmpty()) { return; } Set> textSets = paramMap.entrySet(); for (Map.Entry textSet : textSets) { String mapKey = textSet.getKey(); String docKey = PoiWordUtils.getDocKey(mapKey); if (placeholderValue.indexOf(docKey) != -1) { Object obj = textSet.getValue(); if (obj instanceof List) { placeholderValue = delDynList(placeholder, (List) obj); } else { placeholderValue = placeholderValue.replaceAll( PoiWordUtils.getPlaceholderReg(mapKey) , String.valueOf(obj)); } } } currRun.setText(placeholderValue, 0); } private String delDynList(String placeholder, List obj) { String placeholderValue = placeholder; List dataList = obj; Collections.reverse(dataList); for (int i = 0, size = dataList.size(); i < size; i++) { Object text = dataList.get(i); if (i == 0) { placeholderValue = String.valueOf(text); } else { XWPFParagraph paragraph = createParagraph(String.valueOf(text)); if (paragraph != null) { oldParagraph = paragraph; } if (!isTable) { n--; } } } return placeholderValue; } public XWPFParagraph createParagraph(String... texts) { XmlCursor cursor = oldParagraph.getCTP().newCursor(); XWPFParagraph newPar = templateDoc.insertNewParagraph(cursor); newPar.getCTP().setPPr(oldParagraph.getCTP().getPPr()); copyParagraph(oldParagraph, newPar, texts); return newPar; } public void delTable(XWPFTable table, Map paramMap) throws Exception { List rows = table.getRows(); for (int i = 0, size = rows.size(); i < size; i++) { XWPFTableRow row = rows.get(i); currentRowIndex = i; if (delAndJudgeRow(table, paramMap, row)) { return; } } } private boolean delAndJudgeRow(XWPFTable table, Map paramMap, XWPFTableRow row) throws Exception { if (PoiWordUtils.isAddRow(row)) { List xwpfTableRows = addAndGetRows(table, row, paramMap); for (XWPFTableRow tbRow : xwpfTableRows) { delAndJudgeRow(table, paramMap, tbRow); } return true; } if (PoiWordUtils.isAddRowRepeat(row)) { List xwpfTableRows = addAndGetRepeatRows(table, row, paramMap); /* for (XWPFTableRow tbRow : xwpfTableRows) { delAndJudgeRow(table, paramMap, tbRow); }*/ return true; } List cells = row.getTableCells(); for (XWPFTableCell cell : cells) { if (PoiWordUtils.checkText(cell.getText())) { List paragraphs = cell.getParagraphs(); for (XWPFParagraph paragraph : paragraphs) { List runs = paragraph.getRuns(); StringBuilder sb = new StringBuilder(); for (XWPFRun run : runs) { sb.append(run.toString()); run.setText("", 0); } Placeholder(paragraph, runs, sb); } } } return false; } private void Placeholder(XWPFParagraph currentPar, List runs, StringBuilder sb) throws Exception { if (runs.size() > 0) { String text = sb.toString(); XWPFRun currRun = runs.get(0); if (PoiWordUtils.isPicture(text)) { ImageEntity imageEntity = (ImageEntity) PoiWordUtils.getValueByPlaceholder(paramMap, text); int indentationFirstLine = currentPar.getIndentationFirstLine(); currentPar.getCTP().setPPr(null); currentPar.setIndentationFirstLine(indentationFirstLine); addPicture(currRun, imageEntity); } else { changeValue(currRun, text, paramMap); } } } private void addPicture(XWPFRun currRun, ImageEntity imageEntity) throws InvalidFormatException, FileNotFoundException { Integer typeId = imageEntity.getTypeId().getTypeId(); String picId = currRun.getDocument().addPictureData(new FileInputStream(imageEntity.getUrl()), typeId); ImageUtils.createPicture(currRun, picId, templateDoc.getNextPicNameNumber(typeId), imageEntity.getWidth(), imageEntity.getHeight()); } private List addAndGetRows(XWPFTable table, XWPFTableRow flagRow, Map paramMap) throws Exception { List flagRowCells = flagRow.getTableCells(); XWPFTableCell flagCell = flagRowCells.get(0); String text = flagCell.getText(); List> dataList = (List>) PoiWordUtils.getValueByPlaceholder(paramMap, text); List newRows = new ArrayList<>(dataList.size()); if (dataList == null || dataList.size() <= 0) { return newRows; } XWPFTableRow currentRow = flagRow; int cellSize = flagRow.getTableCells().size(); for (int i = 0, size = dataList.size(); i < size; i++) { if (i != 0) { currentRow = table.createRow(); if (flagRow.getCtRow() != null) { currentRow.getCtRow().setTrPr(flagRow.getCtRow().getTrPr()); } } addRow(flagCell, currentRow, cellSize, dataList.get(i)); newRows.add(currentRow); } return newRows; } private List addAndGetRepeatRows(XWPFTable table, XWPFTableRow flagRow, Map paramMap) throws Exception { List flagRowCells = flagRow.getTableCells(); XWPFTableCell flagCell = flagRowCells.get(0); String text = flagCell.getText(); List> dataList = (List>) PoiWordUtils.getValueByPlaceholder(paramMap, text); String tbRepeatMatrix = PoiWordUtils.getTbRepeatMatrix(text); Assert.notNull(tbRepeatMatrix, "模板矩阵不能为空"); List newRows = new ArrayList<>(dataList.size()); if (dataList == null || dataList.size() <= 0) { return newRows; } String[] split = tbRepeatMatrix.split(PoiWordUtils.tbRepeatMatrixSeparator); int startRow = Integer.parseInt(split[0]); int endRow = Integer.parseInt(split[1]); int startCell = Integer.parseInt(split[2]); int endCell = Integer.parseInt(split[3]); XWPFTableRow currentRow; for (int i = 0, size = dataList.size(); i < size; i++) { int flagRowIndex = i % (endRow - startRow + 1); XWPFTableRow repeatFlagRow = table.getRow(flagRowIndex); if (i == 0) { table.removeRow(currentRowIndex); } currentRow = table.createRow(); if (repeatFlagRow.getCtRow() != null) { currentRow.getCtRow().setTrPr(repeatFlagRow.getCtRow().getTrPr()); } addRowRepeat(startCell, endCell, currentRow, repeatFlagRow, dataList.get(i)); delAndJudgeRow(table, paramMap, currentRow); newRows.add(currentRow); } deleteTemplateRow(startRow, endRow, table); return newRows; } private void deleteTemplateRow(int startRowIdx, int endRowIdx, XWPFTable table) { for (;startRowIdx <= endRowIdx; startRowIdx++) { table.removeRow(0); } } private void addRow(XWPFTableCell flagCell, XWPFTableRow row, int cellSize, List rowDataList) { for (int i = 0; i < cellSize; i++) { XWPFTableCell cell = row.getCell(i); cell = cell == null ? row.createCell() : row.getCell(i); if (i < rowDataList.size()) { PoiWordUtils.copyCellAndSetValue(flagCell, cell, rowDataList.get(i)); } else { PoiWordUtils.copyCellAndSetValue(flagCell, cell, ""); } } } private void addRowRepeat(int startCell, int endCell, XWPFTableRow currentRow, XWPFTableRow repeatFlagRow, List rowDataList) { int cellSize = repeatFlagRow.getTableCells().size(); for (int i = 0; i < cellSize; i++) { XWPFTableCell cell = currentRow.getCell(i); cell = cell == null ? currentRow.createCell() : currentRow.getCell(i); int flagCellIndex = i % (endCell - startCell + 1); XWPFTableCell repeatFlagCell = repeatFlagRow.getCell(flagCellIndex); if (i < rowDataList.size()) { PoiWordUtils.copyCellAndSetValue(repeatFlagCell, cell, rowDataList.get(i)); } else { PoiWordUtils.copyCellAndSetValue(repeatFlagCell, cell, ""); } } } private void copyParagraph(XWPFParagraph sourcePar, XWPFParagraph targetPar, String... texts) { targetPar.setAlignment(sourcePar.getAlignment()); targetPar.setVerticalAlignment(sourcePar.getVerticalAlignment()); targetPar.setAlignment(sourcePar.getAlignment()); targetPar.setVerticalAlignment(sourcePar.getVerticalAlignment()); if (texts != null && texts.length > 0) { String[] arr = texts; XWPFRun xwpfRun = sourcePar.getRuns().size() > 0 ? sourcePar.getRuns().get(0) : null; for (int i = 0, len = texts.length; i < len; i++) { String text = arr[i]; XWPFRun run = targetPar.createRun(); run.setText(text); run.setFontFamily(xwpfRun.getFontFamily()); int fontSize = xwpfRun.getFontSize(); run.setFontSize((fontSize == -1) ? DEFAULT_FONT_SIZE : fontSize); run.setBold(xwpfRun.isBold()); run.setItalic(xwpfRun.isItalic()); } } } public void setParamMap(Map paramMap) { this.paramMap = paramMap; } }