0


EasyExcel实现excel导出(多sheet)

EasyExcel官方地址:

EasyExcel官方文档 - 基于Java的Excel处理工具 | Easy ExcelEasyExcel是一个基于Java的、快速、简洁、解决大文件内存溢出的Excel处理工具。他能让你在不用考虑性能、内存的等因素的情况下,快速完成Excel的读、写等功能。https://easyexcel.opensource.alibaba.com/

EasyExcel简介

Java领域解析、生成Excel比较有名的框架有Apache poi、jxl等。但他们都存在一个严重的问题就是非常的耗内存。如果你的系统并发量不大的话可能还行,但是一旦并发上来后一定会OOM或 者JVM频繁的full gc。
EasyExcel是阿里巴巴开源的一个excel处理框架,以使用简单、节省内存著称。EasyExcel能大大减少占用内存的主要原因是在解析Excel时没有将文件数据一次性全部加载到内存中,而是从磁盘上一 行行读取数据,逐个解析。
EasyExcel采用一行一行的解析模式,并将一行的解析结果以观察者的模式通知处理 (AnalysisEventListener)

SpringBoot整合easyexcel

easyexcel提供读、写、填充三种功能。这里我们采用模板填充的方式实现excel导出。

1.引入依赖

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>3.1.0</version>
</dependency>

2.模板文件

我们将模板excel放在resource下:

3.数据准备

4.数据传输对象

@Data
public class FtBranchDTO {
    /**
     * 部门名称
     */
    private String branchName;
    /**
     * 部门人数
     */
    private Integer branchPeople;
    /**
     * 部门电话
     */
    private String branchPhone;
    /**
     * 部门经理
     */
    private String branchManager;
    /**
     * 部门考评
     */
    private String branchGrade;
}

@Data
public class FtUserDTO {
    /**
     * 用户名称
     */
    private String name;
    /**
     * 用户年龄
     */
    private Integer age;
    /**
     * 用户手机号
     */
    private String phone;
    /**
     * 性别
     */
    private String sex;
    /**
     * 成绩
     */
    private BigDecimal grade;
}

@Data
public class GradeAvgDTO {
    /**
     * 员工平均分
     */
    private BigDecimal userAverage;
}

@Data
public class PeopleSumDTO {
    /**
     * 公司总人数
     */
    private Integer sum;
}

4.导出excel

@Slf4j
@RestController
@RequestMapping("/excelExport")
public class ExcelExportController {
    
    @Autowired
    private FtUserService ftUserService;

    @Autowired
    private FtBranchService ftBranchService;

    @GetMapping
    public void excelExport(HttpServletResponse response){
        //员工信息  平均成绩
        List<FtUserEntity> ftUserEntities = ftUserService.list();
        List<FtUserDTO> ftUserDTOS = ftUserEntities.stream().map(ftUserEntity -> {
            FtUserDTO ftUserDTO = new FtUserDTO();
            BeanUtils.copyProperties(ftUserEntity,ftUserDTO);
            return ftUserDTO;
        }).collect(Collectors.toList());
        GradeAvgDTO gradeAvgDTO = ftUserService.getAverageGrade();
        //部门信息 员工总数
        List<FtBranchEntity> ftBranchEntities = ftBranchService.list();
        List<FtBranchDTO> ftBranchDTOS = ftBranchEntities.stream().map(ftBranchEntity -> {
            FtBranchDTO ftBranchDTO = new FtBranchDTO();
            BeanUtils.copyProperties(ftBranchEntity,ftBranchDTO);
            return ftBranchDTO;
        }).collect(Collectors.toList());
        PeopleSumDTO peopleSumDTO =  ftBranchService.getPeopleSum();

        //获取模板(模板你可以放在任何位置,前提是你能获取到。这里放在resource下)
        ClassPathResource couponOrderTemplateResource = new ClassPathResource("userInfo.xlsx");

        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        String excelFileName = URLEncoder.encode("公司信息", StandardCharsets.UTF_8)
                .replaceAll("\\+", "%20");
        response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
        // attachment这个代表要下载的,如果去掉就直接打开了(attachment-作为附件下载,inline-在线打开)
        // excelFileName是文件名,另存为或者下载时,为默认的文件名
        response.setHeader("Content-disposition","attachment;filename=" + excelFileName + ".xlsx");
        response.setHeader("Content-Type","application/octet-stream;charset=utf-8");

        InputStream templateInputStream = null;
        ExcelWriter excelWriter = null;
        WriteSheet userSheet = null;
        WriteSheet branchSheet = null;
        ServletOutputStream outputStream = null;

        try {
            outputStream = response.getOutputStream();
            templateInputStream = couponOrderTemplateResource.getInputStream();
        } catch (IOException e) {
            log.error("获取模板失败");
        }

        // 这里注意 入参用了forceNewRow 代表在写入list的时候不管list下面有没有空行 都会创建一行,然后下面的数据往后移动。默认 是false,会直接使用下一行,如果没有则创建。
        // forceNewRow 如果设置了true,有个缺点 就是他会把所有的数据都放到内存了,所以慎用
        // 简单的说 如果你的模板有list,且list不是最后一行,下面还有数据需要填充 就必须设置 forceNewRow=true 但是这个就会把所有数据放到内存 会很耗内存
        // 如果数据量大 list不是最后一行 参照下一个
        FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
        excelWriter = EasyExcel.write(outputStream).withTemplate(templateInputStream).build();

        //创建第一个sheet
        userSheet = EasyExcel.writerSheet("员工信息").build();
        //填充
        excelWriter.fill(ftUserDTOS,fillConfig,userSheet);//员工基础信息
        excelWriter.fill(gradeAvgDTO,userSheet);//员工平均成绩
        //创建第二个sheet
        branchSheet = EasyExcel.writerSheet("部门信息").build();
        //填充
        excelWriter.fill(ftBranchDTOS,fillConfig,branchSheet);//部门基础信息
        excelWriter.fill(peopleSumDTO,branchSheet);//总人数

        //关闭
        excelWriter.finish();
        IOUtils.closeQuietly(templateInputStream);
        IOUtils.closeQuietly(outputStream);
        IOUtils.closeQuietly(excelWriter);
    }
}

5.测试excel导出

效果图如下:


本文转载自: https://blog.csdn.net/asdksd/article/details/127121892
版权归原作者 抓码男孩 所有, 如有侵权,请联系我们删除。

“EasyExcel实现excel导出(多sheet)”的评论:

还没有评论