需求描述:
客户网页上填一个Excel表格,数据存到数据库,这个导出接口要做的就是从数据库中的获取数据并填充到模板文件,最后通过response返给前端一个下载链接,用户即可获取填充好的Excel文件。
方案一:
一开始使用的是easypoi,发现当填充一行数据时是OK的,但是如果是多行数据,处理对象集合会抛异常,所以在小组长的建议下最终放弃选择使用EasyExcel;
方案二:
组长给了个图示 直接看懂 如下两图:
模糊的数据是模板数据不用关注,目的是往空格里填充数据
左边模板,右边结果,一目了然,我觉得挺简单写了个demo也成功了(文件生成在本地)
后面我想着网上找找样例,把输出流设置到response里面应该不难,我自己写好了调试却发现一直报错,各种改都不行,我调试+修改搞了一上午,后面我跟组长汇报了情况,他说他来改,半小时就改好了。
我写的代码是这样的:
com.alibaba easyexcel 3.1.1
@GetMapping("/exportExcel") @ApiOperation(value = "导出", notes = "导出", httpMethod = "GET") @ApiImplicitParams(value = { @ApiImplicitParam(name = "code", paramType = "query", value = "单位编码", required = true, dataType = "String", example = "12312311") }) public void exportExcel(@RequestParam String code, HttpServletResponse response)throws Exception { reportService.exportExcel(code, response); }
@Override public void exportExcel(String code, HttpServletResponse response) throws Exception{ //先查询详情列表是否存在 List reportDetailDOS = reportDetailDAO.select( ReportDetailDO.builder() .code(code) .build()); //不存在时抛异常——未查询到填报记录 if (CollectionUtils.isEmpty(reportDetailDOS)) { throw new BusException(ResultEnum.NO_FILLED_IN_RECORDS_FOUND); } ReportOrgDO reportOrgDO = reportOrgDAO.selectOne( ReportOrgDO.builder() .code(code) .build()); String templateFileName = "template/vnd.xlsx"; // 这里URLEncoder.encode可以防止中文乱码 String fileName = URLEncoder.encode(reportOrgDO.getName() + TABLE_NAME+".xlsx", "UTF-8").replaceAll("\\+", "%20"); //文件名=公司名+表名 response.setCharacterEncoding("UTF-8"); response.setHeader("content-Type", "application/vnd.ms-excel"); response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8")); ServletOutputStream outputStream = response.getOutputStream(); InputStream templateFile = this.getClass().getClassLoader().getResourceAsStream(templateFileName); ExcelWriter excelWriter = EasyExcel.write(outputStream).withTemplate(templateFile).build(); WriteSheet writeSheet = EasyExcel.writerSheet().build(); //开启自动换行,自动换行表示每次写入一条list数据是都会重新生成一行空行,此选项默认是关闭的,需要提前设置为true FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build(); Listlist=OrikaHelper.convertList(reportDetailDOS, ReportDetailExcelDTO.class);excelWriter.fill(list, fillConfig, writeSheet); excelWriter.finish();}
用户导出过度的类如下:
@Data@NoArgsConstructor@AllArgsConstructor@ApiModel("汇报详情Excel")public class ReportDetailExcelDTO { @ExcelProperty("2019年度") private String content1; @ExcelProperty("2020年度") private String content2; @ExcelProperty("2021年度") private String content3; @ExcelProperty("2022年度") private String content4; @ExcelProperty("备注") private String remark;}
组长是这样写的:
com.alibaba easyexcel 2.2.10
//省略获取数据对象集合的方法。。。(list) String templateFileName = "template/vnd.xlsx"; // 这里URLEncoder.encode可以防止中文乱码 String fileName = URLEncoder.encode(reportOrgDO.getName() + TABLE_NAME + ".xlsx", "UTF-8") .replaceAll("\\+", "%20"); //文件名=公司名+表名 response.setCharacterEncoding("UTF-8"); response.setHeader("content-Type", "application/vnd.ms-excel"); response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));//ReportDetailDO是数据对象的泛型 相当于数据库的实体类 不需要加特殊的EasyExcel注解 InputStream templateFile = this.getClass().getClassLoader().getResourceAsStream(templateFileName); EasyExcel.write(response.getOutputStream(), ReportDetailDO.class) .withTemplate(templateFile).sheet().doFill(Optional.ofNullable(list).orElse(new ArrayList<>()));
组长简简单单改了下依赖的版本,业务代码写了几行然后云淡风轻告诉我可以了,我当时真的很不理解,心情很复杂,一方面觉得自己为什么搞不出来,另外觉得像改变版本这种问题真的很难找到排查出来,经历这件事让我觉得,同样是程序员,有的人还在埋头苦苦调试找原因,有的人轻而易举的可以找到问题并修改,阅历和经验决定了你的实力,自己还是太嫩,路漫漫其修远兮...
另外我发现我用postman居然测不成功,最后用swagger才能返回一个下载链接,无语。。。
这件事给我的启发是,不要新高气傲觉得一切OK的样子,实际上如果网上没有一些开源代码,自己是很难顺利完成某个业务的编写,还是要对技术保持敬畏,自己平时要学会复盘和总结,争取不会被同一个问题难倒两次。另外还要感谢为我们开路的大佬,正所谓前人种树,后人乘凉,respect!
来源地址:https://blog.csdn.net/m0_58946819/article/details/130929273