package cn.net.connor.plm.util; import java.io.FileOutputStream; import java.util.List; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.BorderStyle; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.Font; import org.apache.poi.ss.usermodel.HorizontalAlignment; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.VerticalAlignment; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.util.CellRangeAddress; import cn.net.connor.plm.entity.Prop; public class ExcelWriteTable2 { public static void generateFromTemplateStructure(String outputPath, List props) throws Exception { try (Workbook workbook = new HSSFWorkbook()) { Sheet sheet = workbook.createSheet("sheet1"); // ====================== 创建固定表头 ====================== createHeader(workbook, sheet); // ====================== 创建数据区域 ====================== int rowNum = 2; // 数据起始行(第三行) for (int i = 0; i < props.size(); i++) { Prop prop = props.get(i); // 创建四行数据(合并行) Row row1 = sheet.createRow(rowNum++); Row row2 = sheet.createRow(rowNum++); Row row3 = sheet.createRow(rowNum++); Row row4 = sheet.createRow(rowNum++); // 设置行高为 16.8 磅(336 单位) row1.setHeight((short) 336); row2.setHeight((short) 336); row3.setHeight((short) 336); row4.setHeight((short) 336); // 设置行高为 16.8 磅(336 单位) row1.setHeight((short) 336); row2.setHeight((short) 336); // ====================== 填充动态数据 ====================== fillDynamicData(workbook, row1, prop, i + 1); setRow2Style(workbook, row2); setRow2Style(workbook, row3); setRow2Style(workbook, row4); // ====================== 创建固定模板内容 ====================== createFixedContent(workbook, row1, row2, row3, row4); // ====================== 设置合并区域 ====================== addMergedRegions(sheet, row1, row2, row3, row4); } // ====================== 自动调整列宽 ====================== autoSizeColumns(sheet); // 保存文件 try (FileOutputStream fos = new FileOutputStream(outputPath)) { workbook.write(fos); } } } private static void setRow2Style(Workbook workbook, Row row2) { CellStyle dataStyle = createDataStyle(workbook); for (int i = 0; i < 8; i++) { Cell cell = row2.createCell(i); cell.setCellStyle(dataStyle); } for (int i = 14; i < 18; i++) { Cell cell = row2.createCell(i); cell.setCellStyle(dataStyle); } } private static void createHeader(Workbook workbook, Sheet sheet) { // 第一行标题 Row titleRow = sheet.createRow(0); titleRow.setHeight((short) 436); Cell titleCell = titleRow.createCell(0); titleCell.setCellValue( "\u6280\u672F/\u5DE5\u827A\u3010\u53D8\u66F4\u3011\u53D1\u653E\u3001\u56DE\u6536\u8BB0\u5F55\u8868"); sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 17)); // 创建带实线边框的标题样式 CellStyle headerStyle = workbook.createCellStyle(); Font titleFont = workbook.createFont(); titleFont.setBold(true); titleFont.setFontHeightInPoints((short) 14); headerStyle.setFont(titleFont); headerStyle.setAlignment(HorizontalAlignment.CENTER); headerStyle.setVerticalAlignment(VerticalAlignment.CENTER); // 设置实线边框 headerStyle.setBorderTop(BorderStyle.THIN); headerStyle.setBorderBottom(BorderStyle.THIN); headerStyle.setBorderLeft(BorderStyle.THIN); headerStyle.setBorderRight(BorderStyle.THIN); // 应用样式到合并后的标题单元格 titleCell.setCellStyle(headerStyle); // 单独创建第二行表头的样式 CellStyle secondHeaderStyle = workbook.createCellStyle(); Font secondHeaderFont = workbook.createFont(); secondHeaderFont.setBold(true); secondHeaderFont.setFontHeightInPoints((short) 10); secondHeaderStyle.setFont(secondHeaderFont); secondHeaderStyle.setAlignment(HorizontalAlignment.CENTER); secondHeaderStyle.setVerticalAlignment(VerticalAlignment.CENTER); secondHeaderStyle.setWrapText(true); // 允许换行 // 设置实线边框 secondHeaderStyle.setBorderTop(BorderStyle.THIN); secondHeaderStyle.setBorderBottom(BorderStyle.THIN); secondHeaderStyle.setBorderLeft(BorderStyle.THIN); secondHeaderStyle.setBorderRight(BorderStyle.THIN); // 第二行表头 Row headerRow = sheet.createRow(1); headerRow.setHeight((short) 556); String[] headers = { "\u5E8F\u53F7", "\u6587\u4EF6\u540D\u79F0", "\u4EA7\u54C1/\u96F6\u90E8\u4EF6\u540D\u79F0", "\u4EA7\u54C1/\u96F6\u90E8\u4EF6\u56FE\u53F7", "\u540C\u65F6\u4E0B\u53D1\u56FE\u7EB8", "\u56FE\u7EB8\u72B6\u6001/\u7248\u672C", "\u7F16\u5236\u4EBA", "\u9875\u6570", "\u2714 \u7B7E\u6536\u90E8\u95E8", "", "", "", "", "", "\u7B7E\u6536\u65E5\u671F", "\u6587\u4EF6\u7F16\u53F7", "\u5907\u6CE8", "" }; for (int i = 0; i < headers.length; i++) { Cell cell = headerRow.createCell(i); cell.setCellValue(headers[i]); cell.setCellStyle(secondHeaderStyle); } sheet.addMergedRegion(new CellRangeAddress(1, 1, 8, 13)); sheet.addMergedRegion(new CellRangeAddress(1, 1, 16, 17)); } private static void fillDynamicData(Workbook workbook, Row row, Prop prop, int serialNumber) { CellStyle dataStyle = createDataStyle(workbook); // 序号(A列) createStyledCell(row, 0, String.valueOf(serialNumber), dataStyle); // 动态字段 createStyledCell(row, 1, prop.getFileName(), dataStyle); createStyledCell(row, 2, prop.getProductName(), dataStyle); createStyledCell(row, 3, prop.getProductDrawingNum(), dataStyle); createStyledCell(row, 4, prop.getDrawingStatus(), dataStyle); createStyledCell(row, 5, prop.getDrawingRevision(), dataStyle); createStyledCell(row, 6, prop.getCompiler(), dataStyle); createStyledCell(row, 14, prop.getDrawingDate(), dataStyle); // O列 createStyledCell(row, 15, prop.getRelationFileNo(), dataStyle); // P列 } private static void createFixedContent(Workbook workbook, Row row1, Row row2, Row row3, Row row4) { CellStyle fixedStyle = createFixedStyle(workbook); CellStyle dataStyle = createDataStyle(workbook); // H列固定内容(合并单元格) createStyledCell(row1, 7, "1", dataStyle); // I-N列固定模板 // I-N列固定模板(按行分配) String[][] fixedRows = { { "", "\u91C7\u8D2D\u90E8:", "", "PMC\u90E8:", "", "\u751F\u4EA7\u90E8:" }, { "", "\u5DE5\u827A\u90E8:", "", "\u8D28\u4FDD\u90E8\uFF1A", "", "SQE:" }, { "", "\u56FD\u96451\u90E8:", "", "\u56FD\u96452\u90E8:", "", "\u9500\u552E:" }, { "", "\u96F6\u552E:", "", "\u8BD5\u9A8C\u5BA4:", "", "\u7EFC\u7BA1:" } }; int colIndex = 8; // I列开始 for (int i = 0; i < fixedRows.length; i++) { Row currentRow = null; switch (i) { case 0: currentRow = row1; break; case 1: currentRow = row2; break; case 2: currentRow = row3; break; case 3: currentRow = row4; break; } if (currentRow != null) { for (int j = 0; j < fixedRows[i].length; j++) { createStyledCell(currentRow, colIndex + j, fixedRows[i][j], fixedStyle); } } } // Q-R列固定内容 createStyledCell(row1, 16, "", dataStyle); createStyledCell(row1, 17, "", dataStyle); } private static void addMergedRegions(Sheet sheet, Row row1, Row row2, Row row3, Row row4) { int startRow = row1.getRowNum(); int endRow = row4.getRowNum(); // 合并 A-H 列(索引 0-7) for (int i = 0; i < 8; i++) { sheet.addMergedRegion(new CellRangeAddress(startRow, endRow, i, i)); } // 合并 O-R 列(索引 14-15) for (int i = 14; i < 16; i++) { sheet.addMergedRegion(new CellRangeAddress(startRow, endRow, i, i)); } sheet.addMergedRegion(new CellRangeAddress(startRow, endRow, 16, 17)); } private static CellStyle createFixedStyle(Workbook workbook) { CellStyle style = workbook.createCellStyle(); style.setBorderTop(BorderStyle.THIN); style.setBorderBottom(BorderStyle.THIN); style.setBorderLeft(BorderStyle.THIN); style.setBorderRight(BorderStyle.THIN); return style; } private static CellStyle createDataStyle(Workbook workbook) { CellStyle style = workbook.createCellStyle(); Font dataFont = workbook.createFont(); dataFont.setFontHeightInPoints((short) 10); style.setBorderTop(BorderStyle.THIN); style.setBorderBottom(BorderStyle.THIN); style.setBorderLeft(BorderStyle.THIN); style.setBorderRight(BorderStyle.THIN); style.setVerticalAlignment(VerticalAlignment.CENTER); style.setAlignment(HorizontalAlignment.CENTER); style.setVerticalAlignment(VerticalAlignment.CENTER); style.setFont(dataFont); return style; } private static void createStyledCell(Row row, int column, String value, CellStyle style) { Cell cell = row.createCell(column); cell.setCellValue(value); cell.setCellStyle(style); } private static void autoSizeColumns(Sheet sheet) { for (int i = 0; i < 18; i++) { if (i == 8 || i == 10 || i == 12) { sheet.setColumnWidth(i, 5 * 256); } else { sheet.setColumnWidth(i, 10 * 256); } } } }