SpringBoot导出Excel的四种方式
时间:2025-06-24 12:48:56 来源:新华社
【字体:  

 方法一:hutools


       该方法通过自研的一套Excel注解,在实体类上添加注解,然后用一套工具类(见源码中com.leixi.excel.util.excelOne)实现实体类列表的导出。优点是不用建模板,调用简单,缺点是迁移麻烦。有好几个配套的文件如注解,工具类等,想要在别的项目中使用,就涉及到文件的拷贝。老实说,不太优雅,而且更可惜的是,这些方法里居然没有封装导出方法。下面给出实体类创建,方法调用的代码,供各位参考(相关源码会在文中提供)

//引入依赖

                    cn.hutool            hutool-all            5.7.12                            cn.afterturn            easypoi-base            4.3.0        


 

//controller方法,不得不说,调用起来是真的方便    @PostMapping(value = "/exportData")    public ResponseEntity exportData(String fileName) {         List list = CommonUtil.buildDemoExcel(ExcelOneDto.class);        Workbook workbook = new DefaultWriteHandler().write("sheet名称",list, ExcelOneDto.class);        return CommonUtil.exportWorkbook(workbook, fileName);    }  //实体类@Datapublic class ExcelOneDto {     @ExcelCell(priority = "A", cellTitle = "编号")    private Integer code;     @ExcelCell(priority = "B", cellTitle = "名称")    private String name;      @ExcelCell(priority = "C", cellTitle = "详情")    private String desc;     @ExcelCell(priority = "D", cellTitle = "备注")    private String remark;}


这是导出的测试结果:

 方法二:easyexcel

       现在使用频率较高的是用easyexcel实现的。经过一番了解,我将easyexcel的实现方式也列出来作为参考。该方法的优点是使用方便,功能强大!本文中我只实现了最简单的导入导出,easyexcel还支持很多如嵌套导入,合并行列等高级操作,相关实现可以参考大神的博客【精选】Spring Boot 集成 EasyExcel 3.x 优雅实现Excel导入导出_easyexcel3-CSDN博客。 以下是我学习了他的博客后,整理的最基本的代码:

//引入maven依赖                    com.alibaba            easyexcel            3.1.3         //controller:    @PostMapping(value = "/exportData")    public void exportData(String fileName, HttpServletResponse response) {         try {             this.setExcelResponseProp(response, fileName);            List list = CommonUtil.buildDemoExcel(ExcelFourDto.class);;            EasyExcel.write(response.getOutputStream())                    .head(ExcelFourDto.class)                    .excelType(ExcelTypeEnum.XLSX)                    .sheet(fileName)                    .doWrite(list);        } catch (IOException e) {             throw new RuntimeException(e);        }    }     @PostMapping("/importData")    @SneakyThrows    public Object importUserExcel(@RequestPart("file") MultipartFile file) {             List list = EasyExcel.read(file.getInputStream())                    .head(ExcelFourDto.class).sheet().doReadSync();            return list;    }        /**     * 设置响应结果     *     * @param response    响应结果对象     * @param rawFileName 文件名     * @throws UnsupportedEncodingException 不支持编码异常     */    private void setExcelResponseProp(HttpServletResponse response, String rawFileName) throws UnsupportedEncodingException {         response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");        response.setCharacterEncoding("utf-8");        String fileName = URLEncoder.encode(rawFileName, "UTF-8").replaceAll("\\+", "%20");        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");    }  // 实体类@Datapublic class ExcelFourDto {     @ExcelProperty("编号")    @ColumnWidth(20)    private Integer code;     @ExcelProperty("名称")    @ColumnWidth(20)    private String name;     @ExcelProperty("详情")    @ColumnWidth(20)    private String desc;     @ExcelProperty("备注")    @ColumnWidth(20)    private String remark;}

      以下是测试结果:

方法三:ExcelImportUtil工具类

该方法的优点:不用excel模板,导出导出方便。缺点是封装的不够好。研发人员使用时需要对ExcelImportUtil进行一定的加工。下面是我封装后的代码:

//maven依赖
       

            cn.afterturn            easypoi-base            4.3.0        
//control类的导入导出     @PostMapping(value = "/importData")    public Object importManageData(@RequestPart("file") MultipartFile file) throws Exception {         return CommonUtil.getExcelDataFromFile(file, ExcelTwoDto.class, 1,2);    }     @PostMapping(value = "/exportData")    public ResponseEntity exportData(@RequestParam("fileName") String fileName){         List list  = CommonUtil.buildDemoExcel(ExcelTwoDto.class);        List> exportView = CommonUtil.buildExportView("测试Title", "测试Sheet",list);        Workbook workbook = ExcelExportUtil.exportExcel(exportView, ExcelType.XSSF);        ExcelStyleUtil.addNotExistCell(workbook, 0, 3);        return CommonUtil.exportWorkbook(workbook, fileName);    }    //实体类 @Data@Builder@NoArgsConstructor@AllArgsConstructorpublic class ExcelTwoDto {      @Excel(name = "第一列" ,fixedIndex = 0, orderNum = "0")    private String codeOne;    @Excel(name = "第二列" ,fixedIndex = 1, orderNum = "1", width = 50)    private String codeTwo;    @ExcelCollection(name = "第三列" , orderNum = "2")    private List codeThree;     @Excel(name = "第四列" ,fixedIndex = 4, orderNum = "4", width = 50)    private String codeFour;    @Excel(name = "第五列" ,fixedIndex = 5, orderNum = "5")    private String codeFive;    @Excel(name = "第六列A", groupName = "第六列汇总" ,fixedIndex = 6, orderNum = "6")    private String codeThreeOne;    @Excel(name = "第六列B", groupName = "第六列汇总" ,fixedIndex = 7, orderNum = "7")    private String codeThreeTwo;    @Excel(name = "第六列C", groupName = "第六列汇总" ,fixedIndex = 8, orderNum = "8")    private String codeThreeThree;} @Data@Builder@NoArgsConstructor@AllArgsConstructorpublic class ExcelChildDto {     @Excel(name = "编码" ,fixedIndex = 0, orderNum = "0")    private String code;    @Excel(name = "名称" ,fixedIndex = 1, orderNum = "1", width = 50)    private String name;}

   导出测试结果:


       

方法四:Excel模板导出

第三种方案是通过excel模板来实现的方法,现在基本已经废弃了,之所以放在这里是为了做一个参照,让大家看看不同的实现方法的区别。这种方式通过创建一个Excel模板和对应模板的实体类来实现文件导出,优点是实体类里不需要加注解了,而且在excel里可以设计一些style和格式,缺点是配置excelTemplate太麻烦了。配置繁琐,且过程中如出现参数名错误,符号错误等 ,调试起来很不方便,如果要增减字段,实体类和excel都得调整。下面给出编写的代码:

// controller方法    @PostMapping(value = "/exportData")    public ResponseEntity exportData(@RequestParam("fileName") String fileName) {         TemplateExportParams params = new TemplateExportParams("templates/template.xlsx");        params.setScanAllsheet(true);        Map dataMap = new HashMap<>();        List list  = CommonUtil.buildDemoExcel(ExcelThreeDto.class);        dataMap.put("titleName", "标题名称");        dataMap.put("desc", "备注名称");        dataMap.put("dataList", list);        Workbook workbook = ExcelExportUtil.exportExcel(params, dataMap);        ExcelStyleUtil.setAutoHeight(workbook, 0, 4);        return CommonUtil.exportWorkbook(workbook, fileName);    }    //实体类    @Data    @Builder    @NoArgsConstructor    @AllArgsConstructor    public class ExcelThreeDto {         private Integer code;        private String name;        private String desc;        private String remark;    }

        Excel模板的配置

        导出的结果:

        由于年代久远,我没能找到对应的模板导入的方法,于是在网上搜索了相关资料,编写了一个较通用的文件导入方法:

//maven依赖                    cn.afterturn            easypoi-base            4.3.0             /**     * excel 导入     */    @PostMapping("/importData")    public Object upload(@RequestParam(name = "file") MultipartFile file) {         return CommonUtil.importExcel(file, 3, ExcelThreeDto.class);    }     /**     * 通用的excel导入的方法     *     * @param file 导入文件     * @param startRow 第几行开始读数据     * @param clazz 导入后转成的实体类     * @return     * @param <T>      */    @SneakyThrows    public static <T> List<T> importExcel(MultipartFile file, Integer startRow, Class<T> clazz) {         Workbook wb = new XSSFWorkbook(file.getInputStream());        //1.2.获取Sheet        Sheet sheet = wb.getSheetAt(0);        List<T> list = new ArrayList<>();        Field[] fields = clazz.getDeclaredFields();        for (int rowNum = startRow; rowNum <= sheet.getLastRowNum(); rowNum++) {             //根据索引获取每一个行            Row row = sheet.getRow(rowNum);            T obj = clazz.newInstance();            for (int cellNum = 0; cellNum < row.getLastCellNum() && cellNum< fields.length; cellNum++) {                 Cell cell = row.getCell(cellNum);                Object value = CommonUtil.getCellValue(cell);                Field field = fields[cellNum];                field.setAccessible(true);                // 注意,这里是为了演示,只分析了Integer和String的写法,实际上要根据Field数据的枚举分类处理                if (field.getType().equals(Integer.class) && value != null) {                     field.set(obj, new Double(value.toString()).intValue());                } else {                     field.set(obj, value);                }            }            list.add(obj);        }        return list;    }

        导入的结果还是蛮令人满意的:

        原以为方法一已经是别开生面了,但是对比起来,仍然是有些差强人意。时代真是进步的飞快,对于程序员来说,这种变迁显得尤为明显。它就像一根鞭子,不断的抽打着码农们,稍有懈怠就会被这洪流所淹没…

        (文中附上四种方式的源码,仅用于学习和参考!)

本人力荐前两种方法,有大量的项目使用,相关的博客也比较多,尤其是easyexcel,官方对每种导入导出的方式都有完整的案例参考,简单上手!

[责任编辑:百度一下]
检察日报数字报 | 正义网 |
Copyrights©最高人民检察院 All Rights Reserved.