注解

@ColumnWidth

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

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

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

查看XSSFSheet源码

类方法

AbstractHeadColumnWidthStyleStrategy

public abstract class AbstractHeadColumnWidthStyleStrategy extends AbstractColumnWidthStyleStrategy {

    @Override
protected 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

源码查看

public class SimpleColumnWidthStyleStrategy extends AbstractHeadColumnWidthStyleStrategy {
private final Integer columnWidth; public SimpleColumnWidthStyleStrategy(Integer columnWidth) {
this.columnWidth = columnWidth;
} @Override
protected Integer columnWidth(Head head, Integer columnIndex) {
return columnWidth;
}
}

基本使用

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

@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;
}
@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

源码查看

public class LongestMatchColumnWidthStyleStrategy extends AbstractColumnWidthStyleStrategy {

    private static final int MAX_COLUMN_WIDTH = 255;

    private final Map<Integer, Map<Integer, Integer>> cache = MapUtils.newHashMapWithExpectedSize(8);

    @Override
protected 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时则设置为255
if (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数据时,如果希望根据数据的实际长度来自适应调整列宽,就可以使用这个策略。它会遍历指定列的所有数据(包括表头),找出最长的数据,然后根据这个最长数据的长度来设定该列的宽度,确保数据在单元格内不会被截断。

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

基本使用

@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源码自定义工具类

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

/**
* 表头宽度根据表头或数据内容自适应
*/
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 是否为表头
*/
@Override
protected 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;
}
}
}
}
}
@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. 使用单元格内容设置的列宽

Easyexcel(5-自定义列宽)的更多相关文章

  1. NPOI自适应列宽

    当本地没有安装Excel,但是又想导出Excel,采用Office插件是行不通的,NPOI是导出Excel的一个开源的插件.在导出Excel后,为了方便阅读,可以才采用自适应列宽的方式使得单元格的宽度 ...

  2. JQuery 表格拖动调整列宽效果

    类似于桌面程序中的表格拖动表头的效果,当鼠标停留在表头边框线上时,鼠标会变成表示左右拖动的形状,接着拖动鼠标,会在表格中出现一条随鼠标移动的竖线,最后放开鼠标,表格列宽会被调整.最近比较空闲,便自己动 ...

  3. QTableView表格视图的列宽设置

    Qt中的表格控件可以通过从QTableView或QTableWidget派生子类实现.其中,QTableWidget只是对QTableView的一种简单封装.因为使用QTableView常常需要用户指 ...

  4. MS WORD 表格自动调整列宽,自动变漂亮,根据内容自动调整 .

    在MS WORD中,当有大量的表格出现时,调整每个表格的的高和宽和大小将是一件非常累的事情,拖来拖去,非常耗时间,而且当WORD文档达到300页以上时,调整反应非常的慢,每次拖拉线后,需要等待一段时间 ...

  5. (几乎)完美实现 el-table 列宽自适应

    背景 Element UI 是 PC 端比较流行的 Vue.js UI 框架,它的组件库基本能满足大部分常见的业务需求.但有时候会有一些定制性比较高的需求,组件本身可能没办法满足.最近在项目里就碰到了 ...

  6. 修改yapf中的列宽限制值

    yapf是一款由Google开源的Python代码自动格式化工具,它根据PEP 8规范可以帮我们自动格式化我们的代码,让代码更规范.更漂亮.但是其中最大列宽被限制为80,如果超过80,在格式化时就会被 ...

  7. Asp.net 设置GridView自适应列宽不变形

    动态绑定的GridView由于列数不固定,而列又太多,这样设置GridView固定宽度就不能满足需求了.为此整理了两种方法来达到GridView自适应列宽不变形的效果. //在GridView的行数据 ...

  8. java表格操作之设置表格列宽

    设置所有列的宽度 /** * 设置所有列的列宽 * @param table * @param width */ public void setAllColumnWidth(JTable table, ...

  9. column css3 列宽

    column-count 属性规定元素应该被分隔的列数: div { -moz-column-count:3; /* Firefox */ -webkit-column-count:3; /* Saf ...

  10. [转]DevExpress.XtraGrid.GridControl gridView自动列宽代码

    gridView1.OptionsView.ColumnAutoWidth = false;   for (int I = 0; I < gridView1.Columns.Count; I++ ...

随机推荐

  1. ASP.NET Core EventStream (SSE) 使用以及 WebSocket 比较

    在开发环境中,对于实时数据流的需求非常常见,最常用的技术包括 Server-Sent Events (SSE) 和 WebSocket. 什么是 Server-Sent Events (SSE)? S ...

  2. Spring Boot logback springProperty 设置默认值

    springProperty 当没有读取到source字段中设置的log.path值时,设置为defaultValue字段中的${user.dir}/logs变量值. <springProper ...

  3. Spring Validation 校验

    概述 在 Web 应用中,客户端提交数据之前都会进行数据的校验,比如用户注册时填写的邮箱地址是否符合规范.用户名长度的限制等等,不过这并不意味着服务端的代码可以免去数据验证的工作,用户也可能使用 HT ...

  4. Centos-基础配置

    切换下载源到阿里云 备份 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup 下载新的 Cent ...

  5. [车联网/以太网] SOME/IP 协议

    概述: SOME/IP 协议 车载以太网协议栈总共可划分为5层: 物理层 数据链路层 网络层 传输层 应用层 其中本文所要描述的SOME/IP就是一种应用层协议. SOME/IP协议内容按照AUTOS ...

  6. 一文读懂 es6 中class方法中的this绑定

    一直以来有这么个疑问? class 的方法中没有自动的绑定this 为什么手动绑定之后,在绑定之后的方法里调用class中的其他的方法(这个方法为什么就能使用this,不也应该是null或者undef ...

  7. linux:用户管理

    用户账号添加.删除.修改以及用户密码的管理 用户组的管理 涉及三个文件: /etc/passwd    :存储用户的关键信息 /etc/group :存储用户组的关键信息 /etc/shadow :存 ...

  8. Matplotlab显示OpenCV读取到的图像

    Matplotlab显示OpenCV读取到的图像 一. 确认图像的数组类型 在使用 OpenCV 的 cv2.imread() 函数读取图像时,第二个参数(标志)决定了图像的读取方式.具体来说,0.1 ...

  9. 爬虫无限Debugger解决方案

    爬虫无限Debugger解决方案 在应对网站中的debugger语句以防止爬虫被调试时,一些网站会在代码中插入这些断点以干扰调试行为. 一种极端但直接的方法是通过禁用浏览器的断点激活功能来绕过所有de ...

  10. vue-element-template改为从后台获取菜单

    一.后端接口获取菜单信息 1.返回数据样式 { "code": 20000, "data": [{ "menuId": "2000 ...