Easyexcel(5-自定义列宽)

devtools/2024/11/25 3:15:52/

相关文章链接

  1. Easyexcel(1-注解使用)
  2. Easyexcel(2-文件读取)
  3. Easyexcel(3-文件导出)
  4. Easyexcel(4-模板文件)
  5. Easyexcel(5-自定义列宽)

注解

@ColumnWidth

java">@Data
public class WidthAndHeightData {@ExcelProperty("字符串标题")private String string;@ExcelProperty("日期标题")private Date date;@ColumnWidth(50)@ExcelProperty("数字标题")private Double doubleData;
}

注解使用时表头长度无法做到动态调整,只能固定设置,每次调整表头长度时只能重新修改代码

注意:@ColumnWidth最大值只能为255,超过255*256长度时会报错

查看XSSFSheet源码

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

类方法

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

AbstractHeadColumnWidthStyleStrategy

java">public abstract class AbstractHeadColumnWidthStyleStrategy extends AbstractColumnWidthStyleStrategy {@Overrideprotected void setColumnWidth(WriteSheetHolder writeSheetHolder, List<WriteCellData<?>> cellDataList, Cell cell, Head head,Integer relativeRowIndex, Boolean isHead) {// 判断是否满足 当前行索引不为空 && (当前是表头 || 当前行索引是首行)// 如果不满足,则说明不是表头,不需要设置boolean needSetWidth = relativeRowIndex != null && (isHead || relativeRowIndex == 0);if (!needSetWidth) {return;}Integer width = columnWidth(head, cell.getColumnIndex());if (width != null) {width = width * 256;writeSheetHolder.getSheet().setColumnWidth(cell.getColumnIndex(), width);}}protected abstract Integer columnWidth(Head head, Integer columnIndex);
}

通过继承AbstractHeadColumnWidthStyleStrategy类,实现columnWidth方法获取其对应列的宽度

SimpleColumnWidthStyleStrategy

源码查看

java">public class SimpleColumnWidthStyleStrategy extends AbstractHeadColumnWidthStyleStrategy {private final Integer columnWidth;public SimpleColumnWidthStyleStrategy(Integer columnWidth) {this.columnWidth = columnWidth;}@Overrideprotected Integer columnWidth(Head head, Integer columnIndex) {return columnWidth;}
}

基本使用

通过registerWriteHandler设置策略方法调整每列的固定宽度

java">@Data
public class User {@ExcelProperty(value = "用户Id")private Integer userId;@ExcelProperty(value = "姓名")private String name;@ExcelProperty(value = "手机")private String phone;@ExcelProperty(value = "邮箱")private String email;@ExcelProperty(value = "创建时间")private Date createTime;
}
java">@GetMapping("/download2")
public void download2(HttpServletResponse response) {try {response.setContentType("application/vnd.ms-excel");response.setCharacterEncoding("utf-8");// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20");response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xls");User user = new User();user.setUserId(123);user.setName("asplplplplpplplplplpl");user.setPhone("15245413");user.setEmail("54565454@qq.com");user.setCreateTime(new Date());EasyExcel.write(response.getOutputStream(), User.class).sheet("模板").registerWriteHandler(new SimpleColumnWidthStyleStrategy(20)).doWrite(Arrays.asList(user));} catch (Exception e) {e.printStackTrace();}
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

LongestMatchColumnWidthStyleStrategy

源码查看

java">public class LongestMatchColumnWidthStyleStrategy extends AbstractColumnWidthStyleStrategy {private static final int MAX_COLUMN_WIDTH = 255;private final Map<Integer, Map<Integer, Integer>> cache = MapUtils.newHashMapWithExpectedSize(8);@Overrideprotected void setColumnWidth(WriteSheetHolder writeSheetHolder, List<WriteCellData<?>> cellDataList, Cell cell,Head head,Integer relativeRowIndex, Boolean isHead) {// 判断 是否为表头 || 导出内容是否为空boolean needSetWidth = isHead || !CollectionUtils.isEmpty(cellDataList);if (!needSetWidth) {return;}Map<Integer, Integer> maxColumnWidthMap = cache.computeIfAbsent(writeSheetHolder.getSheetNo(), key -> new HashMap<>(16));Integer columnWidth = dataLength(cellDataList, cell, isHead);if (columnWidth < 0) {return;}// 超过最大值255时则设置为255if (columnWidth > MAX_COLUMN_WIDTH) {columnWidth = MAX_COLUMN_WIDTH;}// 比较该列的宽度,如果比原来的宽度大,则重新设置Integer maxColumnWidth = maxColumnWidthMap.get(cell.getColumnIndex());if (maxColumnWidth == null || columnWidth > maxColumnWidth) {maxColumnWidthMap.put(cell.getColumnIndex(), columnWidth);writeSheetHolder.getSheet().setColumnWidth(cell.getColumnIndex(), 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;}}
}

LongestMatchColumnWidthStyleStrategy是一个列宽自适应策略。当我们在写入Excel数据时,如果希望根据数据的实际长度来自适应调整列宽,就可以使用这个策略。它会遍历指定列的所有数据(包括表头),找出最长的数据,然后根据这个最长数据的长度来设定该列的宽度,确保数据在单元格内不会被截断。

根据官网介绍:这个目前不是很好用,比如有数字就会导致换行。而且长度也不是刚好和实际长度一致。 所以需要精确到刚好列宽的慎用。

基本使用

java">@GetMapping("/download1")
public void download1(HttpServletResponse response) {try {response.setContentType("application/vnd.ms-excel");response.setCharacterEncoding("utf-8");// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20");response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xls");User user = new User();user.setUserId(123);user.setName("asplplplplpplplplplpl");user.setPhone("15245413");user.setEmail("54565454@qq.com");user.setCreateTime(new Date());EasyExcel.write(response.getOutputStream(), User.class).sheet("模板").registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).doWrite(Arrays.asList(user));} catch (Exception e) {e.printStackTrace();}
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

表头宽度工具类

仿照LongestMatchColumnWidthStyleStrategy源码自定义工具类

使用构造器传参的方式,用户可以自定义通过表头或者单元格内容长度来设置列宽,通过修改常数值和比例可以自己设置想调整的列宽

java">/*** 表头宽度根据表头或数据内容自适应*/
public class CustomWidthStyleStrategy extends AbstractColumnWidthStyleStrategy {/*** 1-根据表头宽度,2-根据单元格内容*/private Integer type;private Map<Integer, Map<Integer, Integer>> cache = new HashMap<>();public CustomWidthStyleStrategy(Integer type) {this.type = type;}/*** 设置列宽** @param writeSheetHolder 写入Sheet的持有者* @param cellDataList 当前列的单元格数据列表* @param cell 当前单元格* @param head 表头* @param relativeRowIndex 当前行的相对索引* @param isHead 是否为表头*/@Overrideprotected void setColumnWidth(WriteSheetHolder writeSheetHolder, List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {if (type == 1) {if (isHead) {int columnWidth = cell.getStringCellValue().length();columnWidth = Math.max(columnWidth * 2, 20);if (columnWidth > 255) {columnWidth = 255;}writeSheetHolder.getSheet().setColumnWidth(cell.getColumnIndex(), columnWidth * 256);}return;}//不把标头计算在内boolean needSetWidth = isHead || !CollectionUtils.isEmpty(cellDataList);if (needSetWidth) {Map<Integer, Integer> maxColumnWidthMap = cache.get(writeSheetHolder.getSheetNo());if (maxColumnWidthMap == null) {maxColumnWidthMap = new HashMap<>();cache.put(writeSheetHolder.getSheetNo(), maxColumnWidthMap);}Integer columnWidth = this.dataLength(cellDataList, cell, isHead);if (columnWidth >= 0) {if (columnWidth > 255) {columnWidth = 255;}Integer maxColumnWidth = maxColumnWidthMap.get(cell.getColumnIndex());if (maxColumnWidth == null || columnWidth > maxColumnWidth) {maxColumnWidthMap.put(cell.getColumnIndex(), columnWidth);writeSheetHolder.getSheet().setColumnWidth(cell.getColumnIndex(), columnWidth * 256);}}}}/*** 数据长度** @param cellDataList* @param cell* @param isHead* @return*/private Integer dataLength(List<WriteCellData<?>> cellDataList, Cell cell, Boolean isHead) {//头直接返回原始长度if (isHead) {return cell.getStringCellValue().getBytes().length;} else {//不是头的话  看是什么类型  用数字加就可以了WriteCellData cellData = cellDataList.get(0);CellDataTypeEnum type = cellData.getType();if (type == null) {return -1;} else {switch (type) {case STRING:return cellData.getStringValue().getBytes().length + 1;case BOOLEAN:return cellData.getBooleanValue().toString().getBytes().length;case NUMBER:return cellData.getNumberValue().toString().getBytes().length * 2;case DATE:return cellData.getDateValue().toString().length() + 1;default:return -1;}}}}
}
java">@GetMapping("/download3")
public void download3(HttpServletResponse response) {try {response.setContentType("application/vnd.ms-excel");response.setCharacterEncoding("utf-8");// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20");response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xls");User user = new User();user.setUserId(123);user.setName("asplplplplpplplplplpl");user.setPhone("15245413");user.setEmail("54565454@qq.com");user.setCreateTime(new Date());EasyExcel.write(response.getOutputStream(), User.class).sheet("模板").registerWriteHandler(new CustomWidthStyleStrategy(1)).doWrite(Arrays.asList(user));} catch (Exception e) {e.printStackTrace();}
}@GetMapping("/download4")
public void download4(HttpServletResponse response) {try {response.setContentType("application/vnd.ms-excel");response.setCharacterEncoding("utf-8");// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20");response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xls");User user = new User();user.setUserId(123);user.setName("asplplplplpplplplplpl");user.setPhone("15245413");user.setEmail("54565454@qq.com");user.setCreateTime(new Date());EasyExcel.write(response.getOutputStream(), User.class).sheet("模板").registerWriteHandler(new CustomWidthStyleStrategy(2)).doWrite(Arrays.asList(user));} catch (Exception e) {e.printStackTrace();}
}

运行结果

  1. 使用表头设置的列宽

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. 使用单元格内容设置的列宽

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传


http://www.ppmy.cn/devtools/136729.html

相关文章

《线性代数的本质》

之前收藏的一门课&#xff0c;刚好期末复习&#xff0c;顺便看一看哈哈 课程链接&#xff1a;【线性代数的本质】合集-转载于3Blue1Brown官方双语】 向量究竟是什么 线性代数中最基础、最根源的组成部分就是向量&#xff0c;需要先明白什么是向量 不同专业对向量的看法 物理专…

动态规划 详解

动态规划&#xff08;Dynamic Programming, DP&#xff09;详解 动态规划是一种通过分解问题为子问题并利用子问题的解来解决原问题的算法设计方法。它通常用于解决具有 重叠子问题 和 最优子结构 性质的问题。 1. 动态规划的核心思想 1.1 重叠子问题 问题可以分解为多个子问…

QT 实现表格展示第一列为CheckBox(复选框)

1.界面实现效果 在Qt中,如果你想要在QTableView中实现复选框展示数据,示例:实现第一列为复选框(checkBox),需要自定义的QAbstractTableModel,重写data和setData方法来返回和设置复选框的状态,并且还需要重写flags方法来允许复选框被点击。 2.自定义CustomModel 需要实…

太速科技-232-基于FMC的2收2发TLK2711子卡

基于FMC的2收2发TLK2711子卡 一、板卡概述 TLK2711 是千兆位收发器&#xff0c;专用于超高速双向点对点数据传输系统。TLK2711与时钟芯片SI5338相结合支持1.6Gbps至2.5Gbps的有效串行接口速度&#xff0c;可提供高达 2Gbps的数据带宽。板卡包含2路TLK2711&#xff0c;实…

《OpenCV 中阈值处理方法全解析及应用实例》

简介&#xff1a;本文详细介绍了 OpenCV 中多种阈值处理方法&#xff0c;包括cv2.threshold函数相关的二值化、反二值化、截断化、超阈值零处理、低阈值零处理等阈值处理方式&#xff0c;解析了阈值分割的作用以及函数返回阈值的原因。同时还涵盖了自适应阈值处理和 Otsu 阈值处…

sqlite-vec一个SQLite3高效向量搜索扩展--JDBC环境使用

最近要用SQLite3&#xff0c;之前放出来了SQLiteUtile工具&#xff0c;方便操作。今天发现AIGC方面&#xff0c;RAG知识库需要使用向量数据库&#xff0c;来存储知识信息。一般呢都是用mysql&#xff0c;但无奈的是mysql就是不让用。突然又发现SQLite3有向量库扩展组件&#xf…

HarmonyOS4+NEXT星河版入门与项目实战(11)------Button组件

文章目录 1、控件图解2、案例实现1、代码实现2、代码解释3、运行效果4、总结1、控件图解 这里我们用一张完整的图来汇整 Button 的用法格式、属性和事件,如下所示: 按钮默认类型就是胶囊类型。 2、案例实现 这里我们实现一个根据放大和缩小按钮来改变图片大小的功能。 功…

linux安装NVM与Node

linux安装NVM与Node 1.安装nvm 安装版本管理工具git&#xff1a;yum install git 查看git版本&#xff1a;git --version 开放443端口&#xff1a;sudo firewall-cmd --permanent --add-port443/tcp 重启防火墙&#xff1a;sudo firewall-cmd --reload 一键式安装指令&#…