需求描述:

客户网页上填一个Excel表格,数据存到数据库,这个导出接口要做的就是从数据库中的获取数据并填充到模板文件,最后通过response返给前端一个下载链接,用户即可获取填充好的Excel文件。

方案一:

一开始使用的是easypoi,发现当填充一行数据时是OK的,但是如果是多行数据,处理对象集合会抛异常,所以在小组长的建议下最终放弃选择使用EasyExcel;

方案二:

组长给了个图示 直接看懂 如下两图:

java word模版填充 java excel模板填充数据导出_ci

java word模版填充 java excel模板填充数据导出_java_02

 模糊的数据是模板数据不用关注,目的是往空格里填充数据

 左边模板,右边结果,一目了然,我觉得挺简单写了个demo也成功了(文件生成在本地)

后面我想着网上找找样例,把输出流设置到response里面应该不难,我自己写好了调试却发现一直报错,各种改都不行,我调试+修改搞了一上午,后面我跟组长汇报了情况,他说他来改,半小时就改好了。

我写的代码是这样的:

<!--EasyExcel-->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>easyexcel</artifactId>
			<version>3.1.1</version>
		</dependency>
@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<ReportDetailDO> 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();
        List<ReportDetailExcelDTO>list=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;
}

组长是这样写的:

<!--EasyExcel-->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>easyexcel</artifactId>
			<version>2.2.10</version>
		</dependency>
//省略获取数据对象集合的方法。。。(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!