diff --git a/bonus-modules/bonus-material-mall/src/main/java/com/bonus/material/device/controller/DevMergeController.java b/bonus-modules/bonus-material-mall/src/main/java/com/bonus/material/device/controller/DevMergeController.java index d09c367..2101b6f 100644 --- a/bonus-modules/bonus-material-mall/src/main/java/com/bonus/material/device/controller/DevMergeController.java +++ b/bonus-modules/bonus-material-mall/src/main/java/com/bonus/material/device/controller/DevMergeController.java @@ -20,6 +20,7 @@ import com.bonus.material.device.domain.vo.DevInfoVo; import com.bonus.material.device.domain.vo.DevMergeVo; import com.bonus.material.device.service.DevInfoService; import com.bonus.material.device.service.DevMergeService; +import com.bonus.material.utils.CenterExcelUtil; import com.bonus.material.utils.FolderZipUtil; import com.bonus.material.utils.ReflectUtils; import io.swagger.annotations.Api; @@ -346,7 +347,8 @@ public class DevMergeController extends BaseController { } // 3. 调用工具类生成模板(自动触发下拉选生成) - ExcelUtil util = new ExcelUtil<>(EquipmentImportDTO.class); + // 使用 CenterExcelUtil 替代 ExcelUtil,确保所有单元格(包括空白行)都居中对齐 + CenterExcelUtil util = new CenterExcelUtil<>(EquipmentImportDTO.class); // importTemplateExcel:专门生成导入模板的方法(仅表头+下拉选,无数据) util.importTemplateExcel(response, "装备信息导入模板", "装备信息导入模板"); } diff --git a/bonus-modules/bonus-material-mall/src/main/java/com/bonus/material/utils/CenterExcelUtil.java b/bonus-modules/bonus-material-mall/src/main/java/com/bonus/material/utils/CenterExcelUtil.java index d6c433e..be9d0a3 100644 --- a/bonus-modules/bonus-material-mall/src/main/java/com/bonus/material/utils/CenterExcelUtil.java +++ b/bonus-modules/bonus-material-mall/src/main/java/com/bonus/material/utils/CenterExcelUtil.java @@ -30,7 +30,7 @@ public class CenterExcelUtil extends ExcelUtil { try { // 1. 将Excel写入到字节数组(而不是直接写入响应) ByteArrayOutputStream baos = new ByteArrayOutputStream(); - HttpServletResponse tempResponse = createTempResponse(baos); + HttpServletResponse tempResponse = createTempResponse(response, baos); // 2. 调用父类方法生成模板 super.importTemplateExcel(tempResponse, sheetName, title); @@ -54,8 +54,8 @@ public class CenterExcelUtil extends ExcelUtil { /** * 创建临时响应对象,用于捕获Excel字节数据 */ - private HttpServletResponse createTempResponse(ByteArrayOutputStream baos) throws IOException { - return new HttpServletResponseWrapper(null) { + private HttpServletResponse createTempResponse(HttpServletResponse originalResponse, ByteArrayOutputStream baos) throws IOException { + return new HttpServletResponseWrapper(originalResponse) { @Override public javax.servlet.ServletOutputStream getOutputStream() { return new javax.servlet.ServletOutputStream() { @@ -86,23 +86,67 @@ public class CenterExcelUtil extends ExcelUtil { Workbook workbook = WorkbookFactory.create(bais); ByteArrayOutputStream baos = new ByteArrayOutputStream()) { + // 创建居中样式(用于空白单元格) + CellStyle centerStyle = workbook.createCellStyle(); + centerStyle.setAlignment(HorizontalAlignment.CENTER); + centerStyle.setVerticalAlignment(VerticalAlignment.CENTER); + + // 使用Map缓存已处理的样式,避免创建过多样式对象(POI有64000个样式的限制) + java.util.Map styleCache = new java.util.HashMap<>(); + // 遍历所有工作表 for (int i = 0; i < workbook.getNumberOfSheets(); i++) { Sheet sheet = workbook.getSheetAt(i); if (sheet == null) continue; - // 遍历所有存在的行 - for (int rowIndex = sheet.getFirstRowNum(); rowIndex <= sheet.getLastRowNum(); rowIndex++) { + // 获取表头行以确定列数 + Row headerRow = sheet.getRow(sheet.getFirstRowNum()); + if (headerRow == null) continue; + + // 获取实际的列数,取表头列数和11(A-K列)的最大值 + int headerColNum = headerRow.getLastCellNum(); + int maxColNum = Math.max(headerColNum, 11); // 确保至少包含A-K列(0-10) + + // 预创建足够多的行(例如1000行),并为所有单元格设置居中样式 + // 这样用户在任何位置输入内容时都会自动居中 + int maxRows = 1000; // 可以根据需要调整行数 + for (int rowIndex = 0; rowIndex < maxRows; rowIndex++) { Row row = sheet.getRow(rowIndex); - if (row == null) continue; + if (row == null) { + row = sheet.createRow(rowIndex); + } - // 遍历所有存在的单元格 - for (int cellIndex = row.getFirstCellNum(); cellIndex <= row.getLastCellNum(); cellIndex++) { - Cell cell = row.getCell(cellIndex); - if (cell == null) continue; + // 为该行的所有列创建单元格并设置居中样式(A-K列,即0-10) + for (int colIndex = 0; colIndex < maxColNum; colIndex++) { + Cell cell = row.getCell(colIndex); + if (cell == null) { + cell = row.createCell(colIndex); + } - // 设置单元格居中 - setCellCenterStyle(workbook, cell); + // 获取或创建居中样式 + CellStyle existingStyle = cell.getCellStyle(); + short styleIndex = existingStyle.getIndex(); + + // 检查缓存中是否已有该样式的居中版本 + CellStyle centeredStyle = styleCache.get(styleIndex); + if (centeredStyle == null) { + // 创建新的居中样式 + if (styleIndex == 0) { + // 默认样式,使用预创建的居中样式 + centeredStyle = centerStyle; + } else { + // 自定义样式,复制并添加居中 + centeredStyle = workbook.createCellStyle(); + centeredStyle.cloneStyleFrom(existingStyle); + centeredStyle.setAlignment(HorizontalAlignment.CENTER); + centeredStyle.setVerticalAlignment(VerticalAlignment.CENTER); + } + // 缓存样式 + styleCache.put(styleIndex, centeredStyle); + } + + // 应用居中样式 + cell.setCellStyle(centeredStyle); } } } @@ -112,32 +156,6 @@ public class CenterExcelUtil extends ExcelUtil { } } - /** - * 设置单元格居中样式 - */ - private void setCellCenterStyle(Workbook workbook, Cell cell) { - // 获取当前样式 - CellStyle currentStyle = cell.getCellStyle(); - - // 创建新样式 - CellStyle newStyle = workbook.createCellStyle(); - - // 复制原有样式 - newStyle.cloneStyleFrom(currentStyle); - - // 设置水平居中 - newStyle.setAlignment(HorizontalAlignment.CENTER); - newStyle.setVerticalAlignment(VerticalAlignment.CENTER); - - // 保持原有的数据格式 - if (currentStyle.getDataFormatString() != null) { - newStyle.setDataFormat(Short.parseShort(currentStyle.getDataFormatString())); - } - - // 应用新样式 - cell.setCellStyle(newStyle); - } - /** * 设置响应头 */