| | |
| | | import org.apache.poi.ss.usermodel.*; |
| | | import org.apache.poi.ss.util.CellRangeAddress; |
| | | import org.apache.poi.ss.util.CellRangeAddressList; |
| | | import org.apache.poi.xssf.streaming.SXSSFWorkbook; |
| | | import org.apache.poi.xssf.usermodel.XSSFClientAnchor; |
| | | import org.apache.poi.xssf.usermodel.XSSFDataValidation; |
| | | import org.apache.poi.hssf.usermodel.HSSFClientAnchor; |
| | | import org.apache.poi.hssf.usermodel.HSSFDataValidation; |
| | | import org.apache.poi.hssf.usermodel.HSSFWorkbook; |
| | | import org.apache.poi.hssf.usermodel.HSSFClientAnchor; |
| | | import org.apache.poi.hssf.usermodel.HSSFDataValidation; |
| | | import org.apache.poi.hssf.usermodel.HSSFWorkbook; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | |
| | |
| | | int column = 0; |
| | | if(index == 0) { |
| | | // 合并第一行的前5个单元格 |
| | | sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 7)); |
| | | sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 6)); |
| | | |
| | | // 创建行并设置高度 |
| | | row = sheet.createRow(0); |
| | | row.setHeight((short)(40 * 40)); |
| | | row.setHeight((short)(20 * 20)); |
| | | |
| | | |
| | | // sheet.addMergedRegion(new CellRangeAddress(1, 1, 0, 7)); |
| | |
| | | CellStyle style = wb.createCellStyle(); |
| | | Font font = wb.createFont(); |
| | | font.setBold(true); |
| | | font.setFontHeightInPoints((short) 12); |
| | | |
| | | font.setFontName("宋体"); |
| | | style.setFont(font); |
| | | style.setAlignment(HorizontalAlignment.CENTER); |
| | |
| | | row = sheet.createRow(1); |
| | | // |
| | | row.createCell(0).setCellValue("ISO编号:"); |
| | | row.createCell(1).setCellValue(list.get(0).getIos5()); |
| | | // row.createCell(4).setCellValue("档号:"); |
| | | //拿到档号 |
| | | row.createCell(5).setCellValue(""); |
| | |
| | | CellStyle style = wb.createCellStyle(); |
| | | style.setAlignment(HorizontalAlignment.CENTER); |
| | | style.setVerticalAlignment(VerticalAlignment.CENTER); |
| | | // 设置单元格内容自动换行 |
| | | style.setWrapText(true); |
| | | style.setBorderRight(BorderStyle.THIN); |
| | | style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); |
| | | style.setBorderLeft(BorderStyle.THIN); |
| | |
| | | style.setFont(dataFont); |
| | | styles.put("data", style); |
| | | |
| | | style = wb.createCellStyle(); |
| | | style.cloneStyleFrom(styles.get("data")); |
| | | style.setAlignment(HorizontalAlignment.CENTER); |
| | | style.setVerticalAlignment(VerticalAlignment.CENTER); |
| | | style.setFillForegroundColor(IndexedColors.GREY_50_PERCENT.getIndex()); |
| | | style.setFillPattern(FillPatternType.SOLID_FOREGROUND); |
| | | Font headerFont = wb.createFont(); |
| | | headerFont.setFontName("Arial"); |
| | | headerFont.setFontHeightInPoints((short) 10); |
| | | headerFont.setBold(true); |
| | | headerFont.setColor(IndexedColors.WHITE.getIndex()); |
| | | style.setFont(headerFont); |
| | | styles.put("header", style); |
| | | // 创建表头样式映射,根据Excel注解动态生成 |
| | | Map<String, CellStyle> headerStyles = new HashMap<String, CellStyle>(); |
| | | for (Object[] os : fields) |
| | | { |
| | | Excel excel = (Excel) os[1]; |
| | | String key = StringUtils.format("header_{}_{}", excel.headerColor(), excel.headerBackgroundColor()); |
| | | if (!headerStyles.containsKey(key)) |
| | | { |
| | | style = wb.createCellStyle(); |
| | | style.cloneStyleFrom(styles.get("data")); |
| | | style.setAlignment(HorizontalAlignment.CENTER); |
| | | style.setVerticalAlignment(VerticalAlignment.CENTER); |
| | | // 设置单元格内容自动换行 |
| | | style.setWrapText(true); |
| | | // 根据注解设置表头背景色 - 已注释,表头不显示背景色 |
| | | /*if (excel.headerBackgroundColor() != IndexedColors.WHITE) { |
| | | style.setFillForegroundColor(excel.headerBackgroundColor().index); |
| | | style.setFillPattern(FillPatternType.SOLID_FOREGROUND); |
| | | }*/ |
| | | Font headerFont = wb.createFont(); |
| | | headerFont.setFontName("Arial"); |
| | | headerFont.setFontHeightInPoints((short) 10); |
| | | headerFont.setBold(false); |
| | | headerFont.setColor(excel.headerColor().index); |
| | | style.setFont(headerFont); |
| | | headerStyles.put(key, style); |
| | | } |
| | | } |
| | | styles.putAll(headerStyles); |
| | | |
| | | style = wb.createCellStyle(); |
| | | style.setAlignment(HorizontalAlignment.CENTER); |
| | | style.setVerticalAlignment(VerticalAlignment.CENTER); |
| | | // 设置单元格内容自动换行 |
| | | style.setWrapText(true); |
| | | Font totalFont = wb.createFont(); |
| | | totalFont.setFontName("Arial"); |
| | | totalFont.setFontHeightInPoints((short) 10); |
| | |
| | | style = wb.createCellStyle(); |
| | | style.cloneStyleFrom(styles.get("data")); |
| | | style.setAlignment(HorizontalAlignment.LEFT); |
| | | // 设置单元格内容自动换行 |
| | | style.setWrapText(true); |
| | | styles.put("data1", style); |
| | | |
| | | style = wb.createCellStyle(); |
| | | style.cloneStyleFrom(styles.get("data")); |
| | | style.setAlignment(HorizontalAlignment.CENTER); |
| | | // 设置单元格内容自动换行 |
| | | style.setWrapText(true); |
| | | styles.put("data2", style); |
| | | |
| | | style = wb.createCellStyle(); |
| | | style.cloneStyleFrom(styles.get("data")); |
| | | style.setAlignment(HorizontalAlignment.RIGHT); |
| | | // 设置单元格内容自动换行 |
| | | style.setWrapText(true); |
| | | styles.put("data3", style); |
| | | |
| | | return styles; |
| | |
| | | // 写入列信息 |
| | | cell.setCellValue(attr.name()); |
| | | setDataValidation(attr, row, column); |
| | | cell.setCellStyle(styles.get("header")); |
| | | // 根据Excel注解动态选择表头样式 |
| | | String key = StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor()); |
| | | cell.setCellStyle(styles.get(key)); |
| | | return cell; |
| | | } |
| | | |
| | |
| | | } else if (Excel.ColumnType.NUMERIC == attr.cellType()) { |
| | | cell.setCellValue(StringUtils.contains(Convert.toStr(value), ".") ? Convert.toDouble(value) : Convert.toInt(value)); |
| | | } else if (Excel.ColumnType.IMAGE == attr.cellType()) { |
| | | ClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, (short) cell.getColumnIndex(), cell.getRow().getRowNum(), (short) (cell.getColumnIndex() + 1), |
| | | ClientAnchor anchor = new HSSFClientAnchor(0, 0, 0, 0, (short) cell.getColumnIndex(), cell.getRow().getRowNum(), (short) (cell.getColumnIndex() + 1), |
| | | cell.getRow().getRowNum() + 1); |
| | | String imagePath = Convert.toStr(value); |
| | | if (StringUtils.isNotEmpty(imagePath)) { |
| | |
| | | // 如果设置了提示信息则鼠标放上去提示. |
| | | if (StringUtils.isNotEmpty(attr.prompt())) { |
| | | // 这里默认设了2-101列提示. |
| | | setXSSFPrompt(sheet, "", attr.prompt(), 1, 100, column, column); |
| | | setHSSFPrompt(sheet, "", attr.prompt(), 1, 100, column, column); |
| | | } |
| | | // 如果设置了combo属性则本列只能选择不能输入 |
| | | if (attr.combo().length > 0) { |
| | | // 这里默认设了2-101列只能选择不能输入. |
| | | setXSSFValidation(sheet, attr.combo(), 1, 100, column, column); |
| | | setHSSFValidation(sheet, attr.combo(), 1, 100, column, column); |
| | | } |
| | | } |
| | | |
| | |
| | | public Cell addCell(Excel attr, Row row, T vo, Field field, int column) { |
| | | Cell cell = null; |
| | | try { |
| | | // 设置行高 |
| | | row.setHeight(maxHeight); |
| | | // 设置行高为自动调整 |
| | | // row.setHeight((short) -1); |
| | | // 根据Excel中设置情况决定是否导出,有些情况需要保持为空,希望用户填写这一列. |
| | | if (attr.isExport()) { |
| | | // 创建cell |
| | | cell = row.createCell(column); |
| | | // attr.align(); |
| | | // int align = attr.align().value; |
| | | // cell.setCellStyle(styles.get("data" + (align >= 1 && align <= 3 ? align : ""))); |
| | | // 设置单元格样式 |
| | | HorizontalAlignment align = attr.align(); |
| | | String styleKey = "data"; |
| | | if (align == HorizontalAlignment.LEFT) { |
| | | styleKey = "data1"; |
| | | } else if (align == HorizontalAlignment.CENTER) { |
| | | styleKey = "data2"; |
| | | } else if (align == HorizontalAlignment.RIGHT) { |
| | | styleKey = "data3"; |
| | | } |
| | | // 获取并修改样式 |
| | | CellStyle style = styles.get(styleKey); |
| | | Workbook workbook = row.getSheet().getWorkbook(); |
| | | CellStyle newStyle = workbook.createCellStyle(); |
| | | newStyle.cloneStyleFrom(style); |
| | | newStyle.setWrapText(true); // 关键:启用自动换行 |
| | | cell.setCellStyle(newStyle); |
| | | |
| | | // 用于读取对象中的属性 |
| | | Object value = getTargetValue(vo, field, attr); |
| | |
| | | // 设置列类型 |
| | | setCellVo(value, attr, cell); |
| | | } |
| | | adjustRowHeightAfterSetValue(row, cell, value); |
| | | |
| | | addStatisticsData(column, Convert.toStr(value), attr); |
| | | } |
| | | } catch (Exception e) { |
| | |
| | | } |
| | | return cell; |
| | | } |
| | | /** |
| | | * 设置值后调整行高 |
| | | */ |
| | | private void adjustRowHeightAfterSetValue(Row row, Cell cell, Object value) { |
| | | if (value == null) return; |
| | | |
| | | String text = value.toString(); |
| | | Sheet sheet = row.getSheet(); |
| | | |
| | | // 1. 计算自动高度(基于内容) |
| | | short autoHeight = calculateSimpleAutoHeight(text, cell); |
| | | |
| | | // 2. 获取当前行高 |
| | | short currentHeight = row.getHeight(); |
| | | if (currentHeight == -1) { |
| | | currentHeight = sheet.getDefaultRowHeight(); |
| | | } |
| | | |
| | | // 3. 使用较大的高度(自动计算的高度或当前高度) |
| | | short baseHeight = (short) Math.max(currentHeight, autoHeight); |
| | | System.out.println(baseHeight+"aaaaaaaaatttttttt"); |
| | | // 4. 在基础上增加额外高度(100单位 = 5点) |
| | | short extraHeight = 80; |
| | | short newHeight = (short) (baseHeight + extraHeight); |
| | | |
| | | // 5. 限制最大高度 |
| | | short maxHeight = (short) 4000; // 100点 |
| | | row.setHeight((short) Math.min(maxHeight,newHeight)); |
| | | } |
| | | |
| | | /** |
| | | * 设置 POI XSSFSheet 单元格提示 |
| | | * 简化的自动高度计算 |
| | | */ |
| | | private short calculateSimpleAutoHeight(String text, Cell cell) { |
| | | if (text == null || text.isEmpty()) return 0; |
| | | |
| | | Sheet sheet = cell.getSheet(); |
| | | int colIndex = cell.getColumnIndex(); |
| | | |
| | | // 获取列宽(字符数) |
| | | int colWidthChars = sheet.getColumnWidth(colIndex) / 256; |
| | | if (colWidthChars <= 0) colWidthChars = 10; |
| | | |
| | | // 计算文本行数 |
| | | int lines = 1; |
| | | if (text.contains("\n")) { |
| | | // 有显式换行 |
| | | String[] parts = text.split("\n"); |
| | | for (String part : parts) { |
| | | lines += Math.max(1, (int) Math.ceil(part.length() * 1.5 / colWidthChars)); |
| | | } |
| | | } else { |
| | | // 自动换行 |
| | | lines = (int) Math.ceil(text.length() * 1.5 / colWidthChars); |
| | | } |
| | | |
| | | // 每行高度:假设18点(360 POI单位) |
| | | return (short) (lines * 360); |
| | | } |
| | | /** |
| | | * 设置 POI HSSFSheet 单元格提示 |
| | | * |
| | | * @param sheet 表单 |
| | | * @param promptTitle 提示标题 |
| | |
| | | * @param firstCol 开始列 |
| | | * @param endCol 结束列 |
| | | */ |
| | | public void setXSSFPrompt(Sheet sheet, String promptTitle, String promptContent, int firstRow, int endRow, |
| | | public void setHSSFPrompt(Sheet sheet, String promptTitle, String promptContent, int firstRow, int endRow, |
| | | int firstCol, int endCol) { |
| | | DataValidationHelper helper = sheet.getDataValidationHelper(); |
| | | DataValidationConstraint constraint = helper.createCustomConstraint("DD1"); |
| | |
| | | * @param endCol 结束列 |
| | | * @return 设置好的sheet. |
| | | */ |
| | | public void setXSSFValidation(Sheet sheet, String[] textlist, int firstRow, int endRow, int firstCol, int endCol) { |
| | | public void setHSSFValidation(Sheet sheet, String[] textlist, int firstRow, int endRow, int firstCol, int endCol) { |
| | | DataValidationHelper helper = sheet.getDataValidationHelper(); |
| | | // 加载下拉列表内容 |
| | | DataValidationConstraint constraint = helper.createExplicitListConstraint(textlist); |
| | |
| | | // 数据有效性对象 |
| | | DataValidation dataValidation = helper.createValidation(constraint, regions); |
| | | // 处理Excel兼容性问题 |
| | | if (dataValidation instanceof XSSFDataValidation) { |
| | | dataValidation.setSuppressDropDownArrow(true); |
| | | dataValidation.setShowErrorBox(true); |
| | | } else { |
| | | if (dataValidation instanceof HSSFDataValidation) { |
| | | dataValidation.setSuppressDropDownArrow(false); |
| | | dataValidation.setShowErrorBox(true); |
| | | } |
| | | |
| | | sheet.addValidationData(dataValidation); |
| | |
| | | * 创建一个工作簿 |
| | | */ |
| | | public void createWorkbook() { |
| | | this.wb = new SXSSFWorkbook(500); |
| | | this.wb = new HSSFWorkbook(); |
| | | } |
| | | |
| | | /** |