package com.ruoyi.common.utils.excel; import com.alibaba.excel.metadata.Head; import com.alibaba.excel.metadata.data.CellData; import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.write.handler.CellWriteHandler; import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; import com.alibaba.excel.write.metadata.holder.WriteTableHolder; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Sheet; import java.util.HashMap; import java.util.List; import java.util.Map; /** * 完全自定义自适应列宽处理器 */ public class FullCustomAutoWidthHandler implements CellWriteHandler { // 存储每列最大宽度(字符) private final Map columnMaxWidth = new HashMap<>(); // 配置每列的特殊规则(如第0列最大宽度20) private final Map columnMaxWidthRules; private final int defaultMaxWidth; private final int defaultMinWidth; public FullCustomAutoWidthHandler() { this(new HashMap<>(), 30, 8); } public FullCustomAutoWidthHandler(Map columnMaxWidthRules, int defaultMaxWidth, int defaultMinWidth) { this.columnMaxWidthRules = columnMaxWidthRules; this.defaultMaxWidth = defaultMaxWidth; this.defaultMinWidth = defaultMinWidth; } @Override public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { int columnIndex = cell.getColumnIndex(); String cellValue = cell.getStringCellValue(); int contentWidth = calculateStringWidth(cellValue); // 更新最大宽度 columnMaxWidth.put(columnIndex, Math.max(columnMaxWidth.getOrDefault(columnIndex, 0), contentWidth)); // 所有数据写入完成后设置列宽(最后一行处理时) Sheet sheet = writeSheetHolder.getSheet(); if (cell.getRowIndex() == sheet.getLastRowNum()) { int finalWidth = columnMaxWidth.get(columnIndex); // 应用特殊规则或默认规则 int maxWidth = columnMaxWidthRules.getOrDefault(columnIndex, defaultMaxWidth); finalWidth = Math.min(finalWidth, maxWidth); finalWidth = Math.max(finalWidth, defaultMinWidth); sheet.setColumnWidth(columnIndex, finalWidth * 256); } } /** * 计算字符串显示宽度(中文算2字符,英文/数字算1字符) */ private int calculateStringWidth(String value) { if (value == null || value.isEmpty()) return 0; int width = 0; for (char c : value.toCharArray()) { width += (c > 255) ? 2 : 1; // 中文占2字符,英文占1字符 } return width + 2; // 额外加2字符的边距,避免内容溢出 } }