From 531f3c6b29a356206decfa18f98022ac75be0799 Mon Sep 17 00:00:00 2001 From: YuanFeng <770153798@qq.com> Date: Thu, 4 Jun 2026 20:51:33 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=20excel=E5=AF=BC=E5=87=BA?= =?UTF-8?q?=E5=88=97=E5=AE=BD=E5=A4=AA=E5=A4=A7=E5=AF=BC=E8=87=B4=E5=8D=A0?= =?UTF-8?q?=E6=BB=A1=E5=B1=8F=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../handler/OmsColumnWidthStyleStrategy.java | 115 ++++++++++++++++++ .../framework/excel/core/util/ExcelUtils.java | 3 +- .../productinfo/vo/ProductInfoExcelVO.java | 2 + 3 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 hangtag-framework/hangtag-spring-boot-starter-excel/src/main/java/cn/hangtag/framework/excel/core/handler/OmsColumnWidthStyleStrategy.java diff --git a/hangtag-framework/hangtag-spring-boot-starter-excel/src/main/java/cn/hangtag/framework/excel/core/handler/OmsColumnWidthStyleStrategy.java b/hangtag-framework/hangtag-spring-boot-starter-excel/src/main/java/cn/hangtag/framework/excel/core/handler/OmsColumnWidthStyleStrategy.java new file mode 100644 index 0000000..d9950b1 --- /dev/null +++ b/hangtag-framework/hangtag-spring-boot-starter-excel/src/main/java/cn/hangtag/framework/excel/core/handler/OmsColumnWidthStyleStrategy.java @@ -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> cache = MapUtils.newHashMapWithExpectedSize(8); + private final int MAX_COLUMN_WIDTH; + + // 缓存:列index → 注解指定宽度(只解析一次) + private final Map annotatedWidthMap = new HashMap<>(); + private boolean initialized = false; + + public OmsColumnWidthStyleStrategy(int maxColumnWidth) { + MAX_COLUMN_WIDTH = maxColumnWidth; + } + + @Override + protected void setColumnWidth(WriteSheetHolder writeSheetHolder, List> 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 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> 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; + } + } +} \ No newline at end of file diff --git a/hangtag-framework/hangtag-spring-boot-starter-excel/src/main/java/cn/hangtag/framework/excel/core/util/ExcelUtils.java b/hangtag-framework/hangtag-spring-boot-starter-excel/src/main/java/cn/hangtag/framework/excel/core/util/ExcelUtils.java index 2541213..d13c84d 100644 --- a/hangtag-framework/hangtag-spring-boot-starter-excel/src/main/java/cn/hangtag/framework/excel/core/util/ExcelUtils.java +++ b/hangtag-framework/hangtag-spring-boot-starter-excel/src/main/java/cn/hangtag/framework/excel/core/util/ExcelUtils.java @@ -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); diff --git a/hangtag-module-oms/hangtag-module-oms-biz/src/main/java/cn/hangtag/module/oms/controller/admin/productinfo/vo/ProductInfoExcelVO.java b/hangtag-module-oms/hangtag-module-oms-biz/src/main/java/cn/hangtag/module/oms/controller/admin/productinfo/vo/ProductInfoExcelVO.java index 175f116..257f7dd 100644 --- a/hangtag-module-oms/hangtag-module-oms-biz/src/main/java/cn/hangtag/module/oms/controller/admin/productinfo/vo/ProductInfoExcelVO.java +++ b/hangtag-module-oms/hangtag-module-oms-biz/src/main/java/cn/hangtag/module/oms/controller/admin/productinfo/vo/ProductInfoExcelVO.java @@ -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 = "产品规格-宽")