优化 excel导出列宽太大导致占满屏问题
This commit is contained in:
parent
287afdc119
commit
531f3c6b29
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 = "产品规格-宽")
|
||||
|
|
|
|||
Loading…
Reference in New Issue