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","施工单位");
}
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
@Excel注解是Spring Boot中的一个注解,用于将Java对象映射到Excel表格。它可以帮助开发人员快速地实现将数据导出Excel文件的功能。 @Excel注解有以下几个属性: 1. name:指定Excel表格的名称。 2. orderNum:指定Excel表格的顺序。 3. width:指定Excel表格的宽度。 4. isImportField:指定是否导入该字段,默认为true。 5. isExportField:指定是否导出该字段,默认为true。 6. dateFormat:指定日期格式化。 7. replace:指定替换内容。 使用@Excel注解的步骤如下: 1. 在实体类中添加@Excel注解,指定属性的名称、顺序、宽度等。 2. 使用EasyExcel或其他Excel操作库,将数据导出Excel文件。 3. 使用EasyExcel或其他Excel操作库,将Excel文件导入为Java对象。 以下是一个使用@Excel注解的示例: ``` public class User { @Excel(name = "姓名", orderNum = "0", width = 20) private String name; @Excel(name = "年龄", orderNum = "1", width = 20) private Integer age; // 省略getter和setter方法 } ``` 在上面的示例中,我们使用@Excel注解指定了User类中的name和age属性在Excel表格中的名称、顺序和宽度。 使用EasyExcel导出User对象为Excel文件的代码如下: ``` @Component public class UserExcelService { public void export(List<User> userList) { try { String fileName = "user.xlsx"; ServletOutputStream out = response.getOutputStream(); response.setContentType("multipart/form-data"); response.setHeader("Content-Disposition", "attachment;fileName=" + fileName); ExcelWriter writer = EasyExcel.write(out).build(); WriteSheet sheet = EasyExcel.writerSheet("用户信息").build(); writer.write(userList, sheet); writer.finish(); } catch (Exception e) { e.printStackTrace(); } } } ``` 使用EasyExcelExcel文件导入为User对象的代码如下: ``` @Component public class UserExcelService { public List<User> import(MultipartFile file) { try { InputStream in = file.getInputStream(); List<User> userList = EasyExcel.read(in).head(User.class).sheet().doReadSync(); return userList; } catch (Exception e) { e.printStackTrace(); } return null; } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一只牛博

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值