From 7881d80b355febea6bf1d5d5986a90ef882760e0 Mon Sep 17 00:00:00 2001 From: haomingming Date: Sun, 4 Jan 2026 13:46:45 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AF=BC=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../converter/CustomExcelWriteHandler.java | 151 ++++++++++-------- 1 file changed, 81 insertions(+), 70 deletions(-) diff --git a/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/caseplatformcase/converter/CustomExcelWriteHandler.java b/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/caseplatformcase/converter/CustomExcelWriteHandler.java index 24956e1..de1d58c 100644 --- a/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/caseplatformcase/converter/CustomExcelWriteHandler.java +++ b/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/caseplatformcase/converter/CustomExcelWriteHandler.java @@ -7,7 +7,9 @@ import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.xssf.streaming.SXSSFSheet; +import java.io.IOException; import java.util.List; public class CustomExcelWriteHandler implements WriteHandler { @@ -15,6 +17,9 @@ public class CustomExcelWriteHandler implements WriteHandler { private final double totalTax; private final double totalTotal; private final int dataSize; + private boolean totalRowCreated = false; + // 缓存 Workbook(在 afterSheetCreate 中初始化) + private Workbook workbook; public CustomExcelWriteHandler(double totalActual, double totalTax, double totalTotal, int dataSize) { this.totalActual = totalActual; @@ -24,8 +29,8 @@ public class CustomExcelWriteHandler implements WriteHandler { } public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { - // 工作表创建后,先处理大标题、表头样式、列宽(此时还未写入数据,行未刷盘) - Workbook workbook = writeWorkbookHolder.getWorkbook(); + // 初始化 Workbook 缓存(关键:兼容低版本) + this.workbook = writeWorkbookHolder.getWorkbook(); Sheet sheet = writeSheetHolder.getSheet(); // 1. 处理大标题(第0行) @@ -33,7 +38,6 @@ public class CustomExcelWriteHandler implements WriteHandler { titleRow.setHeightInPoints(30); Cell titleCell = titleRow.createCell(0); titleCell.setCellValue("人工肝诊疗病例征集项目专家劳务费表"); - // 合并大标题单元格(0行0列到0行最后一列) sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 13)); // 大标题样式 CellStyle titleStyle = workbook.createCellStyle(); @@ -60,84 +64,91 @@ public class CustomExcelWriteHandler implements WriteHandler { headRow.setHeightInPoints(25); } - public void afterWorkbookDispose(WriteWorkbookHolder writeWorkbookHolder) { - // 数据写入完成后,处理合计行和数据行高(此时所有数据行已写入,但合计行是新创建的,未刷盘) - Workbook workbook = writeWorkbookHolder.getWorkbook(); - Sheet sheet = workbook.getSheetAt(0); + // 关键:数据行写入完成后创建合计行(兼容低版本) + public void afterRowDispose(WriteSheetHolder writeSheetHolder, Row row, Integer relativeRowIndex, Boolean isHead) throws IOException { + // 仅在最后一行数据写入后创建合计行,且未创建过 + if (!totalRowCreated && relativeRowIndex != null && relativeRowIndex == dataSize - 1) { + Sheet sheet = writeSheetHolder.getSheet(); - // 1. 设置数据行行高(第2行到数据最后一行) - for (int i = 2; i <= dataSize + 1; i++) { // 数据从第2行开始,共dataSize行 - Row row = sheet.getRow(i); - if (row != null) { - row.setHeightInPoints(22); + // 修正合计行索引:0=大标题,1=表头,2~1+dataSize=数据,2+dataSize=合计 + int totalRowIndex = 2 + dataSize; + Row totalRow = sheet.createRow(totalRowIndex); + totalRow.setHeightInPoints(22); + + // 合计行样式(黑底白字) + CellStyle totalStyle = workbook.createCellStyle(); + Font totalFont = workbook.createFont(); + totalFont.setBold(true); + totalFont.setColor(IndexedColors.WHITE.getIndex()); + totalStyle.setFont(totalFont); + totalStyle.setFillForegroundColor(IndexedColors.BLACK.getIndex()); + totalStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); + totalStyle.setAlignment(HorizontalAlignment.CENTER); + totalStyle.setVerticalAlignment(VerticalAlignment.CENTER); + totalStyle.setBorderTop(BorderStyle.THIN); + totalStyle.setBorderBottom(BorderStyle.THIN); + totalStyle.setBorderLeft(BorderStyle.THIN); + totalStyle.setBorderRight(BorderStyle.THIN); + + // 合并前6列写“合计” + sheet.addMergedRegion(new CellRangeAddress(totalRowIndex, totalRowIndex, 0, 5)); + Cell totalCell = totalRow.createCell(0); + totalCell.setCellValue("合计"); + totalCell.setCellStyle(totalStyle); + + // 实发、个税、应发赋值+样式 + Cell actualCell = totalRow.createCell(6); + actualCell.setCellValue(totalActual); + actualCell.setCellStyle(totalStyle); + + Cell taxCell = totalRow.createCell(8); + taxCell.setCellValue(totalTax); + taxCell.setCellStyle(totalStyle); + + Cell totalAmtCell = totalRow.createCell(9); + totalAmtCell.setCellValue(totalTotal); + totalAmtCell.setCellStyle(totalStyle); + + // 其他列补充边框 + CellStyle borderStyle = workbook.createCellStyle(); + borderStyle.setBorderBottom(BorderStyle.THIN); + borderStyle.setBorderTop(BorderStyle.THIN); + borderStyle.setBorderLeft(BorderStyle.THIN); + borderStyle.setBorderRight(BorderStyle.THIN); + borderStyle.setAlignment(HorizontalAlignment.CENTER); + + for (int i = 0; i < 14; i++) { + if (i == 0 || i == 6 || i == 8 || i == 9) { + continue; + } + Cell cell = totalRow.getCell(i); + if (cell == null) { + cell = totalRow.createCell(i); + } + cell.setCellStyle(borderStyle); + } + + // 标记合计行已创建 + totalRowCreated = true; + + // 强制刷新(兼容SXSSF) + if (sheet instanceof SXSSFSheet) { + ((SXSSFSheet) sheet).flushRows(); } } - // 2. 处理合计行 - int totalRowIndex = dataSize + 2; // 合计行在数据行最后一行的下一行 - Row totalRow = sheet.createRow(totalRowIndex); - totalRow.setHeightInPoints(22); - - // 合计行样式(黑底白字) - CellStyle totalStyle = workbook.createCellStyle(); - Font totalFont = workbook.createFont(); - totalFont.setBold(true); - totalFont.setColor(IndexedColors.WHITE.getIndex()); - totalStyle.setFont(totalFont); - totalStyle.setFillForegroundColor(IndexedColors.BLACK.getIndex()); - totalStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); - totalStyle.setAlignment(HorizontalAlignment.CENTER); - totalStyle.setVerticalAlignment(VerticalAlignment.CENTER); - totalStyle.setBorderTop(BorderStyle.THIN); - totalStyle.setBorderBottom(BorderStyle.THIN); - totalStyle.setBorderLeft(BorderStyle.THIN); - totalStyle.setBorderRight(BorderStyle.THIN); - - // 合并前6列(0-5)写“合计” - sheet.addMergedRegion(new CellRangeAddress(totalRowIndex, totalRowIndex, 0, 5)); - Cell totalCell = totalRow.createCell(0); - totalCell.setCellValue("合计"); - totalCell.setCellStyle(totalStyle); - - // 实发(6列)、个税(8列)、应发(9列)设置值和样式 - Cell actualCell = totalRow.createCell(6); - actualCell.setCellValue(totalActual); - actualCell.setCellStyle(totalStyle); - - Cell taxCell = totalRow.createCell(8); - taxCell.setCellValue(totalTax); - taxCell.setCellStyle(totalStyle); - - Cell totalAmtCell = totalRow.createCell(9); - totalAmtCell.setCellValue(totalTotal); - totalAmtCell.setCellStyle(totalStyle); - - // 其他列补充边框样式 - CellStyle borderStyle = workbook.createCellStyle(); - borderStyle.setBorderBottom(BorderStyle.THIN); - borderStyle.setBorderTop(BorderStyle.THIN); - borderStyle.setBorderLeft(BorderStyle.THIN); - borderStyle.setBorderRight(BorderStyle.THIN); - borderStyle.setAlignment(HorizontalAlignment.CENTER); - - for (int i = 0; i < 14; i++) { - if (i == 0 || i == 6 || i == 8 || i == 9) { - continue; // 已设置样式的列跳过 - } - Cell cell = totalRow.getCell(i); - if (cell == null) { - cell = totalRow.createCell(i); - } - cell.setCellStyle(borderStyle); + // 设置数据行行高 + if (row.getRowNum() >= 2 && row.getRowNum() <= 1 + dataSize) { + row.setHeightInPoints(22); } } - // 其他默认方法实现 + // 其他默认方法(无需修改) public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {} public void beforeWorkbookCreate(WriteWorkbookHolder writeWorkbookHolder) {} public void beforeWorkbookDispose(WriteWorkbookHolder writeWorkbookHolder) {} + public void afterWorkbookDispose(WriteWorkbookHolder writeWorkbookHolder) {} public void afterRowCreate(WriteSheetHolder writeSheetHolder, Row row, Integer relativeRowIndex, Boolean isHead) {} - public void afterRowDispose(WriteSheetHolder writeSheetHolder, Row row, Integer relativeRowIndex, Boolean isHead) {} public void beforeRowCreate(WriteSheetHolder writeSheetHolder, Integer rowIndex, Integer relativeRowIndex, Boolean isHead) {} public void beforeRowDispose(WriteSheetHolder writeSheetHolder, Row row, Integer relativeRowIndex, Boolean isHead) {} public void afterCellCreate(WriteSheetHolder writeSheetHolder, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {}