EasyExcel学习笔记

EasyExcel 用于 Java解析、生成Excel,是一个基于Java的简单、省内存的读写Excel的开源项目。在尽可能节约内存的情况下支持读写百M的Excel。

官方文档地址:https://alibaba-easyexcel.github.io/index.html

1.excel导出步骤

第一步,添加依赖。

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

第二步,创建实体类。在对应属性上添加注解 @ExcelProperty 来设置表头。

@Data
public class UserData {

    @ExcelProperty("用户编号")
    private int uid;

    @ExcelProperty("用户名称")
    private String username;

}

第三步,执行 excel 的导出。

/**
 * Parker
 **/
public class TestExcel {
    public static void main(String[] args) {
        //构建数据list集合
        List<UserData> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            UserData userData = new UserData();
            userData.setUid(i);
            userData.setUsername("user" + i);
            list.add(userData);
        }
        //设置excel文件路径和文件名称
        String fileName = "D:\\workplace\\IMedi_excel";
        //调用方法实现写操作
        EasyExcel.write(fileName, UserData.class)
                .sheet("用户信息")
                .doWrite(list);
    }
}

2.excel导入步骤

第一步,修改实体类。在注解 @ExcelProperty 上添加属性来指定属性所要读取的对应列号。

@Data
public class UserData {

    @ExcelProperty(value = "用户编号", index = 0)
    private int uid;

    @ExcelProperty(value = "用户名称", index = 1)
    private String username;

}

第二步,创建一个监听器。在监听器里编写读取方法。

@Slf4j
public class ExcelListener extends AnalysisEventListener<UserData> {

    /**
     * 1.一行一行读取excel内容,从第二行开始读取(不读取表头信息)
     * @param userData
     * @param analysisContext
     */
    @Override
    public void invoke(UserData userData, AnalysisContext analysisContext) {
        log.info(userData.toString());
    }

    /**
     * 2.读取表头信息
     * @param headMap
     * @param context
     */
    @Override
    public void invokeHead(Map<Integer, CellData> headMap, AnalysisContext context) {
        log.info("表头信息:{}",headMap);
    }

    /**
     * 3.读取之后执行
     * @param analysisContext
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        log.info("读取完成了...");
    }
}

第三步,执行 excel 的读取。

/**
 * Parker
 **/
public class TestExcel {
    public static void main(String[] args) {

        //设置excel文件路径和文件名称
        String fileName = "D:\\workplace\\IMedi_excel\\01.xlsx";
        //调用方法实现读操作
        EasyExcel.read(fileName,UserData.class,new ExcelListener()).sheet().doRead();
    }
}

读取成功,输出日志信息。

22:56:01.107 [main] DEBUG com.alibaba.excel.context.AnalysisContextImpl - Began to read:ReadSheetHolder{sheetNo=0, sheetName='用户信息'} com.alibaba.excel.read.metadata.holder.ReadSheetHolder@47db50c5
22:56:01.148 [main] INFO ExcelListener - 表头信息:{0=用户编号, 1=用户名称}
22:56:01.228 [main] INFO ExcelListener - UserData(uid=0, username=user0)
22:56:01.229 [main] INFO ExcelListener - UserData(uid=1, username=user1)
22:56:01.229 [main] INFO ExcelListener - UserData(uid=2, username=user2)
22:56:01.230 [main] INFO ExcelListener - UserData(uid=3, username=user3)
22:56:01.230 [main] INFO ExcelListener - UserData(uid=4, username=user4)
22:56:01.230 [main] INFO ExcelListener - UserData(uid=5, username=user5)
22:56:01.231 [main] INFO ExcelListener - UserData(uid=6, username=user6)
22:56:01.231 [main] INFO ExcelListener - UserData(uid=7, username=user7)
22:56:01.231 [main] INFO ExcelListener - UserData(uid=8, username=user8)
22:56:01.231 [main] INFO ExcelListener - UserData(uid=9, username=user9)
22:56:01.232 [main] INFO ExcelListener - 读取完成了...

4.从Web中导出excel

要导出 HttpServletResponse 的数据,需要编写相应的Controller和Service。

Controller

    /**
     * 导出数据字典到Excel
     * @param response
     * @return
     */
    @GetMapping("exportDictData")
    public void exportDictData(HttpServletResponse response){
        dictService.exportDictData(response);
    }

Service

    /**
     * 导出数据字典到Excel
     * @param response
     */
    @Override
    public void exportDictData(HttpServletResponse response) {
        //设置文件下载的请求头
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        // 这里URLEncoder.encode可以防止中文乱码,但是easyexcel不会发生中文乱码!
        //String fileName = URLEncoder.encode("imedi智慧健康服务数据字典", "UTF-8");
        String fileName = "imediDictData";
        response.setHeader("Content-disposition", "attachment;filename="+ fileName + ".xlsx");
        //查询数据库
        List<Dict> dictList = baseMapper.selectList(null);
        List<DictEeVo> dictEeVoList = new ArrayList<>();
        for (Dict dict : dictList) {
            DictEeVo dictEeVo = new DictEeVo();
            //springframework下的BeanUtils.copyProperties是左拷贝到右
            BeanUtils.copyProperties(dict,dictEeVo);
            dictEeVoList.add(dictEeVo);
        }
        //调用方法执行写操作
        try {
            EasyExcel.write(response.getOutputStream(),DictEeVo.class)
                    .sheet("DictData")
                    .doWrite(dictEeVoList);
        } catch (IOException e) {
            log.error(e.getMessage());
        }

    }

5.从Web中导入excel到数据库

要导入 excel 到后端,需要编写相应的Controller和Service。

Controller

/**
     * 从Web中导入数据字典excel到数据库
     * @param file 变量名最好为file,否则前端可能出错
     * @return
     */
    @PostMapping("importData")
    public Result importDictData(MultipartFile file){
        dictService.importDictData(file);
        return Result.ok();
    }

Service

    /**
     * 从Web中导入数据字典excel到数据库
     * @param file
     */
    @Override
    public void importDictData(MultipartFile file) {
        try {
            EasyExcel.read(file.getInputStream(),DictEeVo.class,new DictListener(baseMapper))
                    .sheet()
                    .doRead();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

其中导入需要多一步,即创建监听器。

listener

@Slf4j
public class DictListener extends AnalysisEventListener<DictEeVo> {

    private DictMapper dictMapper;

    /**
     * ExcelEasy 官方推荐使用构造方法来注入mapper,因为其不支持Spring的IOC
     * @param dictMapper
     */
    public DictListener(DictMapper dictMapper){
        this.dictMapper = dictMapper;
    }

    /**
     * 1.一行一行读取excel内容,从第二行开始读取(不读取表头信息)
     * @param dictEeVo
     * @param analysisContext
     */
    @Override
    public void invoke(DictEeVo dictEeVo, AnalysisContext analysisContext) {
        //调用方法添加到数据库
        Dict dict = new Dict();
        //springframework下的BeanUtils.copyProperties是左拷贝到右
        BeanUtils.copyProperties(dictEeVo,dict);
        dictMapper.insert(dict);
    }

    /**
     * 2.读取表头信息
     * @param headMap
     * @param context
     */
    @Override
    public void invokeHead(Map<Integer, CellData> headMap, AnalysisContext context) {
    }

    /**
     * 3.读取之后执行
     * @param analysisContext
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        log.info("导入完成了...");
    }

}

注:ExcelEasy 官方推荐使用构造方法来注入mapper,因为其不支持Spring的IOC。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐