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 10 import cn.idev.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
11 11 import org.apache.poi.ss.usermodel.Cell;
12 12  
  13 +import java.nio.charset.StandardCharsets;
13 14 import java.util.HashMap;
14 15 import java.util.List;
15 16 import java.util.Map;
... ... @@ -41,6 +42,7 @@ public class ColumnWidthMatchStyleStrategy extends AbstractColumnWidthStyleStrat
41 42 if (columnWidth < 0) {
42 43 return;
43 44 }
  45 + columnWidth += 2; // 留出单元格边距,避免短表头换行
44 46 if (columnWidth > MAX_COLUMN_WIDTH) {
45 47 columnWidth = MAX_COLUMN_WIDTH;
46 48 }
... ... @@ -54,7 +56,7 @@ public class ColumnWidthMatchStyleStrategy extends AbstractColumnWidthStyleStrat
54 56 @SuppressWarnings("EnhancedSwitchMigration")
55 57 private Integer dataLength(List<WriteCellData<?>> cellDataList, Cell cell, Boolean isHead) {
56 58 if (isHead) {
57   - return cell.getStringCellValue().getBytes().length;
  59 + return cell.getStringCellValue().getBytes(StandardCharsets.UTF_8).length;
58 60 }
59 61 WriteCellData<?> cellData = cellDataList.get(0);
60 62 CellDataTypeEnum type = cellData.getType();
... ... @@ -63,16 +65,16 @@ public class ColumnWidthMatchStyleStrategy extends AbstractColumnWidthStyleStrat
63 65 }
64 66 switch (type) {
65 67 case STRING:
66   - return cellData.getStringValue().getBytes().length;
  68 + return cellData.getStringValue().getBytes(StandardCharsets.UTF_8).length;
67 69 case BOOLEAN:
68   - return cellData.getBooleanValue().toString().getBytes().length;
  70 + return cellData.getBooleanValue().toString().getBytes(StandardCharsets.UTF_8).length;
69 71 case NUMBER:
70   - return cellData.getNumberValue().toString().getBytes().length;
  72 + return cellData.getNumberValue().toString().getBytes(StandardCharsets.UTF_8).length;
71 73 case DATE:
72   - return cellData.getDateValue().toString().getBytes().length;
  74 + return cellData.getDateValue().toString().getBytes(StandardCharsets.UTF_8).length;
73 75 default:
74 76 return -1;
75 77 }
76 78 }
77 79  
78   -}
79 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 +}
... ...