package com.estate.expert.admin.stat.report.render; import com.alibaba.fastjson.JSONObject; import com.deepoove.poi.policy.DynamicTableRenderPolicy; import com.deepoove.poi.util.TableTools; import org.apache.poi.xwpf.usermodel.ParagraphAlignment; import org.apache.poi.xwpf.usermodel.XWPFTable; import org.apache.poi.xwpf.usermodel.XWPFTableCell; import org.apache.poi.xwpf.usermodel.XWPFTableRow; import org.openxmlformats.schemas.wordprocessingml.x2006.main.STBorder; import org.openxmlformats.schemas.wordprocessingml.x2006.main.STTblWidth; import org.openxmlformats.schemas.wordprocessingml.x2006.main.STVerticalJc; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import java.math.BigInteger; import java.util.List; /** * 设备分组表格渲染策略:同一设备类型内合并类型和数量,设备类型变更时重新分组。 */ public class DeviceGroupTablePolicy extends DynamicTableRenderPolicy { private static final int TYPE_COL = 0; private static final int COUNT_COL = 1; private static final int NUMBER_COL = 2; @Override public void render(XWPFTable table, Object data) { var groups = (List) data; int templateRowIndex = findTemplateRowIndex(table); if (templateRowIndex < 0) { return; } table.removeRow(templateRowIndex); if (CollectionUtils.isEmpty(groups)) { return; } int insertIndex = templateRowIndex; int groupStart = templateRowIndex; int groupSize = 0; for (Object item : groups) { if (!(item instanceof JSONObject group)) { continue; } boolean firstRowOfGroup = StringUtils.hasText(group.getString("设备类型")); XWPFTableRow row = table.insertNewTableRow(insertIndex++); renderRow(row, group, firstRowOfGroup); if (firstRowOfGroup) { mergeGroup(table, groupStart, groupSize); groupStart = insertIndex - 1; groupSize = 1; } else { groupSize++; } } mergeGroup(table, groupStart, groupSize); } private int findTemplateRowIndex(XWPFTable table) { for (int i = 0; i < table.getRows().size(); i++) { if (rowText(table.getRow(i)).contains("[设备编号]")) { return i; } } return -1; } private String rowText(XWPFTableRow row) { if (row == null) { return ""; } return row.getTableCells().stream() .map(XWPFTableCell::getText) .reduce("", String::concat); } private void renderRow(XWPFTableRow row, JSONObject group, boolean firstRowOfGroup) { renderCell(row, firstRowOfGroup ? group.getString("设备类型") : "", 2972); renderCell(row, firstRowOfGroup ? group.getString("设备数量") : "", 1531); renderCell(row, group.getString("设备编号"), 4706); } private void renderCell(XWPFTableRow row, String text, int width) { XWPFTableCell cell = row.createCell(); var tcPr = cell.getCTTc().isSetTcPr() ? cell.getCTTc().getTcPr() : cell.getCTTc().addNewTcPr(); tcPr.addNewTcW().setW(BigInteger.valueOf(width)); tcPr.getTcW().setType(STTblWidth.DXA); tcPr.addNewGridSpan().setVal(BigInteger.valueOf(2)); tcPr.addNewVAlign().setVal(STVerticalJc.CENTER); var borders = tcPr.addNewTcBorders(); borders.addNewTop().setVal(STBorder.SINGLE); borders.addNewBottom().setVal(STBorder.SINGLE); borders.addNewLeft().setVal(STBorder.SINGLE); borders.addNewRight().setVal(STBorder.SINGLE); borders.getTop().setColor("000000"); borders.getBottom().setColor("000000"); borders.getLeft().setColor("000000"); borders.getRight().setColor("000000"); borders.getTop().setSz(BigInteger.valueOf(4)); borders.getBottom().setSz(BigInteger.valueOf(4)); borders.getLeft().setSz(BigInteger.valueOf(4)); borders.getRight().setSz(BigInteger.valueOf(4)); var paragraph = cell.getParagraphs().get(0); paragraph.setAlignment(ParagraphAlignment.CENTER); var run = paragraph.createRun(); run.setFontFamily("黑体"); run.setFontSize(12); run.setText(text == null ? "" : text); cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER); } private void mergeGroup(XWPFTable table, int groupStart, int groupSize) { if (groupSize <= 1) { return; } TableTools.mergeCellsVertically(table, TYPE_COL, groupStart, groupStart + groupSize - 1); TableTools.mergeCellsVertically(table, COUNT_COL, groupStart, groupStart + groupSize - 1); } }