CustomCellWriteHandler.java 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. package com.ydtech.utils;
  2. import com.alibaba.excel.enums.CellDataTypeEnum;
  3. import com.alibaba.excel.metadata.Head;
  4. import com.alibaba.excel.metadata.data.CellData;
  5. import com.alibaba.excel.metadata.data.WriteCellData;
  6. import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
  7. import com.alibaba.excel.write.style.column.AbstractColumnWidthStyleStrategy;
  8. import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
  9. import org.apache.poi.ss.usermodel.Cell;
  10. import java.nio.ByteBuffer;
  11. import java.nio.CharBuffer;
  12. import java.nio.charset.StandardCharsets;
  13. import java.util.HashMap;
  14. import java.util.List;
  15. import java.util.Map;
  16. /**
  17. * @version
  18. * @author: hxl
  19. * @Date: 2024/7/4 10:44
  20. * @Description: excel 自适应列宽
  21. */
  22. public class CustomCellWriteHandler extends AbstractColumnWidthStyleStrategy {
  23. private static final int MAX_COLUMN_WIDTH = 255;
  24. private static final int COLUMN_WIDTH_BASE = 255;
  25. private final Map<Integer, Map<Integer, Double>> cache = new HashMap<>(8);
  26. private Integer relativeRowIndex = -1;
  27. public CustomCellWriteHandler() {
  28. }
  29. public CustomCellWriteHandler(Integer relativeRowIndex) {
  30. //这里是指定从第几行开始自适应。0是第一行,1是第二行,以此类推
  31. this.relativeRowIndex = relativeRowIndex;
  32. }
  33. @Override
  34. protected void setColumnWidth(WriteSheetHolder writeSheetHolder, List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
  35. boolean needSetWidth = isHead || !CollectionUtils.isEmpty(cellDataList);
  36. if (needSetWidth) {
  37. if (this.relativeRowIndex == -1 || relativeRowIndex >= this.relativeRowIndex) {
  38. Map<Integer, Double> maxColumnWidthMap = cache.computeIfAbsent(writeSheetHolder.getSheetNo(), k -> new HashMap<>(16));
  39. double columnWidth = this.dataLength(cellDataList, cell, isHead);
  40. if (columnWidth >= 0) {
  41. if (columnWidth > MAX_COLUMN_WIDTH) {
  42. columnWidth = MAX_COLUMN_WIDTH;
  43. }
  44. Double maxColumnWidth = maxColumnWidthMap.get(cell.getColumnIndex());
  45. if (maxColumnWidth == null || columnWidth > maxColumnWidth) {
  46. maxColumnWidthMap.put(cell.getColumnIndex(), columnWidth);
  47. writeSheetHolder.getSheet().setColumnWidth(cell.getColumnIndex(), (int) (maxColumnWidthMap.get(cell.getColumnIndex()) * COLUMN_WIDTH_BASE)+80);
  48. }
  49. }
  50. }
  51. }
  52. }
  53. private double dataLength(List<WriteCellData<?>> cellDataList, Cell cell, Boolean isHead) {
  54. if (isHead) {
  55. return cell.getStringCellValue().getBytes().length;
  56. } else {
  57. CellData<?> cellData = cellDataList.get(0);
  58. CellDataTypeEnum type = cellData.getType();
  59. //禁止这行
  60. cell.getCellStyle().setWrapText(false);
  61. if (type == null) {
  62. return -1;
  63. } else {
  64. switch (type) {
  65. case STRING:
  66. return getExcelWidth(cellData.getStringValue());
  67. case BOOLEAN:
  68. return getExcelWidth(cellData.getBooleanValue().toString());
  69. case NUMBER:
  70. return getExcelWidth(cellData.getNumberValue().toString());
  71. default:
  72. return -1;
  73. }
  74. }
  75. }
  76. }
  77. /** * 调整单元格字符字节宽度,easyExcel默认直接用的UTF-8的byte长度,导致一旦三字节的字符过多就会变得很宽,一字节的字符过多就会不够宽 */
  78. private double getExcelWidth(String str){
  79. double length = 0.0;
  80. char[] chars = str.toCharArray();
  81. for(char c : chars){
  82. byte[] bytes = this.getUtf8Bytes(c);
  83. if(bytes.length == 1){
  84. length += 1.05;
  85. }
  86. if(bytes.length == 2){
  87. length += 1.5;
  88. }
  89. if(bytes.length == 3){
  90. length += 1.85;
  91. }
  92. if(bytes.length == 4){
  93. length += 2.2;
  94. }
  95. }
  96. return length;
  97. }
  98. private byte[] getUtf8Bytes(char c) {
  99. char[] chars = {c};
  100. CharBuffer charBuffer = CharBuffer.allocate(chars.length);
  101. charBuffer.put(chars);
  102. charBuffer.flip();
  103. ByteBuffer byteBuffer = StandardCharsets.UTF_8.encode(charBuffer);
  104. return byteBuffer.array();
  105. }
  106. }