From 64506eaa6977059a8b2c3e43d138342b696c5a72 Mon Sep 17 00:00:00 2001 From: haomingming Date: Sun, 4 Jan 2026 12:18:35 +0800 Subject: [PATCH 1/9] =?UTF-8?q?=E5=AF=BC=E5=87=BA=E5=A4=A7=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CaseplatformCaseExcelController.java | 60 +++++++++++++++---- 1 file changed, 48 insertions(+), 12 deletions(-) diff --git a/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/caseplatformcase/controller/CaseplatformCaseExcelController.java b/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/caseplatformcase/controller/CaseplatformCaseExcelController.java index f73f1b5..8f4c0f7 100644 --- a/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/caseplatformcase/controller/CaseplatformCaseExcelController.java +++ b/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/caseplatformcase/controller/CaseplatformCaseExcelController.java @@ -146,29 +146,65 @@ public class CaseplatformCaseExcelController { contentStyle.setBorderRight(BorderStyle.THIN); // ExcelWriter writer = EasyExcel.write(outputStream, ExportExpertCaseExcelVo.class) +// ExcelWriter writer = EasyExcel.write(response.getOutputStream(), ExportExpertCaseExcelVo.class) +// .head(head) +// .excelType(ExcelTypeEnum.XLSX) +// .registerWriteHandler(new HorizontalCellStyleStrategy(headStyle, contentStyle)) +// .build(); +// +// WriteSheet writeSheet = EasyExcel.writerSheet("劳务费明细") +// .needHead(true) +// .relativeHeadRowIndex(1) // 数据从第3行开始,前2行为标题 +// .build(); +// +// // 写数据 +// writer.write(processedList, writeSheet); +// +// // 合并大标题 +// Workbook workbook = (Workbook) writer.writeContext().writeWorkbookHolder().getWorkbook(); +// Sheet sheet = workbook.getSheetAt(0); +// sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, head.size() - 1)); +// //Row titleRow = sheet.createRow(0); +// Row titleRow = sheet.getRow(0); +// if (titleRow == null) { +// titleRow = sheet.createRow(0); +// } + + // 1. 构建ExcelWriter(先不写入数据,先处理大标题行) ExcelWriter writer = EasyExcel.write(response.getOutputStream(), ExportExpertCaseExcelVo.class) .head(head) .excelType(ExcelTypeEnum.XLSX) .registerWriteHandler(new HorizontalCellStyleStrategy(headStyle, contentStyle)) + // 关键:禁用EasyExcel自动创建表头行(后续手动控制行号) + .needHead(false) .build(); - WriteSheet writeSheet = EasyExcel.writerSheet("劳务费明细") - .needHead(true) - .relativeHeadRowIndex(1) // 数据从第3行开始,前2行为标题 - .build(); - - // 写数据 - writer.write(processedList, writeSheet); - - // 合并大标题 + // 2. 先获取Workbook和Sheet,手动创建大标题行(行0),此时行未刷盘 Workbook workbook = (Workbook) writer.writeContext().writeWorkbookHolder().getWorkbook(); Sheet sheet = workbook.getSheetAt(0); - sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, head.size() - 1)); - //Row titleRow = sheet.createRow(0); + if (sheet == null) { + sheet = workbook.createSheet("劳务费明细"); + } + + // 3. 手动创建行0(大标题行),此时行在内存中,未刷盘 Row titleRow = sheet.getRow(0); if (titleRow == null) { titleRow = sheet.createRow(0); } + + // 合并大标题行(0行0列 到 0行最后一列) + sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, head.size() - 1)); + + + // 4. 构建WriteSheet:表头从行1开始,数据从行2开始(对应relativeHeadRowIndex(1)) + WriteSheet writeSheet = EasyExcel.writerSheet("劳务费明细") + .needHead(true) // 重新开启表头,表头写入行1 + .relativeHeadRowIndex(1) // 数据从行2开始(表头行1 + 1) + .build(); + + // 5. 最后写入数据(行号递增:行0→行1→行2+,无回头修改) + writer.write(processedList, writeSheet); + titleRow.setHeightInPoints(30); // 设置标题行高 Cell titleCell = titleRow.createCell(0); titleCell.setCellValue("人工肝诊疗病例征集项目专家劳务费表"); @@ -251,7 +287,7 @@ public class CaseplatformCaseExcelController { response.setContentType("multipart/form-data"); response.setCharacterEncoding("utf-8"); writer.finish(); - + response.getOutputStream().flush(); outputStream.close(); } catch (Exception e) { From 848ec53939f282902b25ca912ae7ffe68e8a2f44 Mon Sep 17 00:00:00 2001 From: haomingming Date: Sun, 4 Jan 2026 13:14:46 +0800 Subject: [PATCH 2/9] =?UTF-8?q?=E5=AF=BC=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/CaseplatformCaseExcelController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/caseplatformcase/controller/CaseplatformCaseExcelController.java b/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/caseplatformcase/controller/CaseplatformCaseExcelController.java index 8f4c0f7..6572434 100644 --- a/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/caseplatformcase/controller/CaseplatformCaseExcelController.java +++ b/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/caseplatformcase/controller/CaseplatformCaseExcelController.java @@ -287,7 +287,7 @@ public class CaseplatformCaseExcelController { response.setContentType("multipart/form-data"); response.setCharacterEncoding("utf-8"); writer.finish(); - response.getOutputStream().flush(); + //response.getOutputStream().flush(); outputStream.close(); } catch (Exception e) { From e9970d5057e307199c42a78bde7bdb675cc76143 Mon Sep 17 00:00:00 2001 From: haomingming Date: Sun, 4 Jan 2026 13:35:39 +0800 Subject: [PATCH 3/9] =?UTF-8?q?=E5=AF=BC=E5=87=BA=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CaseplatformCaseExcelController.java | 361 ++++++++++-------- .../converter/CustomExcelWriteHandler.java | 146 +++++++ 2 files changed, 350 insertions(+), 157 deletions(-) create mode 100644 sa-admin/src/main/java/net/lab1024/sa/admin/module/business/caseplatformcase/converter/CustomExcelWriteHandler.java diff --git a/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/caseplatformcase/controller/CaseplatformCaseExcelController.java b/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/caseplatformcase/controller/CaseplatformCaseExcelController.java index 6572434..030ef71 100644 --- a/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/caseplatformcase/controller/CaseplatformCaseExcelController.java +++ b/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/caseplatformcase/controller/CaseplatformCaseExcelController.java @@ -9,6 +9,7 @@ import com.alibaba.excel.write.style.HorizontalCellStyleStrategy; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import net.lab1024.sa.admin.module.app.medicalrecord.service.MedicalRecordService; +import net.lab1024.sa.admin.module.business.caseplatformcase.converter.CustomExcelWriteHandler; import net.lab1024.sa.admin.module.business.caseplatformcase.domain.form.CaseplatformCaseQueryForm; import net.lab1024.sa.admin.module.business.caseplatformcase.domain.vo.EasyExcelCaseDetailVO; import net.lab1024.sa.admin.module.business.caseplatformcase.domain.vo.ExportExpertCaseExcelVo; @@ -94,58 +95,58 @@ public class CaseplatformCaseExcelController { } // 结算导出 - @ApiOperation("结算导出") - @GetMapping("/caseplatformCase/settlementExcel") - @PreAuthorize("@saAuth.checkPermission('case-system:case:exportExpertCaseExceli')") - public void exportExpertCaseExceli(HttpServletResponse response, @Valid CaseplatformCaseQueryForm queryForm) { - try { - List list = caseplatformCaseService.exportExpertCaseExcel(queryForm); - List processedList = caseplatformCaseService.exportExpertCaseExcelProcess(list); - - // 总计 - double totalActual = processedList.stream().mapToDouble(e -> Optional.ofNullable(e.getActualAmount()).orElse(0.0)).sum(); - double totalTax = processedList.stream().mapToDouble(e -> Optional.ofNullable(e.getTaxAmount()).orElse(0.0)).sum(); - double totalTotal = processedList.stream().mapToDouble(e -> Optional.ofNullable(e.getTotalAmount()).orElse(0.0)).sum(); - - String filePath = "./人工肝诊疗专家劳务费.xlsx"; - FileOutputStream outputStream = new FileOutputStream(filePath); - - // 字段标题 - List> head = Arrays.asList( - Collections.singletonList("序号"), - Collections.singletonList("银行"), - Collections.singletonList("账号所在省份"), - Collections.singletonList("账户所在地市"), - Collections.singletonList("卡号"), - Collections.singletonList("姓名"), - Collections.singletonList("实发"), - Collections.singletonList("备注"), - Collections.singletonList("个税"), - Collections.singletonList("应发"), - Collections.singletonList("单位"), - Collections.singletonList("电话"), - Collections.singletonList("身份证号"), - Collections.singletonList("关联病例") - ); - - WriteCellStyle headStyle = new WriteCellStyle(); - headStyle.setHorizontalAlignment(HorizontalAlignment.CENTER); - headStyle.setVerticalAlignment(VerticalAlignment.CENTER); - headStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND); - headStyle.setBorderBottom(BorderStyle.THIN); - headStyle.setBorderTop(BorderStyle.THIN); - headStyle.setBorderLeft(BorderStyle.THIN); - headStyle.setBorderRight(BorderStyle.THIN); - - WriteCellStyle contentStyle = new WriteCellStyle(); - contentStyle.setHorizontalAlignment(HorizontalAlignment.CENTER); - contentStyle.setVerticalAlignment(VerticalAlignment.CENTER); - contentStyle.setBorderBottom(BorderStyle.THIN); - contentStyle.setBorderTop(BorderStyle.THIN); - contentStyle.setBorderLeft(BorderStyle.THIN); - contentStyle.setBorderRight(BorderStyle.THIN); - -// ExcelWriter writer = EasyExcel.write(outputStream, ExportExpertCaseExcelVo.class) +// @ApiOperation("结算导出") +// @GetMapping("/caseplatformCase/settlementExcel") +// @PreAuthorize("@saAuth.checkPermission('case-system:case:exportExpertCaseExceli')") +// public void exportExpertCaseExceli(HttpServletResponse response, @Valid CaseplatformCaseQueryForm queryForm) { +// try { +// List list = caseplatformCaseService.exportExpertCaseExcel(queryForm); +// List processedList = caseplatformCaseService.exportExpertCaseExcelProcess(list); +// +// // 总计 +// double totalActual = processedList.stream().mapToDouble(e -> Optional.ofNullable(e.getActualAmount()).orElse(0.0)).sum(); +// double totalTax = processedList.stream().mapToDouble(e -> Optional.ofNullable(e.getTaxAmount()).orElse(0.0)).sum(); +// double totalTotal = processedList.stream().mapToDouble(e -> Optional.ofNullable(e.getTotalAmount()).orElse(0.0)).sum(); +// +// String filePath = "./人工肝诊疗专家劳务费.xlsx"; +// FileOutputStream outputStream = new FileOutputStream(filePath); +// +// // 字段标题 +// List> head = Arrays.asList( +// Collections.singletonList("序号"), +// Collections.singletonList("银行"), +// Collections.singletonList("账号所在省份"), +// Collections.singletonList("账户所在地市"), +// Collections.singletonList("卡号"), +// Collections.singletonList("姓名"), +// Collections.singletonList("实发"), +// Collections.singletonList("备注"), +// Collections.singletonList("个税"), +// Collections.singletonList("应发"), +// Collections.singletonList("单位"), +// Collections.singletonList("电话"), +// Collections.singletonList("身份证号"), +// Collections.singletonList("关联病例") +// ); +// +// WriteCellStyle headStyle = new WriteCellStyle(); +// headStyle.setHorizontalAlignment(HorizontalAlignment.CENTER); +// headStyle.setVerticalAlignment(VerticalAlignment.CENTER); +// headStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND); +// headStyle.setBorderBottom(BorderStyle.THIN); +// headStyle.setBorderTop(BorderStyle.THIN); +// headStyle.setBorderLeft(BorderStyle.THIN); +// headStyle.setBorderRight(BorderStyle.THIN); +// +// WriteCellStyle contentStyle = new WriteCellStyle(); +// contentStyle.setHorizontalAlignment(HorizontalAlignment.CENTER); +// contentStyle.setVerticalAlignment(VerticalAlignment.CENTER); +// contentStyle.setBorderBottom(BorderStyle.THIN); +// contentStyle.setBorderTop(BorderStyle.THIN); +// contentStyle.setBorderLeft(BorderStyle.THIN); +// contentStyle.setBorderRight(BorderStyle.THIN); +// +//// ExcelWriter writer = EasyExcel.write(outputStream, ExportExpertCaseExcelVo.class) // ExcelWriter writer = EasyExcel.write(response.getOutputStream(), ExportExpertCaseExcelVo.class) // .head(head) // .excelType(ExcelTypeEnum.XLSX) @@ -169,129 +170,175 @@ public class CaseplatformCaseExcelController { // if (titleRow == null) { // titleRow = sheet.createRow(0); // } +// titleRow.setHeightInPoints(30); // 设置标题行高 +// Cell titleCell = titleRow.createCell(0); +// titleCell.setCellValue("人工肝诊疗病例征集项目专家劳务费表"); +// CellStyle titleStyle = workbook.createCellStyle(); +// Font font = workbook.createFont(); +// font.setFontHeightInPoints((short) 16); +// font.setBold(true); +// titleStyle.setFont(font); +// titleStyle.setAlignment(HorizontalAlignment.CENTER); +// titleStyle.setVerticalAlignment(VerticalAlignment.CENTER); +// titleStyle.setBorderRight(BorderStyle.THIN); // 最后一格加右边框 +// titleCell.setCellStyle(titleStyle); +// +// // === 设置行高 === +// sheet.getRow(1).setHeightInPoints(25); // 表头行 +// for (int i = 2; i <= processedList.size() + 2; i++) { +// Row row = sheet.getRow(i); +// if (row != null) { +// row.setHeightInPoints(22); +// } +// } +// +// // === 设置列宽 === +// int[] columnWidths = { +// 6, 25, 15, 15, 25, 10, 10, 30, 8, 8, 30, 25, 30, 15 +// }; +// for (int i = 0; i < columnWidths.length; i++) { +// sheet.setColumnWidth(i, columnWidths[i] * 256); // 乘 256 为 Excel 单位 +// } +// +// // 写合计行 +// int totalRowIndex = processedList.size() + 2; // +1是数据从第3行开始,+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.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); +// +// // 合并前3列,写“合计” +// sheet.addMergedRegion(new CellRangeAddress(totalRowIndex, totalRowIndex, 0, 5)); +// Cell cell0 = totalRow.createCell(0); +// cell0.setCellValue("合计"); +// +// // 设置边框样式 +// 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 < head.size(); i++) { +// Cell cell = totalRow.getCell(i); +// if (cell == null) { +// cell = totalRow.createCell(i); +// } +// cell.setCellStyle(borderStyle); +// } +// +// // 实发(列 G = index 6)、个税(I = 8)、应发(J = 9) +// totalRow.getCell(6).setCellValue(totalActual); +// totalRow.getCell(8).setCellValue(totalTax); +// totalRow.getCell(9).setCellValue(totalTotal); +// +// // 6通知浏览器以附件的形式下载处理,设置返回头要注意文件名有中文 +// String fileName = URLEncoder.encode("病例数据", "UTF-8").replaceAll("\\+", "%20"); +// response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx"); +// response.setContentType("multipart/form-data"); +// response.setCharacterEncoding("utf-8"); +// writer.finish(); +// +// outputStream.close(); +// +// } catch (Exception e) { +// e.printStackTrace(); +// } +// } + @ApiOperation("结算导出") + @GetMapping("/caseplatformCase/settlementExcel") + @PreAuthorize("@saAuth.checkPermission('case-system:case:exportExpertCaseExceli')") + public void exportExpertCaseExceli(HttpServletResponse response, @Valid CaseplatformCaseQueryForm queryForm) { + try { + List list = caseplatformCaseService.exportExpertCaseExcel(queryForm); + List processedList = caseplatformCaseService.exportExpertCaseExcelProcess(list); - // 1. 构建ExcelWriter(先不写入数据,先处理大标题行) + // 总计 + double totalActual = processedList.stream().mapToDouble(e -> Optional.ofNullable(e.getActualAmount()).orElse(0.0)).sum(); + double totalTax = processedList.stream().mapToDouble(e -> Optional.ofNullable(e.getTaxAmount()).orElse(0.0)).sum(); + double totalTotal = processedList.stream().mapToDouble(e -> Optional.ofNullable(e.getTotalAmount()).orElse(0.0)).sum(); + + // 字段标题 + List> head = Arrays.asList( + Collections.singletonList("序号"), + Collections.singletonList("银行"), + Collections.singletonList("账号所在省份"), + Collections.singletonList("账户所在地市"), + Collections.singletonList("卡号"), + Collections.singletonList("姓名"), + Collections.singletonList("实发"), + Collections.singletonList("备注"), + Collections.singletonList("个税"), + Collections.singletonList("应发"), + Collections.singletonList("单位"), + Collections.singletonList("电话"), + Collections.singletonList("身份证号"), + Collections.singletonList("关联病例") + ); + + // 1. 配置样式策略 + WriteCellStyle headStyle = new WriteCellStyle(); + headStyle.setHorizontalAlignment(HorizontalAlignment.CENTER); + headStyle.setVerticalAlignment(VerticalAlignment.CENTER); + headStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND); + headStyle.setBorderBottom(BorderStyle.THIN); + headStyle.setBorderTop(BorderStyle.THIN); + headStyle.setBorderLeft(BorderStyle.THIN); + headStyle.setBorderRight(BorderStyle.THIN); + + WriteCellStyle contentStyle = new WriteCellStyle(); + contentStyle.setHorizontalAlignment(HorizontalAlignment.CENTER); + contentStyle.setVerticalAlignment(VerticalAlignment.CENTER); + contentStyle.setBorderBottom(BorderStyle.THIN); + contentStyle.setBorderTop(BorderStyle.THIN); + contentStyle.setBorderLeft(BorderStyle.THIN); + contentStyle.setBorderRight(BorderStyle.THIN); + + // 2. 初始化 ExcelWriter(仅使用响应输出流,移除本地文件输出) ExcelWriter writer = EasyExcel.write(response.getOutputStream(), ExportExpertCaseExcelVo.class) .head(head) .excelType(ExcelTypeEnum.XLSX) .registerWriteHandler(new HorizontalCellStyleStrategy(headStyle, contentStyle)) - // 关键:禁用EasyExcel自动创建表头行(后续手动控制行号) - .needHead(false) + // 关键:注册自定义处理器,提前处理标题、样式、合计等 + .registerWriteHandler(new CustomExcelWriteHandler(totalActual, totalTax, totalTotal, processedList.size())) .build(); - // 2. 先获取Workbook和Sheet,手动创建大标题行(行0),此时行未刷盘 - Workbook workbook = (Workbook) writer.writeContext().writeWorkbookHolder().getWorkbook(); - Sheet sheet = workbook.getSheetAt(0); - if (sheet == null) { - sheet = workbook.createSheet("劳务费明细"); - } - - // 3. 手动创建行0(大标题行),此时行在内存中,未刷盘 - Row titleRow = sheet.getRow(0); - if (titleRow == null) { - titleRow = sheet.createRow(0); - } - - // 合并大标题行(0行0列 到 0行最后一列) - sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, head.size() - 1)); - - - // 4. 构建WriteSheet:表头从行1开始,数据从行2开始(对应relativeHeadRowIndex(1)) + // 3. 配置 Sheet(数据从第2行开始,第0行是大标题,第1行是表头) WriteSheet writeSheet = EasyExcel.writerSheet("劳务费明细") - .needHead(true) // 重新开启表头,表头写入行1 - .relativeHeadRowIndex(1) // 数据从行2开始(表头行1 + 1) + .needHead(true) + .relativeHeadRowIndex(1) // 表头行是第1行,数据从第2行开始 .build(); - // 5. 最后写入数据(行号递增:行0→行1→行2+,无回头修改) + // 4. 先写数据(此时自定义处理器会在写入前后处理样式/标题/合计) writer.write(processedList, writeSheet); - titleRow.setHeightInPoints(30); // 设置标题行高 - Cell titleCell = titleRow.createCell(0); - titleCell.setCellValue("人工肝诊疗病例征集项目专家劳务费表"); - CellStyle titleStyle = workbook.createCellStyle(); - Font font = workbook.createFont(); - font.setFontHeightInPoints((short) 16); - font.setBold(true); - titleStyle.setFont(font); - titleStyle.setAlignment(HorizontalAlignment.CENTER); - titleStyle.setVerticalAlignment(VerticalAlignment.CENTER); - titleStyle.setBorderRight(BorderStyle.THIN); // 最后一格加右边框 - titleCell.setCellStyle(titleStyle); - - // === 设置行高 === - sheet.getRow(1).setHeightInPoints(25); // 表头行 - for (int i = 2; i <= processedList.size() + 2; i++) { - Row row = sheet.getRow(i); - if (row != null) { - row.setHeightInPoints(22); - } - } - - // === 设置列宽 === - int[] columnWidths = { - 6, 25, 15, 15, 25, 10, 10, 30, 8, 8, 30, 25, 30, 15 - }; - for (int i = 0; i < columnWidths.length; i++) { - sheet.setColumnWidth(i, columnWidths[i] * 256); // 乘 256 为 Excel 单位 - } - - // 写合计行 - int totalRowIndex = processedList.size() + 2; // +1是数据从第3行开始,+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.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); - - // 合并前3列,写“合计” - sheet.addMergedRegion(new CellRangeAddress(totalRowIndex, totalRowIndex, 0, 5)); - Cell cell0 = totalRow.createCell(0); - cell0.setCellValue("合计"); - - // 设置边框样式 - 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 < head.size(); i++) { - Cell cell = totalRow.getCell(i); - if (cell == null) { - cell = totalRow.createCell(i); - } - cell.setCellStyle(borderStyle); - } - - // 实发(列 G = index 6)、个税(I = 8)、应发(J = 9) - totalRow.getCell(6).setCellValue(totalActual); - totalRow.getCell(8).setCellValue(totalTax); - totalRow.getCell(9).setCellValue(totalTotal); - - // 6通知浏览器以附件的形式下载处理,设置返回头要注意文件名有中文 + // 5. 响应头配置(中文文件名编码) String fileName = URLEncoder.encode("病例数据", "UTF-8").replaceAll("\\+", "%20"); - response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx"); - response.setContentType("multipart/form-data"); + response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx"); + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setCharacterEncoding("utf-8"); + + // 6. 完成写入 writer.finish(); - //response.getOutputStream().flush(); - outputStream.close(); } catch (Exception e) { e.printStackTrace(); + // 补充:抛出异常让全局异常处理器处理,避免前端无响应 + throw new RuntimeException("导出Excel失败:" + e.getMessage(), e); } } 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 new file mode 100644 index 0000000..24956e1 --- /dev/null +++ b/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/caseplatformcase/converter/CustomExcelWriteHandler.java @@ -0,0 +1,146 @@ +package net.lab1024.sa.admin.module.business.caseplatformcase.converter; + +import com.alibaba.excel.metadata.Head; +import com.alibaba.excel.metadata.data.CellData; +import com.alibaba.excel.write.handler.WriteHandler; +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 java.util.List; + +public class CustomExcelWriteHandler implements WriteHandler { + private final double totalActual; + private final double totalTax; + private final double totalTotal; + private final int dataSize; + + public CustomExcelWriteHandler(double totalActual, double totalTax, double totalTotal, int dataSize) { + this.totalActual = totalActual; + this.totalTax = totalTax; + this.totalTotal = totalTotal; + this.dataSize = dataSize; + } + + public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { + // 工作表创建后,先处理大标题、表头样式、列宽(此时还未写入数据,行未刷盘) + Workbook workbook = writeWorkbookHolder.getWorkbook(); + Sheet sheet = writeSheetHolder.getSheet(); + + // 1. 处理大标题(第0行) + Row titleRow = sheet.createRow(0); + 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(); + Font titleFont = workbook.createFont(); + titleFont.setFontHeightInPoints((short) 16); + titleFont.setBold(true); + titleStyle.setFont(titleFont); + titleStyle.setAlignment(HorizontalAlignment.CENTER); + titleStyle.setVerticalAlignment(VerticalAlignment.CENTER); + titleStyle.setBorderBottom(BorderStyle.THIN); + titleStyle.setBorderTop(BorderStyle.THIN); + titleStyle.setBorderLeft(BorderStyle.THIN); + titleStyle.setBorderRight(BorderStyle.THIN); + titleCell.setCellStyle(titleStyle); + + // 2. 设置列宽 + int[] columnWidths = {6, 25, 15, 15, 25, 10, 10, 30, 8, 8, 30, 25, 30, 15}; + for (int i = 0; i < columnWidths.length; i++) { + sheet.setColumnWidth(i, columnWidths[i] * 256); + } + + // 3. 预设置表头行(第1行)样式和行高 + Row headRow = sheet.createRow(1); + headRow.setHeightInPoints(25); + } + + public void afterWorkbookDispose(WriteWorkbookHolder writeWorkbookHolder) { + // 数据写入完成后,处理合计行和数据行高(此时所有数据行已写入,但合计行是新创建的,未刷盘) + Workbook workbook = writeWorkbookHolder.getWorkbook(); + Sheet sheet = workbook.getSheetAt(0); + + // 1. 设置数据行行高(第2行到数据最后一行) + for (int i = 2; i <= dataSize + 1; i++) { // 数据从第2行开始,共dataSize行 + Row row = sheet.getRow(i); + if (row != null) { + row.setHeightInPoints(22); + } + } + + // 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); + } + } + + // 其他默认方法实现 + public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {} + public void beforeWorkbookCreate(WriteWorkbookHolder writeWorkbookHolder) {} + public void beforeWorkbookDispose(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) {} + public void afterCellDispose(WriteSheetHolder writeSheetHolder, List cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {} + public void beforeCellCreate(WriteSheetHolder writeSheetHolder, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {} +} \ No newline at end of file From 7881d80b355febea6bf1d5d5986a90ef882760e0 Mon Sep 17 00:00:00 2001 From: haomingming Date: Sun, 4 Jan 2026 13:46:45 +0800 Subject: [PATCH 4/9] =?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) {} From 3a7c6aa4e32d274df7640f4d0c42037c70b6b59f Mon Sep 17 00:00:00 2001 From: haomingming Date: Sun, 4 Jan 2026 13:57:15 +0800 Subject: [PATCH 5/9] dd --- .../CaseplatformCaseExcelController.java | 191 +----------------- 1 file changed, 9 insertions(+), 182 deletions(-) diff --git a/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/caseplatformcase/controller/CaseplatformCaseExcelController.java b/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/caseplatformcase/controller/CaseplatformCaseExcelController.java index 030ef71..9f4fff3 100644 --- a/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/caseplatformcase/controller/CaseplatformCaseExcelController.java +++ b/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/caseplatformcase/controller/CaseplatformCaseExcelController.java @@ -8,7 +8,6 @@ import com.alibaba.excel.write.metadata.style.WriteCellStyle; import com.alibaba.excel.write.style.HorizontalCellStyleStrategy; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; -import net.lab1024.sa.admin.module.app.medicalrecord.service.MedicalRecordService; import net.lab1024.sa.admin.module.business.caseplatformcase.converter.CustomExcelWriteHandler; import net.lab1024.sa.admin.module.business.caseplatformcase.domain.form.CaseplatformCaseQueryForm; import net.lab1024.sa.admin.module.business.caseplatformcase.domain.vo.EasyExcelCaseDetailVO; @@ -19,16 +18,13 @@ import net.lab1024.sa.common.common.exception.BusinessException; import net.lab1024.sa.common.module.support.operatelog.annoation.OperateLog; import org.apache.poi.ss.formula.functions.T; import org.apache.poi.ss.usermodel.*; -import org.apache.poi.ss.util.CellRangeAddress; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; -import java.io.FileOutputStream; import java.net.URLEncoder; import java.util.*; @@ -95,170 +91,6 @@ public class CaseplatformCaseExcelController { } // 结算导出 -// @ApiOperation("结算导出") -// @GetMapping("/caseplatformCase/settlementExcel") -// @PreAuthorize("@saAuth.checkPermission('case-system:case:exportExpertCaseExceli')") -// public void exportExpertCaseExceli(HttpServletResponse response, @Valid CaseplatformCaseQueryForm queryForm) { -// try { -// List list = caseplatformCaseService.exportExpertCaseExcel(queryForm); -// List processedList = caseplatformCaseService.exportExpertCaseExcelProcess(list); -// -// // 总计 -// double totalActual = processedList.stream().mapToDouble(e -> Optional.ofNullable(e.getActualAmount()).orElse(0.0)).sum(); -// double totalTax = processedList.stream().mapToDouble(e -> Optional.ofNullable(e.getTaxAmount()).orElse(0.0)).sum(); -// double totalTotal = processedList.stream().mapToDouble(e -> Optional.ofNullable(e.getTotalAmount()).orElse(0.0)).sum(); -// -// String filePath = "./人工肝诊疗专家劳务费.xlsx"; -// FileOutputStream outputStream = new FileOutputStream(filePath); -// -// // 字段标题 -// List> head = Arrays.asList( -// Collections.singletonList("序号"), -// Collections.singletonList("银行"), -// Collections.singletonList("账号所在省份"), -// Collections.singletonList("账户所在地市"), -// Collections.singletonList("卡号"), -// Collections.singletonList("姓名"), -// Collections.singletonList("实发"), -// Collections.singletonList("备注"), -// Collections.singletonList("个税"), -// Collections.singletonList("应发"), -// Collections.singletonList("单位"), -// Collections.singletonList("电话"), -// Collections.singletonList("身份证号"), -// Collections.singletonList("关联病例") -// ); -// -// WriteCellStyle headStyle = new WriteCellStyle(); -// headStyle.setHorizontalAlignment(HorizontalAlignment.CENTER); -// headStyle.setVerticalAlignment(VerticalAlignment.CENTER); -// headStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND); -// headStyle.setBorderBottom(BorderStyle.THIN); -// headStyle.setBorderTop(BorderStyle.THIN); -// headStyle.setBorderLeft(BorderStyle.THIN); -// headStyle.setBorderRight(BorderStyle.THIN); -// -// WriteCellStyle contentStyle = new WriteCellStyle(); -// contentStyle.setHorizontalAlignment(HorizontalAlignment.CENTER); -// contentStyle.setVerticalAlignment(VerticalAlignment.CENTER); -// contentStyle.setBorderBottom(BorderStyle.THIN); -// contentStyle.setBorderTop(BorderStyle.THIN); -// contentStyle.setBorderLeft(BorderStyle.THIN); -// contentStyle.setBorderRight(BorderStyle.THIN); -// -//// ExcelWriter writer = EasyExcel.write(outputStream, ExportExpertCaseExcelVo.class) -// ExcelWriter writer = EasyExcel.write(response.getOutputStream(), ExportExpertCaseExcelVo.class) -// .head(head) -// .excelType(ExcelTypeEnum.XLSX) -// .registerWriteHandler(new HorizontalCellStyleStrategy(headStyle, contentStyle)) -// .build(); -// -// WriteSheet writeSheet = EasyExcel.writerSheet("劳务费明细") -// .needHead(true) -// .relativeHeadRowIndex(1) // 数据从第3行开始,前2行为标题 -// .build(); -// -// // 写数据 -// writer.write(processedList, writeSheet); -// -// // 合并大标题 -// Workbook workbook = (Workbook) writer.writeContext().writeWorkbookHolder().getWorkbook(); -// Sheet sheet = workbook.getSheetAt(0); -// sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, head.size() - 1)); -// //Row titleRow = sheet.createRow(0); -// Row titleRow = sheet.getRow(0); -// if (titleRow == null) { -// titleRow = sheet.createRow(0); -// } -// titleRow.setHeightInPoints(30); // 设置标题行高 -// Cell titleCell = titleRow.createCell(0); -// titleCell.setCellValue("人工肝诊疗病例征集项目专家劳务费表"); -// CellStyle titleStyle = workbook.createCellStyle(); -// Font font = workbook.createFont(); -// font.setFontHeightInPoints((short) 16); -// font.setBold(true); -// titleStyle.setFont(font); -// titleStyle.setAlignment(HorizontalAlignment.CENTER); -// titleStyle.setVerticalAlignment(VerticalAlignment.CENTER); -// titleStyle.setBorderRight(BorderStyle.THIN); // 最后一格加右边框 -// titleCell.setCellStyle(titleStyle); -// -// // === 设置行高 === -// sheet.getRow(1).setHeightInPoints(25); // 表头行 -// for (int i = 2; i <= processedList.size() + 2; i++) { -// Row row = sheet.getRow(i); -// if (row != null) { -// row.setHeightInPoints(22); -// } -// } -// -// // === 设置列宽 === -// int[] columnWidths = { -// 6, 25, 15, 15, 25, 10, 10, 30, 8, 8, 30, 25, 30, 15 -// }; -// for (int i = 0; i < columnWidths.length; i++) { -// sheet.setColumnWidth(i, columnWidths[i] * 256); // 乘 256 为 Excel 单位 -// } -// -// // 写合计行 -// int totalRowIndex = processedList.size() + 2; // +1是数据从第3行开始,+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.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); -// -// // 合并前3列,写“合计” -// sheet.addMergedRegion(new CellRangeAddress(totalRowIndex, totalRowIndex, 0, 5)); -// Cell cell0 = totalRow.createCell(0); -// cell0.setCellValue("合计"); -// -// // 设置边框样式 -// 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 < head.size(); i++) { -// Cell cell = totalRow.getCell(i); -// if (cell == null) { -// cell = totalRow.createCell(i); -// } -// cell.setCellStyle(borderStyle); -// } -// -// // 实发(列 G = index 6)、个税(I = 8)、应发(J = 9) -// totalRow.getCell(6).setCellValue(totalActual); -// totalRow.getCell(8).setCellValue(totalTax); -// totalRow.getCell(9).setCellValue(totalTotal); -// -// // 6通知浏览器以附件的形式下载处理,设置返回头要注意文件名有中文 -// String fileName = URLEncoder.encode("病例数据", "UTF-8").replaceAll("\\+", "%20"); -// response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx"); -// response.setContentType("multipart/form-data"); -// response.setCharacterEncoding("utf-8"); -// writer.finish(); -// -// outputStream.close(); -// -// } catch (Exception e) { -// e.printStackTrace(); -// } -// } @ApiOperation("结算导出") @GetMapping("/caseplatformCase/settlementExcel") @PreAuthorize("@saAuth.checkPermission('case-system:case:exportExpertCaseExceli')") @@ -290,7 +122,6 @@ public class CaseplatformCaseExcelController { Collections.singletonList("关联病例") ); - // 1. 配置样式策略 WriteCellStyle headStyle = new WriteCellStyle(); headStyle.setHorizontalAlignment(HorizontalAlignment.CENTER); headStyle.setVerticalAlignment(VerticalAlignment.CENTER); @@ -308,37 +139,33 @@ public class CaseplatformCaseExcelController { contentStyle.setBorderLeft(BorderStyle.THIN); contentStyle.setBorderRight(BorderStyle.THIN); - // 2. 初始化 ExcelWriter(仅使用响应输出流,移除本地文件输出) + // 使用 CustomExcelWriteHandler 在正确的时机创建标题行和合计行 + CustomExcelWriteHandler customHandler = new CustomExcelWriteHandler(totalActual, totalTax, totalTotal, processedList.size()); + ExcelWriter writer = EasyExcel.write(response.getOutputStream(), ExportExpertCaseExcelVo.class) .head(head) .excelType(ExcelTypeEnum.XLSX) .registerWriteHandler(new HorizontalCellStyleStrategy(headStyle, contentStyle)) - // 关键:注册自定义处理器,提前处理标题、样式、合计等 - .registerWriteHandler(new CustomExcelWriteHandler(totalActual, totalTax, totalTotal, processedList.size())) + .registerWriteHandler(customHandler) .build(); - // 3. 配置 Sheet(数据从第2行开始,第0行是大标题,第1行是表头) WriteSheet writeSheet = EasyExcel.writerSheet("劳务费明细") .needHead(true) - .relativeHeadRowIndex(1) // 表头行是第1行,数据从第2行开始 + .relativeHeadRowIndex(1) // 数据从第3行开始,前2行为标题 .build(); - // 4. 先写数据(此时自定义处理器会在写入前后处理样式/标题/合计) + // 写数据 writer.write(processedList, writeSheet); - // 5. 响应头配置(中文文件名编码) + // 6通知浏览器以附件的形式下载处理,设置返回头要注意文件名有中文 String fileName = URLEncoder.encode("病例数据", "UTF-8").replaceAll("\\+", "%20"); - response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx"); - response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx"); + response.setContentType("multipart/form-data"); response.setCharacterEncoding("utf-8"); - - // 6. 完成写入 writer.finish(); } catch (Exception e) { e.printStackTrace(); - // 补充:抛出异常让全局异常处理器处理,避免前端无响应 - throw new RuntimeException("导出Excel失败:" + e.getMessage(), e); } } From e4b4423b660661c79bb2c79f1e42406bf36f0aed Mon Sep 17 00:00:00 2001 From: haomingming Date: Sun, 4 Jan 2026 14:15:19 +0800 Subject: [PATCH 6/9] daochu --- .../converter/CustomExcelWriteHandler.java | 157 ++++++++++-------- 1 file changed, 86 insertions(+), 71 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 de1d58c..6fb53de 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 @@ -18,6 +18,7 @@ public class CustomExcelWriteHandler implements WriteHandler { private final double totalTotal; private final int dataSize; private boolean totalRowCreated = false; + private int processedDataRowCount = 0; // 已处理的数据行数 // 缓存 Workbook(在 afterSheetCreate 中初始化) private Workbook workbook; @@ -64,82 +65,96 @@ public class CustomExcelWriteHandler implements WriteHandler { headRow.setHeightInPoints(25); } - // 关键:数据行写入完成后创建合计行(兼容低版本) + // 设置数据行行高,并在最后一行数据写入后创建合计行 public void afterRowDispose(WriteSheetHolder writeSheetHolder, Row row, Integer relativeRowIndex, Boolean isHead) throws IOException { - // 仅在最后一行数据写入后创建合计行,且未创建过 - if (!totalRowCreated && relativeRowIndex != null && relativeRowIndex == dataSize - 1) { - Sheet sheet = writeSheetHolder.getSheet(); - - // 修正合计行索引: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); + // 设置数据行行高(排除表头行) + if (isHead == null || !isHead) { + processedDataRowCount++; + if (row.getRowNum() >= 2 && row.getRowNum() <= 1 + dataSize) { + row.setHeightInPoints(22); } - - // 标记合计行已创建 - totalRowCreated = true; - - // 强制刷新(兼容SXSSF) - if (sheet instanceof SXSSFSheet) { - ((SXSSFSheet) sheet).flushRows(); + + // 如果是最后一行数据,创建合计行 + if (!totalRowCreated && processedDataRowCount == dataSize && dataSize > 0) { + createTotalRow(writeSheetHolder.getSheet()); } } + } + + // 创建合计行的辅助方法 + private void createTotalRow(Sheet sheet) throws IOException { + // 修正合计行索引:0=大标题,1=表头,2~1+dataSize=数据,2+dataSize=合计 + int totalRowIndex = 2 + dataSize; + Row totalRow = sheet.createRow(totalRowIndex); + totalRow.setHeightInPoints(22); - // 设置数据行行高 - if (row.getRowNum() >= 2 && row.getRowNum() <= 1 + dataSize) { - row.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(); + } + } + + // 备用:在所有数据写入完成后创建合计行(如果 afterRowDispose 中没有创建) + public void afterSheetDispose(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) throws IOException { + // 如果合计行还未创建,则创建(备用方案) + if (!totalRowCreated && dataSize > 0) { + createTotalRow(writeSheetHolder.getSheet()); } } From c7c7feefcf51e1d8ae54d181758f7526d7fa0b76 Mon Sep 17 00:00:00 2001 From: haomingming Date: Sun, 4 Jan 2026 14:21:42 +0800 Subject: [PATCH 7/9] dd --- .../CaseplatformCaseExcelController.java | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/caseplatformcase/controller/CaseplatformCaseExcelController.java b/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/caseplatformcase/controller/CaseplatformCaseExcelController.java index 9f4fff3..6d76652 100644 --- a/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/caseplatformcase/controller/CaseplatformCaseExcelController.java +++ b/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/caseplatformcase/controller/CaseplatformCaseExcelController.java @@ -18,6 +18,8 @@ import net.lab1024.sa.common.common.exception.BusinessException; import net.lab1024.sa.common.module.support.operatelog.annoation.OperateLog; import org.apache.poi.ss.formula.functions.T; import org.apache.poi.ss.usermodel.*; +import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.xssf.streaming.SXSSFSheet; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; @@ -157,6 +159,101 @@ public class CaseplatformCaseExcelController { // 写数据 writer.write(processedList, writeSheet); + // 创建合计行(在数据写入后,finish 之前) + try { + Workbook workbook = writer.writeContext().writeWorkbookHolder().getWorkbook(); + Sheet sheet = workbook.getSheetAt(0); + int totalRowIndex = 2 + processedList.size(); // 0=大标题,1=表头,2~1+size=数据,2+size=合计 + + Row totalRow = null; + // 如果是 SXSSFSheet,需要特殊处理 + if (sheet instanceof SXSSFSheet) { + SXSSFSheet sxssfSheet = (SXSSFSheet) sheet; + // 先刷新所有已写入的行到磁盘 + sxssfSheet.flushRows(); + // 然后尝试创建新行 + try { + totalRow = sxssfSheet.createRow(totalRowIndex); + } catch (IllegalArgumentException e) { + // 如果行已经存在,尝试获取它 + totalRow = sxssfSheet.getRow(totalRowIndex); + if (totalRow == null) { + // 如果获取失败,尝试使用随机访问窗口 + sxssfSheet.setRandomAccessWindowSize(-1); // 禁用随机访问窗口限制 + totalRow = sxssfSheet.createRow(totalRowIndex); + } + } + } else { + // 普通 Sheet,直接创建或获取 + totalRow = sheet.getRow(totalRowIndex); + if (totalRow == null) { + totalRow = sheet.createRow(totalRowIndex); + } + } + + if (totalRow == null) { + throw new RuntimeException("无法创建合计行"); + } + + 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 < head.size(); 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); + } + } catch (Exception e) { + // 如果创建合计行失败,记录错误但不影响导出 + e.printStackTrace(); + } + // 6通知浏览器以附件的形式下载处理,设置返回头要注意文件名有中文 String fileName = URLEncoder.encode("病例数据", "UTF-8").replaceAll("\\+", "%20"); response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx"); From d071779de8512dc6bab74d7e7babc086baa6603d Mon Sep 17 00:00:00 2001 From: haomingming Date: Sun, 4 Jan 2026 14:27:51 +0800 Subject: [PATCH 8/9] qw --- .../controller/CaseplatformCaseExcelController.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/caseplatformcase/controller/CaseplatformCaseExcelController.java b/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/caseplatformcase/controller/CaseplatformCaseExcelController.java index 6d76652..a644f9c 100644 --- a/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/caseplatformcase/controller/CaseplatformCaseExcelController.java +++ b/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/caseplatformcase/controller/CaseplatformCaseExcelController.java @@ -201,9 +201,9 @@ public class CaseplatformCaseExcelController { CellStyle totalStyle = workbook.createCellStyle(); Font totalFont = workbook.createFont(); totalFont.setBold(true); - totalFont.setColor(IndexedColors.WHITE.getIndex()); + totalFont.setColor(IndexedColors.BLACK.getIndex()); totalStyle.setFont(totalFont); - totalStyle.setFillForegroundColor(IndexedColors.BLACK.getIndex()); + totalStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex()); totalStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); totalStyle.setAlignment(HorizontalAlignment.CENTER); totalStyle.setVerticalAlignment(VerticalAlignment.CENTER); From 5e0ddde4ecded7968f39e181335f69bed9f33f61 Mon Sep 17 00:00:00 2001 From: haomingming Date: Sun, 4 Jan 2026 14:35:44 +0800 Subject: [PATCH 9/9] e --- .../CaseplatformCaseExcelController.java | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/caseplatformcase/controller/CaseplatformCaseExcelController.java b/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/caseplatformcase/controller/CaseplatformCaseExcelController.java index a644f9c..fab5de7 100644 --- a/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/caseplatformcase/controller/CaseplatformCaseExcelController.java +++ b/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/caseplatformcase/controller/CaseplatformCaseExcelController.java @@ -159,10 +159,40 @@ public class CaseplatformCaseExcelController { // 写数据 writer.write(processedList, writeSheet); - // 创建合计行(在数据写入后,finish 之前) + // 设置标题和合计行(在数据写入后,finish 之前) try { Workbook workbook = writer.writeContext().writeWorkbookHolder().getWorkbook(); Sheet sheet = workbook.getSheetAt(0); + + // 确保标题行存在并设置标题 + Row titleRow = sheet.getRow(0); + if (titleRow == null) { + titleRow = sheet.createRow(0); + } + titleRow.setHeightInPoints(30); + Cell titleCell = titleRow.getCell(0); + if (titleCell == null) { + titleCell = titleRow.createCell(0); + } + titleCell.setCellValue("人工肝诊疗病例征集项目专家劳务费表"); + + // 合并标题单元格 + sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, head.size() - 1)); + + // 设置标题样式 + CellStyle titleStyle = workbook.createCellStyle(); + Font titleFont = workbook.createFont(); + titleFont.setFontHeightInPoints((short) 16); + titleFont.setBold(true); + titleStyle.setFont(titleFont); + titleStyle.setAlignment(HorizontalAlignment.CENTER); + titleStyle.setVerticalAlignment(VerticalAlignment.CENTER); + titleStyle.setBorderBottom(BorderStyle.THIN); + titleStyle.setBorderTop(BorderStyle.THIN); + titleStyle.setBorderLeft(BorderStyle.THIN); + titleStyle.setBorderRight(BorderStyle.THIN); + titleCell.setCellStyle(titleStyle); + int totalRowIndex = 2 + processedList.size(); // 0=大标题,1=表头,2~1+size=数据,2+size=合计 Row totalRow = null;