Commit 77193102a2038fafb71e03ac31e680257c40af75

Authored by YunaiV
1 parent 1b412546

feat:添加自适应列宽处理器并替换默认列宽策略

yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/handler/ColumnWidthMatchStyleStrategy.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.excel.core.handler;
  2 +
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.idev.excel.enums.CellDataTypeEnum;
  5 +import cn.idev.excel.metadata.Head;
  6 +import cn.idev.excel.metadata.data.WriteCellData;
  7 +import cn.idev.excel.util.MapUtils;
  8 +import cn.idev.excel.write.metadata.holder.WriteSheetHolder;
  9 +import cn.idev.excel.write.style.column.AbstractColumnWidthStyleStrategy;
  10 +import cn.idev.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
  11 +import org.apache.poi.ss.usermodel.Cell;
  12 +
  13 +import java.util.HashMap;
  14 +import java.util.List;
  15 +import java.util.Map;
  16 +
  17 +/**
  18 + * Excel 自适应列宽处理器
  19 + *
  20 + * 相比 {@link LongestMatchColumnWidthStyleStrategy} 来说,额外处理了 DATE 类型!
  21 + *
  22 + * @see <a href="https://github.com/YunaiV/yudao-cloud/pull/196/">添加自适应列宽处理器,并替换默认列宽策略</a>
  23 + * @author hmb
  24 + */
  25 +public class ColumnWidthMatchStyleStrategy extends AbstractColumnWidthStyleStrategy {
  26 +
  27 + private static final int MAX_COLUMN_WIDTH = 255;
  28 +
  29 + private final Map<Integer, Map<Integer, Integer>> cache = MapUtils.newHashMapWithExpectedSize(8);
  30 +
  31 + @Override
  32 + protected void setColumnWidth(WriteSheetHolder writeSheetHolder, List<WriteCellData<?>> cellDataList, Cell cell,
  33 + Head head, Integer relativeRowIndex, Boolean isHead) {
  34 + boolean needSetWidth = isHead || CollUtil.isNotEmpty(cellDataList);
  35 + if (!needSetWidth) {
  36 + return;
  37 + }
  38 + Map<Integer, Integer> maxColumnWidthMap = cache.computeIfAbsent(writeSheetHolder.getSheetNo(),
  39 + key -> new HashMap<>(16));
  40 + Integer columnWidth = dataLength(cellDataList, cell, isHead);
  41 + if (columnWidth < 0) {
  42 + return;
  43 + }
  44 + if (columnWidth > MAX_COLUMN_WIDTH) {
  45 + columnWidth = MAX_COLUMN_WIDTH;
  46 + }
  47 + Integer maxColumnWidth = maxColumnWidthMap.get(cell.getColumnIndex());
  48 + if (maxColumnWidth == null || columnWidth > maxColumnWidth) {
  49 + maxColumnWidthMap.put(cell.getColumnIndex(), columnWidth);
  50 + writeSheetHolder.getSheet().setColumnWidth(cell.getColumnIndex(), columnWidth * 256);
  51 + }
  52 + }
  53 +
  54 + @SuppressWarnings("EnhancedSwitchMigration")
  55 + private Integer dataLength(List<WriteCellData<?>> cellDataList, Cell cell, Boolean isHead) {
  56 + if (isHead) {
  57 + return cell.getStringCellValue().getBytes().length;
  58 + }
  59 + WriteCellData<?> cellData = cellDataList.get(0);
  60 + CellDataTypeEnum type = cellData.getType();
  61 + if (type == null) {
  62 + return -1;
  63 + }
  64 + switch (type) {
  65 + case STRING:
  66 + return cellData.getStringValue().getBytes().length;
  67 + case BOOLEAN:
  68 + return cellData.getBooleanValue().toString().getBytes().length;
  69 + case NUMBER:
  70 + return cellData.getNumberValue().toString().getBytes().length;
  71 + case DATE:
  72 + return cellData.getDateValue().toString().getBytes().length;
  73 + default:
  74 + return -1;
  75 + }
  76 + }
  77 +
  78 +}
0 \ No newline at end of file 79 \ No newline at end of file
yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/handler/SelectSheetWriteHandler.java
@@ -86,7 +86,7 @@ public class SelectSheetWriteHandler implements SheetWriteHandler { @@ -86,7 +86,7 @@ public class SelectSheetWriteHandler implements SheetWriteHandler {
86 86
87 /** 87 /**
88 * 判断字段是否是静态的、最终的、 transient 的 88 * 判断字段是否是静态的、最终的、 transient 的
89 - * 原因:EasyExcel 默认是忽略 static final 或 transient 的字段,所以需要判断 89 + * 原因:FastExcel 默认是忽略 static final 或 transient 的字段,所以需要判断
90 * 90 *
91 * @param field 字段 91 * @param field 字段
92 * @return 是否是静态的、最终的、transient 的 92 * @return 是否是静态的、最终的、transient 的
yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java
1 package cn.iocoder.yudao.framework.excel.core.util; 1 package cn.iocoder.yudao.framework.excel.core.util;
2 2
  3 +import cn.idev.excel.FastExcelFactory;
  4 +import cn.idev.excel.converters.longconverter.LongStringConverter;
3 import cn.iocoder.yudao.framework.common.util.http.HttpUtils; 5 import cn.iocoder.yudao.framework.common.util.http.HttpUtils;
  6 +import cn.iocoder.yudao.framework.excel.core.handler.ColumnWidthMatchStyleStrategy;
4 import cn.iocoder.yudao.framework.excel.core.handler.SelectSheetWriteHandler; 7 import cn.iocoder.yudao.framework.excel.core.handler.SelectSheetWriteHandler;
5 -import cn.idev.excel.EasyExcel;  
6 -import cn.idev.excel.converters.longconverter.LongStringConverter;  
7 -import cn.idev.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;  
8 import jakarta.servlet.http.HttpServletResponse; 8 import jakarta.servlet.http.HttpServletResponse;
9 import org.springframework.web.multipart.MultipartFile; 9 import org.springframework.web.multipart.MultipartFile;
10 10
@@ -32,9 +32,9 @@ public class ExcelUtils { @@ -32,9 +32,9 @@ public class ExcelUtils {
32 public static <T> void write(HttpServletResponse response, String filename, String sheetName, 32 public static <T> void write(HttpServletResponse response, String filename, String sheetName,
33 Class<T> head, List<T> data) throws IOException { 33 Class<T> head, List<T> data) throws IOException {
34 // 输出 Excel 34 // 输出 Excel
35 - EasyExcel.write(response.getOutputStream(), head) 35 + FastExcelFactory.write(response.getOutputStream(), head)
36 .autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理 36 .autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理
37 - .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 基于 column 长度,自动适配。最大 255 宽度 37 + .registerWriteHandler(new ColumnWidthMatchStyleStrategy()) // 基于 column 长度,自动适配。最大 255 宽度
38 .registerWriteHandler(new SelectSheetWriteHandler(head)) // 基于固定 sheet 实现下拉框 38 .registerWriteHandler(new SelectSheetWriteHandler(head)) // 基于固定 sheet 实现下拉框
39 .registerConverter(new LongStringConverter()) // 避免 Long 类型丢失精度 39 .registerConverter(new LongStringConverter()) // 避免 Long 类型丢失精度
40 .sheet(sheetName).doWrite(data); 40 .sheet(sheetName).doWrite(data);
@@ -44,7 +44,7 @@ public class ExcelUtils { @@ -44,7 +44,7 @@ public class ExcelUtils {
44 } 44 }
45 45
46 public static <T> List<T> read(MultipartFile file, Class<T> head) throws IOException { 46 public static <T> List<T> read(MultipartFile file, Class<T> head) throws IOException {
47 - return EasyExcel.read(file.getInputStream(), head, null) 47 + return FastExcelFactory.read(file.getInputStream(), head, null)
48 .autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理 48 .autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理
49 .doReadAllSync(); 49 .doReadAllSync();
50 } 50 }
yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/package-info.java
1 /** 1 /**
2 - * 基于 EasyExcel 实现 Excel 相关的操作 2 + * 基于 FastExcel 实现 Excel 相关的操作
3 */ 3 */
4 package cn.iocoder.yudao.framework.excel; 4 package cn.iocoder.yudao.framework.excel;