Commit 54b3b5862690c6c2fcde104e8636c758824a93d3

Authored by YunaiV
1 parent 7cae2852

fix(excel): 修复中文表头列宽不足导致换行

yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/handler/ColumnWidthMatchStyleStrategy.java
@@ -10,6 +10,7 @@ import cn.idev.excel.write.style.column.AbstractColumnWidthStyleStrategy; @@ -10,6 +10,7 @@ import cn.idev.excel.write.style.column.AbstractColumnWidthStyleStrategy;
10 import cn.idev.excel.write.style.column.LongestMatchColumnWidthStyleStrategy; 10 import cn.idev.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
11 import org.apache.poi.ss.usermodel.Cell; 11 import org.apache.poi.ss.usermodel.Cell;
12 12
  13 +import java.nio.charset.StandardCharsets;
13 import java.util.HashMap; 14 import java.util.HashMap;
14 import java.util.List; 15 import java.util.List;
15 import java.util.Map; 16 import java.util.Map;
@@ -41,6 +42,7 @@ public class ColumnWidthMatchStyleStrategy extends AbstractColumnWidthStyleStrat @@ -41,6 +42,7 @@ public class ColumnWidthMatchStyleStrategy extends AbstractColumnWidthStyleStrat
41 if (columnWidth < 0) { 42 if (columnWidth < 0) {
42 return; 43 return;
43 } 44 }
  45 + columnWidth += 2; // 留出单元格边距,避免短表头换行
44 if (columnWidth > MAX_COLUMN_WIDTH) { 46 if (columnWidth > MAX_COLUMN_WIDTH) {
45 columnWidth = MAX_COLUMN_WIDTH; 47 columnWidth = MAX_COLUMN_WIDTH;
46 } 48 }
@@ -54,7 +56,7 @@ public class ColumnWidthMatchStyleStrategy extends AbstractColumnWidthStyleStrat @@ -54,7 +56,7 @@ public class ColumnWidthMatchStyleStrategy extends AbstractColumnWidthStyleStrat
54 @SuppressWarnings("EnhancedSwitchMigration") 56 @SuppressWarnings("EnhancedSwitchMigration")
55 private Integer dataLength(List<WriteCellData<?>> cellDataList, Cell cell, Boolean isHead) { 57 private Integer dataLength(List<WriteCellData<?>> cellDataList, Cell cell, Boolean isHead) {
56 if (isHead) { 58 if (isHead) {
57 - return cell.getStringCellValue().getBytes().length; 59 + return cell.getStringCellValue().getBytes(StandardCharsets.UTF_8).length;
58 } 60 }
59 WriteCellData<?> cellData = cellDataList.get(0); 61 WriteCellData<?> cellData = cellDataList.get(0);
60 CellDataTypeEnum type = cellData.getType(); 62 CellDataTypeEnum type = cellData.getType();
@@ -63,16 +65,16 @@ public class ColumnWidthMatchStyleStrategy extends AbstractColumnWidthStyleStrat @@ -63,16 +65,16 @@ public class ColumnWidthMatchStyleStrategy extends AbstractColumnWidthStyleStrat
63 } 65 }
64 switch (type) { 66 switch (type) {
65 case STRING: 67 case STRING:
66 - return cellData.getStringValue().getBytes().length; 68 + return cellData.getStringValue().getBytes(StandardCharsets.UTF_8).length;
67 case BOOLEAN: 69 case BOOLEAN:
68 - return cellData.getBooleanValue().toString().getBytes().length; 70 + return cellData.getBooleanValue().toString().getBytes(StandardCharsets.UTF_8).length;
69 case NUMBER: 71 case NUMBER:
70 - return cellData.getNumberValue().toString().getBytes().length; 72 + return cellData.getNumberValue().toString().getBytes(StandardCharsets.UTF_8).length;
71 case DATE: 73 case DATE:
72 - return cellData.getDateValue().toString().getBytes().length; 74 + return cellData.getDateValue().toString().getBytes(StandardCharsets.UTF_8).length;
73 default: 75 default:
74 return -1; 76 return -1;
75 } 77 }
76 } 78 }
77 79
78 -}  
79 \ No newline at end of file 80 \ No newline at end of file
  81 +}
yudao-framework/yudao-spring-boot-starter-excel/src/test/java/cn/iocoder/yudao/framework/excel/core/handler/ColumnWidthMatchStyleStrategyTest.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.excel.core.handler;
  2 +
  3 +import cn.idev.excel.FastExcelFactory;
  4 +import cn.idev.excel.annotation.ExcelProperty;
  5 +import org.apache.poi.xssf.usermodel.XSSFWorkbook;
  6 +import org.junit.jupiter.api.Test;
  7 +
  8 +import java.io.ByteArrayInputStream;
  9 +import java.io.ByteArrayOutputStream;
  10 +import java.util.Collections;
  11 +import java.util.List;
  12 +
  13 +import static org.junit.jupiter.api.Assertions.assertEquals;
  14 +import static org.junit.jupiter.api.Assertions.assertTrue;
  15 +
  16 +/**
  17 + * {@link ColumnWidthMatchStyleStrategy} 的单元测试
  18 + *
  19 + * @author 芋道源码
  20 + */
  21 +public class ColumnWidthMatchStyleStrategyTest {
  22 +
  23 + @Test
  24 + public void testWrite_emptyChineseHeader() throws Exception {
  25 + // 调用
  26 + try (XSSFWorkbook workbook = write(Collections.emptyList())) {
  27 + // 断言:空列表导出的中文短表头也保留足够宽度
  28 + assertEquals("标题", workbook.getSheetAt(0).getRow(0).getCell(0).getStringCellValue());
  29 + assertTrue(workbook.getSheetAt(0).getColumnWidth(0) >= 8 * 256);
  30 + }
  31 + }
  32 +
  33 + @Test
  34 + public void testWrite_longestValue() throws Exception {
  35 + // mock 数据
  36 + TestRow row = new TestRow();
  37 + row.setName("自动化测试工作项标题");
  38 +
  39 + // 调用
  40 + try (XSSFWorkbook workbook = write(Collections.singletonList(row))) {
  41 + // 断言:数据内容比表头长时继续扩展列宽
  42 + assertTrue(workbook.getSheetAt(0).getColumnWidth(0) > 8 * 256);
  43 + assertEquals(row.getName(), workbook.getSheetAt(0).getRow(1).getCell(0).getStringCellValue());
  44 + }
  45 + }
  46 +
  47 + @Test
  48 + public void testWrite_maxColumnWidth() throws Exception {
  49 + // mock 数据
  50 + TestRow row = new TestRow();
  51 + row.setName("测试".repeat(100));
  52 +
  53 + // 调用
  54 + try (XSSFWorkbook workbook = write(Collections.singletonList(row))) {
  55 + // 断言:留白后仍不超过 Excel 的列宽上限
  56 + assertEquals(255 * 256, workbook.getSheetAt(0).getColumnWidth(0));
  57 + }
  58 + }
  59 +
  60 + private XSSFWorkbook write(List<TestRow> rows) throws Exception {
  61 + ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
  62 + FastExcelFactory.write(outputStream, TestRow.class)
  63 + .registerWriteHandler(new ColumnWidthMatchStyleStrategy()).sheet().doWrite(rows);
  64 + return new XSSFWorkbook(new ByteArrayInputStream(outputStream.toByteArray()));
  65 + }
  66 +
  67 + public static class TestRow {
  68 +
  69 + @ExcelProperty("标题")
  70 + private String name;
  71 +
  72 + public String getName() {
  73 + return name;
  74 + }
  75 +
  76 + public void setName(String name) {
  77 + this.name = name;
  78 + }
  79 +
  80 + }
  81 +
  82 +}