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","施工单位");
}
相关文章
|
2天前
|
前端开发 Java
基于Java爬取微博数据(二) 正文长文本+导出数据Excel
【5月更文挑战第12天】基于Java爬取微博数据,正文长文本+导出数据Excel
|
7天前
|
Java 关系型数据库 MySQL
【MySQL × SpringBoot 突发奇想】全面实现流程 · xlsx文件,Excel表格导入数据库的接口(下)
【MySQL × SpringBoot 突发奇想】全面实现流程 · xlsx文件,Excel表格导入数据库的接口
46 0
|
7天前
|
Java 关系型数据库 MySQL
【MySQL × SpringBoot 突发奇想】全面实现流程 · xlsx文件,Excel表格导入数据库的接口(上)
【MySQL × SpringBoot 突发奇想】全面实现流程 · xlsx文件,Excel表格导入数据库的接口
50 0
|
8天前
|
Java
java导出复杂excel
java导出复杂excel
|
4天前
|
JSON Rust 前端开发
【sheetjs】纯前端如何实现Excel导出下载和上传解析?
本文介绍了如何使用`sheetjs`的`xlsx`库在前端实现Excel的导出和上传。项目依赖包括Vite、React、SheetJS和Arco-Design。对于导出,从后端获取JSON数据,通过`json_to_sheet`、`book_new`和`writeFile`函数生成并下载Excel文件。对于上传,使用`read`函数将上传的Excel文件解析为JSON并发送至后端。完整代码示例可在GitHub仓库[fullee/sheetjs-demo](https://github.com/fullee/sheetjs-demo)中查看。
36 10
|
6天前
|
开发框架 资源调度 JavaScript
uniapp本地导出表格excel
uniapp本地导出表格excel
|
7天前
|
前端开发 关系型数据库 MySQL
【MySQL × SpringBoot 突发奇想】全面实现流程 · 数据库导出Excel表格文件的接口
【MySQL × SpringBoot 突发奇想】全面实现流程 · 数据库导出Excel表格文件的接口
38 0
|
8天前
|
JavaScript
vue导出excel无法打开问题
vue导出excel无法打开问题
|
8天前
|
easyexcel BI
excel合并列导出文件
excel合并列导出文件
|
8天前
|
前端开发
基于jeecgboot的flowable流程任务excel导出功能
基于jeecgboot的flowable流程任务excel导出功能
15 1