commit
06c3f0f11c
17 changed files with 729 additions and 130 deletions
@ -0,0 +1,279 @@ |
||||
package org.springblade.desk.quality.util; |
||||
|
||||
import jakarta.servlet.http.HttpServletResponse; |
||||
import org.apache.poi.ss.usermodel.*; |
||||
import org.apache.poi.ss.util.CellRangeAddress; |
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook; |
||||
import org.springblade.desk.dashboard.utils.DateUtils; |
||||
import org.springblade.desk.quality.pojo.vo.LiquidTankTaskCopyVO; |
||||
|
||||
import java.io.OutputStream; |
||||
import java.net.URLEncoder; |
||||
import java.time.format.DateTimeFormatter; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
public class FullMergeExcelUtil { |
||||
|
||||
/** |
||||
* 导出带合并标头+数据合并的Excel(User实体类版本) |
||||
* @param response 响应对象 |
||||
* @param fileName 导出文件名 |
||||
* @param mergeTitle 合并标头的大标题 |
||||
* @param columnTitles 列标题数组(["部门","用户ID","用户名","年龄","手机号"]) |
||||
* @param userList 用户实体类列表 |
||||
* @param mergeColumnIndexes 需要合并的列索引(如[0]表示合并部门列) |
||||
* @throws Exception 异常 |
||||
*/ |
||||
public static void exportUserExcel(HttpServletResponse response, String fileName, |
||||
String mergeTitle, String[] columnTitles, |
||||
List<LiquidTankTaskCopyVO> userList, int[] mergeColumnIndexes) throws Exception { |
||||
// 1. 创建工作簿和工作表
|
||||
Workbook workbook = new XSSFWorkbook(); |
||||
Sheet sheet = workbook.createSheet("数据报表"); |
||||
// 设置列宽
|
||||
for (int i = 0; i < columnTitles.length; i++) { |
||||
sheet.autoSizeColumn(i); |
||||
sheet.setColumnWidth(i, Math.max(sheet.getColumnWidth(i), 2000)); |
||||
} |
||||
|
||||
// -------------------------- 第一步:创建合并标头 --------------------------
|
||||
Row mergeTitleRow = sheet.createRow(0); |
||||
mergeTitleRow.setHeightInPoints(30); |
||||
Cell mergeTitleCell = mergeTitleRow.createCell(0); |
||||
mergeTitleCell.setCellValue(mergeTitle); |
||||
CellStyle mergeTitleStyle = createStyle(workbook, true, (short) 16, HorizontalAlignment.CENTER); |
||||
mergeTitleCell.setCellStyle(mergeTitleStyle); |
||||
sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, columnTitles.length - 1)); |
||||
|
||||
// -------------------------- 第二步:创建列标题 --------------------------
|
||||
Row columnTitleRow = sheet.createRow(1); |
||||
columnTitleRow.setHeightInPoints(20); |
||||
CellStyle columnTitleStyle = createStyle(workbook, true, (short) 12, HorizontalAlignment.CENTER); |
||||
for (int i = 0; i < columnTitles.length; i++) { |
||||
Cell cell = columnTitleRow.createCell(i); |
||||
cell.setCellValue(columnTitles[i]); |
||||
cell.setCellStyle(columnTitleStyle); |
||||
sheet.autoSizeColumn(i); |
||||
} |
||||
|
||||
// -------------------------- 第三步:填充User实体数据 --------------------------
|
||||
int dataStartRow = 2; |
||||
CellStyle dataStyle = createStyle(workbook, false, (short) 12, HorizontalAlignment.CENTER); |
||||
for (int i = 0; i < userList.size(); i++) { |
||||
Row dataRow = sheet.createRow(dataStartRow + i); |
||||
dataRow.setHeightInPoints(20); |
||||
LiquidTankTaskCopyVO user = userList.get(i); |
||||
|
||||
// 手动映射:列索引 → User字段(与columnTitles一一对应)
|
||||
// 取样时间
|
||||
int a = 0; |
||||
Cell cell0 = dataRow.createCell(a); |
||||
cell0.setCellStyle(dataStyle); |
||||
cell0.setCellValue(user.getSampleDate()); |
||||
|
||||
//温度
|
||||
int b = 1; |
||||
Cell cell1 = dataRow.createCell(b); |
||||
cell1.setCellStyle(dataStyle); |
||||
cell1.setCellValue(user.getTemperatureActual()); |
||||
|
||||
//槽号
|
||||
int c = 2; |
||||
Cell cell2 = dataRow.createCell(c); |
||||
// cell2.setCellStyle(dataStyle);
|
||||
cell2.setCellValue(user.getWorkTankName() == null ? "" : user.getWorkTankName()); |
||||
|
||||
//体积(L)
|
||||
int d = 3; |
||||
Cell cell3 = dataRow.createCell(d); |
||||
// cell3.setCellStyle(dataStyle);
|
||||
cell3.setCellValue(user.getVolume() == null ? 0 : user.getVolume()); |
||||
|
||||
//分析项目
|
||||
Cell cell4 = dataRow.createCell(4); |
||||
cell4.setCellStyle(dataStyle); |
||||
cell4.setCellValue(user.getTestElement() == null ? "" : user.getTestElement()); |
||||
|
||||
//规范下限(g/L)
|
||||
Cell cell5 = dataRow.createCell(5); |
||||
cell5.setCellStyle(dataStyle); |
||||
cell5.setCellValue(user.getNormValueMin() == null ? 0 : user.getNormValueMin()); |
||||
|
||||
//目标下限(g/L)
|
||||
Cell cell6 = dataRow.createCell(6); |
||||
cell6.setCellStyle(dataStyle); |
||||
cell6.setCellValue(user.getTargetValueMin() == null ? 0 : user.getTargetValueMin()); |
||||
|
||||
//添加点(g/L)
|
||||
Cell cell7 = dataRow.createCell(7); |
||||
cell7.setCellStyle(dataStyle); |
||||
cell7.setCellValue(user.getFillingLocation() == null ? 0 : user.getFillingLocation()); |
||||
|
||||
//目标值(g/L)
|
||||
Cell cell8 = dataRow.createCell(8); |
||||
cell8.setCellStyle(dataStyle); |
||||
cell8.setCellValue(user.getTargetValue() == null ? 0 : user.getTargetValue()); |
||||
|
||||
//目标上限(g/L)
|
||||
Cell cell9 = dataRow.createCell(9); |
||||
cell9.setCellStyle(dataStyle); |
||||
cell9.setCellValue(user.getTargetValueMax() == null ? 0 : user.getTargetValueMax()); |
||||
|
||||
//规范上限(g/L)
|
||||
Cell cell10 = dataRow.createCell(10); |
||||
cell10.setCellStyle(dataStyle); |
||||
cell10.setCellValue(user.getNormValueMax() == null ? 0 : user.getNormValueMax()); |
||||
|
||||
//化验频率
|
||||
Cell cell11 = dataRow.createCell(11); |
||||
cell11.setCellStyle(dataStyle); |
||||
cell11.setCellValue(user.getTestFrequency() == null ? "" : user.getTestFrequency()); |
||||
|
||||
//化验值(g/L)
|
||||
Cell cell12 = dataRow.createCell(12); |
||||
cell12.setCellStyle(dataStyle); |
||||
cell12.setCellValue(user.getFirstTestValue() == null ? 0 : user.getFirstTestValue()); |
||||
|
||||
//药品计算公式
|
||||
Cell cell13 = dataRow.createCell(13); |
||||
cell13.setCellStyle(dataStyle); |
||||
cell13.setCellValue(user.getReportFormulaContent() == null ? "" : user.getReportFormulaContent()); |
||||
|
||||
//药品添加量
|
||||
Cell cell14 = dataRow.createCell(14); |
||||
cell14.setCellStyle(dataStyle); |
||||
cell14.setCellValue(user.getActualAddValue() == null ? 0 : user.getActualAddValue()); |
||||
|
||||
//药品批次号
|
||||
Cell cell15 = dataRow.createCell(15); |
||||
cell15.setCellStyle(dataStyle); |
||||
cell15.setCellValue(user.getDrugBatCode() == null ? "" : user.getDrugBatCode()); |
||||
|
||||
//药品监督员签名
|
||||
Cell cell16 = dataRow.createCell(16); |
||||
cell16.setCellStyle(dataStyle); |
||||
cell16.setCellValue(user.getDrugSuUserSign()== null ? "" : user.getDrugSuUserSign()); |
||||
|
||||
//药品添加人签名
|
||||
Cell cell17 = dataRow.createCell(17); |
||||
cell17.setCellStyle(dataStyle); |
||||
cell17.setCellValue(user.getDrugAddUserSign()== null ? "" : user.getDrugAddUserSign()); |
||||
|
||||
//调整后化验值(g/L)
|
||||
Cell cell18 = dataRow.createCell(18); |
||||
cell18.setCellStyle(dataStyle); |
||||
cell18.setCellValue(user.getRepeatTestValue()== null ? 0 : user.getRepeatTestValue()); |
||||
|
||||
//1\合格 2、不合格
|
||||
Cell cell19 = dataRow.createCell(19); |
||||
cell19.setCellStyle(dataStyle); |
||||
cell19.setCellValue(user.getQualified()== null ? 0 : user.getQualified()); |
||||
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); |
||||
//有效期
|
||||
Cell cell20 = dataRow.createCell(20); |
||||
cell20.setCellStyle(dataStyle); |
||||
cell20.setCellValue(user.getValidDate().format(formatter)); |
||||
|
||||
//超出规范极限调整后的结果
|
||||
Cell cell21 = dataRow.createCell(21); |
||||
cell21.setCellStyle(dataStyle); |
||||
cell21.setCellValue(user.getOutRangeResult()==null ? "" : user.getOutRangeResult()); |
||||
|
||||
//槽液清理记录
|
||||
Cell cell22 = dataRow.createCell(22); |
||||
cell22.setCellStyle(dataStyle); |
||||
cell22.setCellValue(user.getClearRecord()==null ? "" : user.getClearRecord()); |
||||
|
||||
//控制规范
|
||||
Cell cell23 = dataRow.createCell(23); |
||||
cell23.setCellStyle(dataStyle); |
||||
cell23.setCellValue(user.getNorm()==null ? "" : user.getNorm()); |
||||
} |
||||
|
||||
// -------------------------- 第四步:合并数据列相同值 --------------------------
|
||||
// if (mergeColumnIndexes != null && mergeColumnIndexes.length > 0 && userList.size() > 0) {
|
||||
// for (int colIndex : mergeColumnIndexes) {
|
||||
// if (colIndex < 0 || colIndex >= columnTitles.length) {
|
||||
// continue;
|
||||
// }
|
||||
// mergeSameValueCells(sheet, dataStartRow, dataStartRow + userList.size() - 1, colIndex);
|
||||
// }
|
||||
// }
|
||||
|
||||
// -------------------------- 第五步:响应头和文件输出 --------------------------
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); |
||||
response.setCharacterEncoding("UTF-8"); |
||||
String encodeFileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20"); |
||||
response.setHeader("Content-Disposition", "attachment;filename*=UTF-8''" + encodeFileName + ".xlsx"); |
||||
|
||||
OutputStream outputStream = response.getOutputStream(); |
||||
workbook.write(outputStream); |
||||
outputStream.flush(); |
||||
outputStream.close(); |
||||
workbook.close(); |
||||
} |
||||
|
||||
/** |
||||
* 合并指定列连续相同值的单元格(逻辑不变) |
||||
*/ |
||||
private static void mergeSameValueCells(Sheet sheet, int startRow, int endRow, int colIndex) { |
||||
int mergeStartRow = startRow; |
||||
for (int rowIndex = startRow + 1; rowIndex <= endRow; rowIndex++) { |
||||
String currentValue = getCellValue(sheet.getRow(rowIndex).getCell(colIndex)); |
||||
String prevValue = getCellValue(sheet.getRow(rowIndex - 1).getCell(colIndex)); |
||||
|
||||
if (!currentValue.equals(prevValue)) { |
||||
if (mergeStartRow < rowIndex - 1) { |
||||
sheet.addMergedRegion(new CellRangeAddress(mergeStartRow, rowIndex - 1, colIndex, colIndex)); |
||||
} |
||||
mergeStartRow = rowIndex; |
||||
} |
||||
|
||||
if (rowIndex == endRow && mergeStartRow <= endRow) { |
||||
sheet.addMergedRegion(new CellRangeAddress(mergeStartRow, endRow, colIndex, colIndex)); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 获取单元格字符串值(逻辑不变) |
||||
*/ |
||||
private static String getCellValue(Cell cell) { |
||||
if (cell == null) { |
||||
return ""; |
||||
} |
||||
switch (cell.getCellType()) { |
||||
case STRING: |
||||
return cell.getStringCellValue().trim(); |
||||
case NUMERIC: |
||||
return String.valueOf(cell.getNumericCellValue()).trim(); |
||||
case BOOLEAN: |
||||
return String.valueOf(cell.getBooleanCellValue()).trim(); |
||||
case FORMULA: |
||||
return cell.getCellFormula().trim(); |
||||
default: |
||||
return ""; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 创建样式(逻辑不变) |
||||
*/ |
||||
private static CellStyle createStyle(Workbook workbook, boolean isBold, short fontSize, HorizontalAlignment alignment) { |
||||
CellStyle style = workbook.createCellStyle(); |
||||
Font font = workbook.createFont(); |
||||
font.setBold(isBold); |
||||
font.setFontName("宋体"); |
||||
font.setFontHeightInPoints(fontSize); |
||||
style.setFont(font); |
||||
style.setAlignment(alignment); |
||||
style.setVerticalAlignment(VerticalAlignment.CENTER); |
||||
style.setBorderTop(BorderStyle.THIN); |
||||
style.setBorderBottom(BorderStyle.THIN); |
||||
style.setBorderLeft(BorderStyle.THIN); |
||||
style.setBorderRight(BorderStyle.THIN); |
||||
return style; |
||||
} |
||||
} |
||||
Binary file not shown.
Loading…
Reference in new issue