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<String, Object> paramMap;
|
|
int n = 0;
|
|
boolean isTable = false;
|
|
XWPFDocument templateDoc;
|
|
final int DEFAULT_FONT_SIZE = 10;
|
|
private int currentRowIndex;
|
|
public static void process(Map<String, Object> 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<IBodyElement> 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<XWPFRun> 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<String, Object> paramMap) throws Exception {
|
String placeholderValue = placeholder;
|
if (paramMap == null || paramMap.isEmpty()) {
|
return;
|
}
|
Set<Map.Entry<String, Object>> textSets = paramMap.entrySet();
|
for (Map.Entry<String, Object> 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<String, Object> paramMap) throws Exception {
|
List<XWPFTableRow> 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<String, Object> paramMap, XWPFTableRow row) throws Exception {
|
|
if (PoiWordUtils.isAddRow(row)) {
|
List<XWPFTableRow> xwpfTableRows = addAndGetRows(table, row, paramMap);
|
|
for (XWPFTableRow tbRow : xwpfTableRows) {
|
delAndJudgeRow(table, paramMap, tbRow);
|
}
|
return true;
|
}
|
|
if (PoiWordUtils.isAddRowRepeat(row)) {
|
List<XWPFTableRow> xwpfTableRows = addAndGetRepeatRows(table, row, paramMap);
|
/*
|
for (XWPFTableRow tbRow : xwpfTableRows) {
|
delAndJudgeRow(table, paramMap, tbRow);
|
}*/
|
return true;
|
}
|
|
List<XWPFTableCell> cells = row.getTableCells();
|
for (XWPFTableCell cell : cells) {
|
|
if (PoiWordUtils.checkText(cell.getText())) {
|
List<XWPFParagraph> paragraphs = cell.getParagraphs();
|
for (XWPFParagraph paragraph : paragraphs) {
|
List<XWPFRun> 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<XWPFRun> 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<XWPFTableRow> addAndGetRows(XWPFTable table, XWPFTableRow flagRow, Map<String, Object> paramMap) throws Exception {
|
List<XWPFTableCell> flagRowCells = flagRow.getTableCells();
|
XWPFTableCell flagCell = flagRowCells.get(0);
|
String text = flagCell.getText();
|
List<List<String>> dataList = (List<List<String>>) PoiWordUtils.getValueByPlaceholder(paramMap, text);
|
|
List<XWPFTableRow> 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<XWPFTableRow> addAndGetRepeatRows(XWPFTable table, XWPFTableRow flagRow, Map<String, Object> paramMap) throws Exception {
|
List<XWPFTableCell> flagRowCells = flagRow.getTableCells();
|
XWPFTableCell flagCell = flagRowCells.get(0);
|
String text = flagCell.getText();
|
List<List<String>> dataList = (List<List<String>>) PoiWordUtils.getValueByPlaceholder(paramMap, text);
|
String tbRepeatMatrix = PoiWordUtils.getTbRepeatMatrix(text);
|
Assert.notNull(tbRepeatMatrix, "模板矩阵不能为空");
|
|
List<XWPFTableRow> 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<String> 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<String> 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<String, Object> paramMap) {
|
this.paramMap = paramMap;
|
}
|
}
|