EasyExcel 的读写使用

最近在总结项目项目中用到的知识点,EasyExcel 是一个技术点:EasyExcel是一个基于Java的简单、省内存的读写Excel的开源项目。在尽可能节约内存的情况下支持读写百M的Excel。

我之前用过apache的poi技术来读取本地的excel文件,但是他有一个显著的缺点就是 在处理的数据非常多的时候,非常消耗内存,并且很容易出现异常的情况,所以在选择技术工具的时候选择了阿里的easyExcel。
因为我负责的项目采用的是spring boot框架,所以我这里主要讲解一下如何在spring boot项目里面集成EasyExcel

EasyExcel 官方文档说明 EasyExcel 文档使用说明,大家在使用的过程中可以参考者官方文档

一、 pom.xml 导入相关依赖

<!-- https://mvnrepository.com/artifact/com.alibaba/easyexcel -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>2.1.6</version>
        </dependency>

二、读取excel

  1. 编写相关的工具类

我在项目里面用到的是读取单个sheet ,但是有好多情况是需要调用多个sheet的,所以下面我也把读取多个sheet的方法写在了这里

 /**
     * 读取 Excel(多个 sheet)
     *
     * @param excel 文件
     * @param rowModel 实体类映射,继承 BaseRowModel 类
     * @return Excel 数据 list
     */
    public static List<Object> readExcel(MultipartFile excel, BaseRowModel rowModel) throws Exception {
    
    
        ExcelListener excelListener = new ExcelListener();
        ExcelReader reader = getReader(excel, excelListener);

        if (reader == null) {
    
    
            return null;
        }

        for (Sheet sheet : reader.getSheets()) {
    
    
            if (rowModel != null) {
    
    
                sheet.setClazz(rowModel.getClass());
            }
            reader.read(sheet);
        }

        return excelListener.getDatas();
    }

    /**
     * 读取某个 sheet 的 Excel
     *
     * @param excel 文件
     * @param rowModel 实体类映射,继承 BaseRowModel 类
     * @param sheetNo sheet 的序号 从1开始
     * @return Excel 数据 list
     */
    public static List<Object> readExcel(MultipartFile excel, BaseRowModel rowModel, int sheetNo) throws Exception {
    
    
        return readExcel(excel, rowModel, sheetNo, 1);
    }

    /**
     * 读取某个 sheet 的 Excel
     *
     * @param excel 文件
     * @param rowModel 实体类映射,继承 BaseRowModel 类
     * @param sheetNo sheet 的序号 从1开始
     * @param headLineNum 表头行数,默认为1
     * @return Excel 数据 list
     */
    public static List<Object> readExcel(MultipartFile excel, BaseRowModel rowModel, int sheetNo, int headLineNum) throws Exception {
    
    
        ExcelListener excelListener = new ExcelListener();
        ExcelReader reader = getReader(excel, excelListener);

        if (reader == null) {
    
    
            return null;
        }

        reader.read(new Sheet(sheetNo, headLineNum, rowModel.getClass()));

        return excelListener.getDatas();
    }

    /**
     * 返回 ExcelReader
     *
     * @param excel 需要解析的 Excel 文件
     * @param excelListener new ExcelListener()
     */
    private static ExcelReader getReader(MultipartFile excel, ExcelListener excelListener) throws Exception {
    
    
        String filename = excel.getOriginalFilename();
        if (filename == null || (!filename.toLowerCase().endsWith(".xls") && !filename.toLowerCase().endsWith(".xlsx"))) {
    
    
            throw new Exception("文件格式错误!");
        }
        InputStream inputStream;

        try {
    
    
            inputStream = new BufferedInputStream(excel.getInputStream());
            return new ExcelReader(inputStream, null, excelListener, false);
        } catch (IOException e) {
    
    
            e.printStackTrace();
        }

        return null;
    }

  1. 对应的相关实体类,需要加==@ExcelProperty==注解,在于你读取的excel的位置
@Data
public class CompanyPersonImportVo extends BaseRowModel {
    
    
	/**
     * 用名字去匹配,这里需要注意,如果名字重复,会导致只有一个字段
     * 读取到数据,所以建议使用索引来匹配(index 从0开始
     * 因为我需要导入的excel表格第一列是序号列,
     * 不需要,所以我设置的索引是从1开始,这个需要根据自己的实际情况)
     */
	@ColumnWidth(13) // 设置 Cell 宽度 (这个看自己的情况,按需引用)
    @ExcelProperty(value = "姓名", index = 1)
    private String name;

    @ExcelProperty(value = "性别", index = 2)
    private String sex;

    @ExcelProperty(value = "出生日期", index = 3)
    private String birthday;

    @ExcelProperty(value = "工作单位", index = 4)
    private String company;

    @ExcelProperty(value = "现任职级", index = 5)
    private String leval;

    @ExcelProperty(value = "任职时间", index = 6)
    private String workDay;

    @ExcelProperty(value = "备注", index = 7)
    private String remark;
}

在这里插入图片描述
3. Controller调用样例说明

 @PostMapping("assistUploadExcel")
 @ResponseBody
 public AjaxResult assistUploadExcel(MultipartFile fileupload) {
    
    
     Object objList = null;
     try {
    
    
         objList = ExcelUtil.readExcel(fileupload, new CompanyPersonImportVo(), 1, 3);
     } catch (Exception e) {
    
    
         return AjaxResult.error("导入失败!");
     }
     if (objList == null) {
    
    
         return AjaxResult.error("导入的数据不能为空");
     }
     List<CompanyPersonImportVo> orderList = (List) objList;
     if (orderList.size() > 0) {
    
    
         // orderList 其实就是我们将excel表格里面的一行行信息封装成一个个实体,存到List里面
         //接下来就是调用自己的Service 方法,对这些数据进行处理了
         return AjaxResult.success(map.get("msg"));
     }else {
    
    
         return AjaxResult.error("导入的数据不能为空");
     }
 }

这样我们读取表格的功能就写完了,接下我们来看读取excel表格

三、写excel

我在项目里面用到的是将一个列表信息 写到一个excel里面,并下载到本地(支持写 多个sheet),因为我用到的就是导出多个sheet,哈哈

导出一个sheet 相对的比较简单,原理是相同的。
在这里插入图片描述

  1. 编写导出工具类
 /**
     * @ClassName ExcelUtil
     * @Description : 用于生成指定目录的Excel不用ReisterConverter
     *
     * @param path
     * @param T
     * @param sheetName
     * @param res
     * @Return : boolean
     * @Author : zte
     * @Date : 2020/6/24 8:48
    */
    public static boolean generatorExcelWithoutConverter(String path, Class T, String sheetName, List<? extends Object> res){
    
    
        try{
    
    
            EasyExcel.write(path, T).sheet(sheetName).doWrite(res);
        }
        catch (Exception e){
    
    
            log.error(e.getMessage());
            return false;
        }
        return true;
    }
    /**
     * @ClassName ExcelUtil
     * @Description : 用于生成指定目录的Excel使用指定的ReisterConverter
     *
     * @param path
     * @param T
     * @param sheetName
     * @param res
     * @param converter
     * @Return : boolean
     * @Author : zte
     * @Date : 2020/6/24 8:51
    */

    public static boolean generatorExcelWithConverter(String path, Class T, String sheetName, List<? extends Object> res, Converter converter){
    
    
        try{
    
    
            EasyExcel.write(path, T).registerConverter(converter).sheet(sheetName).doWrite(res);
        }
        catch (Exception e){
    
    
            log.error(e.getMessage());
            return false;
        }
        return true;
    }

    //生成多个sheet
    public static boolean generatorExcelWithoutConverter(String filename, Class<Info> infoClass, String infoName, List<Info> infos, Class<DetailedInfoLog> detailedInfoLogClass, String allName, List<DetailedInfoLog> detailedInfoLogs, HttpServletResponse response) {
    
    
        try{
    
    
            ExcelWriter excelWriter = EasyExcel.write(filename).build();
            //获取sheet0对象
            WriteSheet mainSheet = EasyExcel.writerSheet(0, "sheet1Name").head(infoClass).build();
            //向sheet0写入数据 传入空list这样只导出表头
            excelWriter.write(infos,mainSheet);
            //获取sheet1对象
            WriteSheet detailSheet = EasyExcel.writerSheet(1, "sheet2Name").head(detailedInfoLogClass).build();
            //向sheet1写入数据 传入空list这样只导出表头
            excelWriter.write(detailedInfoLogs,detailSheet);
            excelWriter.finish();
        }
        catch (Exception e){
    
    
            log.error(e.getMessage());
            return false;
        }
        return true;
    }
  1. 编写对应的Controller Demo
@RequestMapping(value = "/saveExcel/{uiId}", method = RequestMethod.GET, produces = "application/json;charset=UTF-8")
@ResponseBody
public AjaxResult saveExcel(Model model,@PathVariable("uiId") Long uiId, HttpServletResponse response) throws IOException {
    
    

    DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd-HH-mm-ss");

    List<DetailedInfoLog> detailedInfoLog = detailedInfoLogService.list(....); //定义自己的查询条件
    List<DetailedInfoLog> detailedInfoLogs = detailedInfoLogService.list(....);
    
    String name = "asd";
    // 定义自己导出文件的名字
    String filename = URLEncoder.encode(name + '-' +  dateTimeFormatter.format(LocalDateTime.now()), "UTF-8");
    try{
    
    
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-disposition", "attachment;filename=" + filename + ".xlsx");
        List<Info> infos = new ArrayList<>();
        infos.add(info);

        //新建ExcelWriter
        ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).build();
        //获取sheet0对象
        WriteSheet mainSheet = EasyExcel.writerSheet(0, "健康档案").head(Info.class).build();
        //向sheet0写入数据 传入空list这样只导出表头
        excelWriter.write(infos,mainSheet);
        //获取sheet1对象
        WriteSheet detailSheet = EasyExcel.writerSheet(1, "所有病史").head(DetailedInfoLog.class).build();
        //向sheet1写入数据 传入空list这样只导出表头
        excelWriter.write(detailedInfoLogs,detailSheet);
        //关闭流
        excelWriter.finish();
    } catch (Exception var10) {
    
    
        response.reset();
        response.setContentType("application/json");
        response.setCharacterEncoding("utf-8");
        Map<String, String> map = new HashMap();
        map.put("status", "failure");
        map.put("message", "下载文件失败" + var10.getMessage());
        response.getWriter().println(JSON.toJSONString(map));
    }
    return AjaxResult.success();
}

到这里我们的操作就写完了。

猜你喜欢

转载自blog.csdn.net/qq_44922113/article/details/112695531
今日推荐