优化 excel导出列宽太大导致占满屏问题

This commit is contained in:
YuanFeng 2026-06-04 20:51:33 +08:00
parent 287afdc119
commit 531f3c6b29
3 changed files with 119 additions and 1 deletions

View File

@ -0,0 +1,115 @@
package cn.hangtag.framework.excel.core.handler;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.util.MapUtils;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.style.column.AbstractColumnWidthStyleStrategy;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.poi.ss.usermodel.Cell;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Excel 列宽自适应处理器
* 规则
* 1. 字段上加 @ColumnWidth 则使用注解宽度
* 2. 未加注解 自动计算宽度
* 3. 自动宽度不超过设定最大值
*/
public class OmsColumnWidthStyleStrategy extends AbstractColumnWidthStyleStrategy {
private final Map<Integer, Map<Integer, Integer>> cache = MapUtils.newHashMapWithExpectedSize(8);
private final int MAX_COLUMN_WIDTH;
// 缓存列index 注解指定宽度只解析一次
private final Map<Integer, Integer> annotatedWidthMap = new HashMap<>();
private boolean initialized = false;
public OmsColumnWidthStyleStrategy(int maxColumnWidth) {
MAX_COLUMN_WIDTH = maxColumnWidth;
}
@Override
protected void setColumnWidth(WriteSheetHolder writeSheetHolder, List<WriteCellData<?>> cellDataList, Cell cell,
Head head, Integer relativeRowIndex, Boolean isHead) {
if (!initialized && isHead && relativeRowIndex == 0) {
try {
Class<?> clazz = writeSheetHolder.getClazz(); // 这里才是真正的导出实体类
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);
ColumnWidth columnWidth = field.getAnnotation(ColumnWidth.class);
if (excelProperty != null && columnWidth != null) {
int index = excelProperty.index();
annotatedWidthMap.put(index, columnWidth.value());
}
}
} catch (Exception ignored) {
}
initialized = true;
}
boolean needSetWidth = isHead || !CollectionUtils.isEmpty(cellDataList);
if (!needSetWidth) {
return;
}
Integer columnIndex = cell.getColumnIndex();
// ===================== 优先使用注解宽度 =====================
if (annotatedWidthMap.containsKey(columnIndex)) {
Integer width = annotatedWidthMap.get(columnIndex);
writeSheetHolder.getSheet().setColumnWidth(columnIndex, width * 256);
return;
}
// ===================== 没有注解走自适应 =====================
Map<Integer, Integer> maxColumnWidthMap = cache.get(writeSheetHolder.getSheetNo());
if (maxColumnWidthMap == null) {
maxColumnWidthMap = new HashMap<>(16);
cache.put(writeSheetHolder.getSheetNo(), maxColumnWidthMap);
}
Integer columnWidth = dataLength(cellDataList, cell, isHead);
if (columnWidth < 0) {
return;
}
if (columnWidth > MAX_COLUMN_WIDTH) {
columnWidth = MAX_COLUMN_WIDTH;
}
Integer maxWidth = maxColumnWidthMap.get(columnIndex);
if (maxWidth == null || columnWidth > maxWidth) {
maxColumnWidthMap.put(columnIndex, columnWidth);
writeSheetHolder.getSheet().setColumnWidth(columnIndex, columnWidth * 256);
}
}
private Integer dataLength(List<WriteCellData<?>> cellDataList, Cell cell, Boolean isHead) {
if (isHead) {
return cell.getStringCellValue().getBytes().length;
}
WriteCellData<?> cellData = cellDataList.get(0);
CellDataTypeEnum type = cellData.getType();
if (type == null) {
return -1;
}
switch (type) {
case STRING:
return cellData.getStringValue().getBytes().length;
case BOOLEAN:
return cellData.getBooleanValue().toString().getBytes().length;
case NUMBER:
return cellData.getNumberValue().toString().getBytes().length;
default:
return -1;
}
}
}

View File

@ -1,5 +1,6 @@
package cn.hangtag.framework.excel.core.util;
import cn.hangtag.framework.excel.core.handler.OmsColumnWidthStyleStrategy;
import cn.hangtag.framework.excel.core.handler.SelectSheetWriteHandler;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.converters.longconverter.LongStringConverter;
@ -35,7 +36,7 @@ public class ExcelUtils {
// 输出 Excel
EasyExcel.write(response.getOutputStream(), head)
.autoCloseStream(false) // 不要自动关闭交给 Servlet 自己处理
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 基于 column 长度自动适配最大 255 宽度
.registerWriteHandler(new OmsColumnWidthStyleStrategy(80)) // 基于 column 长度自动适配最大 80 宽度
.registerWriteHandler(new SelectSheetWriteHandler(head)) // 基于固定 sheet 实现下拉框
.registerConverter(new LongStringConverter()) // 避免 Long 类型丢失精度
.sheet(sheetName).doWrite(data);

View File

@ -2,6 +2,7 @@ package cn.hangtag.module.oms.controller.admin.productinfo.vo;
import cn.hangtag.framework.excel.core.annotations.ExcelColumnSelect;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.ContentStyle;
import com.alibaba.excel.annotation.write.style.HeadFontStyle;
import com.alibaba.excel.annotation.write.style.HeadStyle;
@ -48,6 +49,7 @@ public class ProductInfoExcelVO {
@Schema(description = "产品简介")
@ExcelProperty("产品简介")
@HeadFontStyle(color = Font.COLOR_NORMAL)
@ColumnWidth(value = 10)
private String introduction;
@Schema(description = "产品规格-宽")