Explorar o código

提交导出格式修正导致报错的bug

hxl13994548489 %!s(int64=2) %!d(string=hai) anos
pai
achega
a3119e4801

+ 94 - 0
src/main/java/com/ydtech/utils/AutoCellWriteWidthHandle.java

@@ -0,0 +1,94 @@
+package com.ydtech.utils;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.alibaba.excel.write.handler.RowWriteHandler;
+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.DataFormatter;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.util.CellRangeAddress;
+
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+/**
+ * EasyExcel自适应列宽专用
+ */
+public class AutoCellWriteWidthHandle implements RowWriteHandler {
+    private final Map<Integer, Map<Integer, Integer>> MAX_COLUMN_WIDTH_CACHE = new HashMap<>(8);
+    private final int MIN_WIDTH = 800;
+    private final DataFormatter dataFormatter = new DataFormatter();
+    private Integer startHeadRow;
+    private Integer endHeadRow;
+
+    @Override
+    public void afterRowDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Integer relativeRowIndex, Boolean isHead) {
+        if (isHead) {
+            return;
+        }
+        isHead = ObjectUtil.isEmpty(startHeadRow) || ObjectUtil.isEmpty(endHeadRow) || (row.getRowNum() >= startHeadRow && row.getRowNum() <= endHeadRow);
+        Integer sheetNo = writeSheetHolder.getSheetNo();
+        if (CollUtil.isEmpty(MAX_COLUMN_WIDTH_CACHE.get(sheetNo)) && isHead) {
+            //踩坑标注; 不能通过writeSheetHolder获取sheet对象, 这会拿不到已填充的数据 因为EasyExcel是最后才把sheet同步到writeSheetHolder
+            Sheet sheet = row.getSheet();
+            HashMap<Integer, Integer> headWidthMap = new HashMap<>();
+            MAX_COLUMN_WIDTH_CACHE.put(sheetNo, headWidthMap);
+            List<CellRangeAddress> mergedRegions = sheet.getMergedRegions();
+            //表头可能存在多行
+            for (int headRowIndex = startHeadRow = sheet.getFirstRowNum(); headRowIndex < (endHeadRow = row.getRowNum()); headRowIndex++) {
+                Row headRow = sheet.getRow(headRowIndex);
+                if (ObjectUtil.isEmpty(headRow)) {
+                    continue;
+                }
+                for (int cellIndex = headRow.getFirstCellNum();
+                     cellIndex < headRow.getLastCellNum(); cellIndex++) {
+                    Cell headCell = headRow.getCell(cellIndex);
+                    if (ObjectUtil.isEmpty(headCell) || this.isMeagerCell(mergedRegions, headCell)) {
+                        continue;
+                    }
+                    //获取字符长度
+                    int newHeadCellWidth = this.getDataLength(headCell);
+                    Integer oldHeadMaxWidth = headWidthMap.get(headCell.getColumnIndex());
+                    int currentMaxWidth = ObjectUtil.isEmpty(oldHeadMaxWidth) ? newHeadCellWidth : Math.max(oldHeadMaxWidth, newHeadCellWidth);
+                    headWidthMap.put(cellIndex, currentMaxWidth);
+                }
+            }
+        }
+        for (int cellIndex = row.getFirstCellNum(); cellIndex < row.getLastCellNum(); cellIndex++) {
+            //获取字符长度
+            Cell cell = row.getCell(cellIndex);
+            if (ObjectUtil.isEmpty(cell)) {
+                continue;
+            }
+            int newHeadCellWidth = this.getDataLength(cell);
+            //比较列宽度,取最大值
+            Map<Integer, Integer> cellMaxWidthMap = Optional.ofNullable(MAX_COLUMN_WIDTH_CACHE.get(writeSheetHolder.getSheetNo())).orElse(new HashMap<Integer, Integer>());
+            Integer mapMaxWidth = Optional.ofNullable(cellMaxWidthMap.get(cell.getColumnIndex())).orElse(MIN_WIDTH);
+            int currentMaxWidth = Math.max(mapMaxWidth, newHeadCellWidth);
+            //设置列宽
+            writeSheetHolder.getSheet().setColumnWidth(cell.getColumnIndex(), currentMaxWidth);
+            cellMaxWidthMap.put(cell.getColumnIndex(), currentMaxWidth);
+            MAX_COLUMN_WIDTH_CACHE.put(writeSheetHolder.getSheetNo(), cellMaxWidthMap);
+        }
+    }
+
+    private int getDataLength(Cell cell) {
+        String cellValue = dataFormatter.formatCellValue(cell);
+        return cellValue.getBytes(StandardCharsets.UTF_8).length * 256 + MIN_WIDTH;
+    }
+
+    /**
+     * 判断是否合并单元格
+     */
+    private boolean isMeagerCell(List<CellRangeAddress> mergedRegions, Cell cell) {
+        Optional<CellRangeAddress> mergedRegionOptional = mergedRegions.stream().filter(mergedRegion -> mergedRegion.isInRange(cell)).findFirst();
+        //纵向合并忽略, 横向合并才处理
+        return mergedRegionOptional.isPresent() && mergedRegionOptional.get().getLastColumn() - mergedRegionOptional.get().getFirstColumn() > 0;
+    }
+}

+ 8 - 8
src/main/java/com/ydtech/utils/CustomCellWriteHandler.java

@@ -85,17 +85,17 @@ public class CustomCellWriteHandler extends AbstractColumnWidthStyleStrategy {
           char[] chars = str.toCharArray();
           for(char c : chars){
               byte[] bytes = this.getUtf8Bytes(c);
-              if(bytes.length == 1){
-                  length += 1.05;
+              if (bytes.length == 1) {
+                  length += 1.6;
               }
-              if(bytes.length == 2){
-                  length += 1.5;
+              if (bytes.length == 2) {
+                  length += 2.2;
               }
-              if(bytes.length == 3){
-                  length += 1.85;
+              if (bytes.length == 3) {
+                  length += 3.85;
               }
-              if(bytes.length == 4){
-                  length += 2.2;
+              if (bytes.length == 4) {
+                  length += 4.2;
               }
           }
           return length;

+ 2 - 2
src/main/java/com/ydtech/utils/ExcelUtils.java

@@ -41,7 +41,7 @@ public class ExcelUtils<T> {
      */
     public boolean writeExcel(String saveFileName, String sheetName,List<T> data) {
         try {
-            EasyExcel.write(saveFileName, clazz).sheet(sheetName).registerWriteHandler(new CustomCellWriteHandler(0)).doWrite(data);
+            EasyExcel.write(saveFileName, clazz).sheet(sheetName).registerWriteHandler(new AutoCellWriteWidthHandle()).doWrite(data);
             return true;
         }catch(Exception e){
             return false;
@@ -57,7 +57,7 @@ public class ExcelUtils<T> {
      */
     public void writeExcelNew(String saveFileName, String sheetName,List<T> data) {
         try {
-            EasyExcel.write(saveFileName, clazz).sheet(sheetName).registerWriteHandler(new CustomCellWriteHandler(0)).doWrite(data);
+            EasyExcel.write(saveFileName, clazz).sheet(sheetName).registerWriteHandler(new AutoCellWriteWidthHandle()).doWrite(data);
         }catch(Exception e){
             throw new SystemException(e.getMessage());
         }