springboot优雅的实现excel的导出(自适应列宽实现,中文也行),复制可用

简介: springboot优雅的实现excel的导出(自适应列宽实现,中文也行),复制可用

springboot实现excel的导出(自适应列宽实现)

【说明】废话不多说,直接就是干,⛳️

首先是环境准备

1️⃣:这里我就直接贴出用到的相关maven坐标了

<dependency>
  <groupId>cn.hutool</groupId>
  <artifactId>hutool-all</artifactId>
  <version>5.3.8</version>
</dependency>
<dependency>
  <groupId>org.apache.poi</groupId>
  <artifactId>poi</artifactId>
  <version>4.1.2</version>
</dependency>
<dependency>
  <groupId>org.apache.poi</groupId>
  <artifactId>poi-ooxml</artifactId>
  <version>4.1.2</version>
</dependency>

【警告】这里根据自己的需求确定版本号

接下来就是上正餐了

【说明】首先对于excel的导出,前端调用接口最后的响应类型要为blob,不然你导出的excel会显示损坏以及打不开

1️⃣: 直接贴代码如下:

public void exportFundOutExcel(HttpServletResponse response, @RequestBody Map<String, Object> data) {
  ExcelWriter writer = ExcelUtil.getBigWriter();
  // 设置默认的行高
  writer.setDefaultRowHeight(20);
  try {
    // 获取数据
    List<Map<String, Object>> list = service.getList(data);
    String messages = "这是excel的第一行(内容自己看)";
    // 这里正常情况是要放到常量类中的,这里为了大家看清楚,或者复制直接用,这里的key要对应上面查出来的Map中的key,这里的value对应的就是你的excel表头了
    public static final Map<String,String> FUNDS_OUT_EXCEL_MAP = new LinkedHashMap<>(3);
    static {
      FUNDS_OUT_EXCEL_MAP.put("projectName","所属项目");
      FUNDS_OUT_EXCEL_MAP.put("managementUnit","建设单位");
      FUNDS_OUT_EXCEL_MAP.put("constructionUnit","施工单位");
    }
    // 表头信息
    writer.merge(FUNDS_OUT_EXCEL_MAP.size() - 1
                 , messages
                 , true);
    FUNDS_OUT_EXCEL_MAP.forEach(writer::addHeaderAlias);
    // 仅仅获取取别名的字段
    writer.setOnlyAlias(true);
    // 一定要先进性写入数据,再设置列宽
    writer.write(list, true);
    // 获取当前工作表,需要注意的是,SXSSFSheet 在处理大数据量的 Excel 文件时非常有用,但对于小型文件,使用 XSSFSheet(基于内存)可能更为合适。
    SXSSFSheet sheet = (SXSSFSheet) writer.getSheet();
    // 这里的代码就是实现自适应列宽
    //--------------------------------
    writer.setSheet(sheet);
    // 这里默认会只显示后100行数据,所以在设置的时候会Row row = this.sheet.getRow(rownum);row为null
    //            writer.setRowHeight(3,30000);
    response.resetBuffer();
    response.setContentType("application/octet-stream;charset=utf-8");
    response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode("测试.xlsx", "UTF-8"));
    writer.flush(response.getOutputStream());
  } catch (Exception e) {
    // 异常处理
  } finally {
    // 关闭writer,释放内存
    writer.close();
  }
}

下面的两种方式都可以放到上面的代码的// 这里的代码就是实现自适应列宽

//--------------------------------这个下

2️⃣:如果是excel中没有涉及到中文的话,那么可以用这种方式实现

// 这里不进行追踪的话会报错,Could not auto-size column. Make sure the column was tracked prior to auto-sizing the column.
// 跟踪所有列
sheet.trackAllColumnsForAutoSizing();
for (int i = 0; i < LotConstants.FUNDS_OUT_EXCEL_MAP.size(); i++) {
  sheet.autoSizeColumn(i);
}
int columnCount = LotConstants.FUNDS_OUT_EXCEL_MAP.size();

上面的代码我也都做了注释,大致就是必须要先执行追踪,然后再执行下面的,这个对于非中文的excel还是能做到列宽自适应的,已验证

但是对于大部分的情况下,都是含有中文的,那么就需要自己去实现了,目前我还没发现有自带的,具体实现如下

// 获取最大列宽
for (int i = 0; i < columnCount; i++) {
  final int[] maxColumnWidth = {0};
  int finalI = i;
  // 流处理,异步设置最大列宽
  IntStream.range(0, sheet.getLastRowNum() + 1).parallel().forEach(rowIndex -> {
    Row row = sheet.getRow(rowIndex);
    Cell cell = row.getCell(finalI);
    if (cell != null) {
      // 这里选择将所有格式的都转化为String类型,防止报错->Cannot get a STRING value from a NUMERIC cell
      DataFormatter dataFormatter = new DataFormatter();
      String cellValue = dataFormatter.formatCellValue(cell);
      // String cellValue = cell.getStringCellValue();
      int cellWidth = cellValue.getBytes(StandardCharsets.UTF_8).length;
      if (cellWidth > maxColumnWidth[0]) {
        maxColumnWidth[0] = cellWidth;
      }
    }
  });
  // 设置列宽,这里之所以要乘256,点进去这个方法可以看到Set the width (in units of 1256th of a character width) The maximum column width for an individual cell is 255 characters.
  // 至于200就是偏移量
  sheet.setColumnWidth(i, maxColumnWidth[0] * 256 + 200);
}

完事收工,亲测可用,如果不行请call我,一定是你哪里cv错了

补充一下上面的FUNDS_OUT_EXCEL_MAP常量,这个其实就是为了设置excel的表头,以及对应我们查询出来的字段名,大致如下:

public static final Map<String,String> FUNDS_OUT_EXCEL_MAP = new LinkedHashMap<>(3);
static {
  FUNDS_OUT_EXCEL_MAP.put("projectName","所属项目");
  FUNDS_OUT_EXCEL_MAP.put("managementUnit","建设单位");
  FUNDS_OUT_EXCEL_MAP.put("constructionUnit","施工单位");
}
相关文章
|
26天前
|
SQL 缓存 easyexcel
面试官问10W 行级别数据的 Excel 导入如何10秒处理
面试官问10W 行级别数据的 Excel 导入如何10秒处理
53 0
|
1月前
|
NoSQL 关系型数据库 MySQL
多人同时导出 Excel 干崩服务器?怎样实现一个简单排队导出功能!
业务诉求:考虑到数据库数据日渐增多,导出会有全量数据的导出,多人同时导出可以会对服务性能造成影响,导出涉及到mysql查询的io操作,还涉及文件输入、输出流的io操作,所以对服务器的性能会影响的比较大;结合以上原因,对导出操作进行排队; 刚开始拿到这个需求,第一时间想到就是需要维护一个FIFO先进先出的队列,给定队列一个固定size,在队列里面的人进行排队进行数据导出,导出完成后立马出队列,下一个排队的人进行操作;还考虑到异步,可能还需要建个文件导出表,主要记录文件的导出情况,文件的存放地址,用户根据文件列表情况下载导出文件。
多人同时导出 Excel 干崩服务器?怎样实现一个简单排队导出功能!
|
2月前
|
XML Java 数据格式
使用Freemarker模版导出xls文件使用excel打开提示文件损坏
使用Freemarker模版导出xls文件使用excel打开提示文件损坏
63 0
|
2月前
|
存储 Java Apache
Spring Boot整合OpenOffice实现Word、Excel、PPT在线预览
Spring Boot整合OpenOffice实现Word、Excel、PPT在线预览
140 0
|
9天前
|
easyexcel 数据库
公司大佬对excel导入、导出的封装,那叫一个秒啊
封装公司统一使用的组件的主要目标是为了简化开发人员的调用流程,避免各个项目组重复集成和编写不规范的代码。文中提到对阿里EasyExcel进行了二次封装,提供了导入和导出功能,并支持模板的导入和导出。此外,还处理了读取数据与实际保存数据不一致的情况,通过提供自定义转换器来解决。
32 0
|
9天前
|
数据库
开发指南009-从list导出excel文件
从数据库返回一般是对象的列表,平台底层提供了从list转为excel文件的方法
|
9天前
|
前端开发
开发指南007-导出Excel
平台上开发导出Excel比过去的单体架构要复杂些,因为前端和后台不在一个进程空间里。
|
1月前
|
数据采集 移动开发 前端开发
springboot使用html模版导出pdf文档
springboot使用html模版导出pdf文档
|
1月前
|
Java easyexcel 应用服务中间件
【二十五】springboot使用EasyExcel和线程池实现多线程导入Excel数据
【二十五】springboot使用EasyExcel和线程池实现多线程导入Excel数据
216 0
|
1月前
|
SQL Java easyexcel
【Java】百万数据excel导出功能如何实现
【Java】百万数据excel导出功能如何实现
144 0