EasyExcel读与写

举报
多米诺的古牌 发表于 2021/04/29 10:21:44 2021/04/29
【摘要】 EasyExcel是阿里巴巴开源的一个excel处理框架,以使用简单,节省内存著称,EasyExcel能大大减少占用内存的主要原因是在解析Excel时没有将文件数据一次性全部加载到内存中,而是从磁盘上一行行读取数据,逐个解析。相对于poi个人感觉更加轻量与简捷,很容易上手,并且操作简单。1.首先依然是导入依赖<dependency>  <groupId>com.alibaba</groupI...

EasyExcel是阿里巴巴开源的一个excel处理框架,以使用简单,节省内存著称,EasyExcel能大大减少占用内存的主要原因是在解析Excel时没有将文件数据一次性全部加载到内存中,而是从磁盘上一行行读取数据,逐个解析。

相对于poi个人感觉更加轻量与简捷,很容易上手,并且操作简单。

1.首先依然是导入依赖

<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>easyexcel</artifactId>
  <version>版本</version>
</dependency>

<!--xls-->
<dependency>
  <groupId>org.apache.poi</groupId>
  <artifactId>poi</artifactId>
  <version>版本</version>
</dependency>
<dependency>
  <groupId>org.apache.poi</groupId>
  <artifactId>poi-ooxml</artifactId>
  <version>版本</version>
</dependency>

2.创建实体类

这里EasyExcel与poi的区别在于,提供了很多注解,可以更加方便灵活的配置字段,常用的注解有:

  • ExcelProperty index 指定写到第几列,默认根据成员变量排序。value指定写入的名称,默认成员变量的名字,多个value可以参照快速开始中的复杂头
  • ExcelIgnore 默认所有字段都会写入excel,这个注解会忽略这个字段
  • DateTimeFormat 日期转换,将Date写到excel会调用这个注解。里面的value参照java.text.SimpleDateFormat
  • NumberFormat 数字转换,用Number写excel会调用这个注解。里面的value参照java.text.DecimalFormat
  • ExcelIgnoreUnannotated 默认不加ExcelProperty 的注解的都会参与读写,加了不会参与

写表格的例子:

@Data
public class DemoData {
    //设置excel表头名称
    @ExcelProperty(value = "学号",index = 0)
    private Integer numbers;
    @ExcelProperty(value = "姓名",index = 1)
    private String name;
}

执行方法:

public class Test {

    public static void main(String[] args) {

        //实现excel写的操作
        //1 设置写入文件夹地址和excel文件名称
        String filename = "D:\\test.xlsx";
       // 2 调用easyexcel里面的方法实现写操作
       // write方法两个参数:第一个参数文件路径名称,第二个参数实体类class
        EasyExcel.write(filename,DemoData.class).sheet("输出表").doWrite(getData());

    }

    //创建方法返回list集合
    private static List<DemoData> getData() {
        List<DemoData> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            DemoData data = new DemoData();
            data.setNumbers(100+i);
            data.setName("学生"+i);
            list.add(data);
        }
        return list;
    }
}

效果图:

读和写的注解类似,有如下注解:

  • ExcelProperty 指定当前字段对应excel中的那一列。可以根据名字或者Index去匹配。
  • ExcelIgnore 默认所有字段都会和excel去匹配,加了这个注解会忽略该字段
  • DateTimeFormat 日期转换,用String去接收excel日期格式的数据会调用这个注解。里面的value参照java.text.SimpleDateFormat
  • NumberFormat 数字转换,用String去接收excel数字格式的数据会调用这个注解。里面的value参照java.text.DecimalFormat
  • ExcelIgnoreUnannotated 默认不加ExcelProperty 的注解的都会参与读写,加了不会参与

通用参数

WriteWorkbook,WriteSheet ,WriteTable都会有的参数,如果为空,默认使用上级。

  • converter 转换器,默认加载了很多转换器。也可以自定义。
  • writeHandler 写的处理器。可以实现WorkbookWriteHandler,SheetWriteHandler,RowWriteHandler,CellWriteHandler,在写入excel的不同阶段会调用
  • relativeHeadRowIndex 距离多少行后开始。也就是开头空几行
  • needHead 是否导出头
  • head  与clazz二选一。写入文件的头列表,建议使用class。
  • clazzhead二选一。写入文件的头对应的class,也可以使用注解。
  • autoTrim 字符串、表头等数据自动trim

WriteWorkbook(理解成excel对象)参数

  • excelType 当前excel的类型 默认xlsx
  • outputStreamfile二选一。写入文件的流
  • fileoutputStream二选一。写入的文件
  • templateInputStream 模板的文件流
  • templateFile 模板文件
  • autoCloseStream 自动关闭流。
  • password 写的时候是否需要使用密码
  • useDefaultStyle 写的时候是否是使用默认头

WriteSheet(excel的一个Sheet)参数

  • sheetNo 需要写入的编码。默认0
  • sheetName 需要些的Sheet名称,默认同sheetNo

WriteTable(就把excel的一个Sheet,一块区域看一个table)参数

  • tableNo 需要写入的编码。默认0

举个读取的表格的例子:

1.依然是创建实体类

@Data
public class User  {

    @ExcelProperty(index = 0)
    private String name;

    @ExcelProperty(index = 1)
    private int age;

}

2.创建监听器,用于解析读取的数据,这里需要注意的点,因为业务层的Listener 并没有交给Spring容器来管理,所以监听器代码无法注入Service ,

这里通过构造方法的方式传过来,从而完成对数据库的操作

/**
 * 每解析一行会回调invoke()方法。
 * 整个excel解析结束会执行doAfterAllAnalysed()方法
 */

//有个很重要的点,不能被spring管理,要每次读取excel都要new。
public class UserDataListener extends AnalysisEventListener<User> {

    Logger logger = LoggerFactory.getLogger(UserDataListener.class);

    //每次读取100条数据就进行保存操作
    private static final int BATCH_COUNT = 100;
    //由于每次读都是新new UserDataListener的,所以这个list不会存在线程安全问题
    List<User> list = new ArrayList<>();

    //这个组件是Spring中的组件,这边推荐两种方法注入这个组件
    //第一种就是提供一个UserDataListener的构造方法,这个方法提供一个参数是UserDataListener类型
    //另外一种方法就是将 UserDataListener 这个类定义成 UserService 实现类的内部类(推荐这种方式)
    //private UserService userService;

    @Override
    public void invoke(User data, AnalysisContext analysisContext) {
        logger.info("解析到一条数据:{}", JSON.toJSONString(data));
        list.add(data);
        if (list.size() >= BATCH_COUNT) {
            saveData();
            // 存储完成清理 list
            list.clear();
        }
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        // 这里也要保存数据,确保最后遗留的数据也存储到数据库
        saveData();
        logger.info("所有数据解析完成!");
    }

    private void saveData() {
        logger.info("{}条数据,开始存储数据库!", list.size());
        //保存数据
        //userService.save(list);
        logger.info("存储数据库成功!");
    }

}

3.执行读取方法,调用监听器解析读取的数据

public class EasyExcelDemo {

    public static void main(String[] args) throws Exception {
        InputStream fis = new FileInputStream("D:\\user.xlsx");

        AnalysisEventListener listener = new UserDataListener();

        ExcelReader excelReader = EasyExcel.read(fis, User.class, listener).build();
        ReadSheet readSheet = EasyExcel.readSheet(0).build();
        ReadSheet readSheet2 = EasyExcel.readSheet(1).build();
        excelReader.read(readSheet);
        // 这里千万别忘记关闭,读的时候会创建临时文件,到时磁盘会崩的
        excelReader.finish();
    }

}

经过上述三步就可以完成EasyExcel的读取解析工作了。

通用参数

ReadWorkbook,ReadSheet 都会有的参数,如果为空,默认使用上级。

  • converter 转换器,默认加载了很多转换器。也可以自定义。
  • readListener 监听器,在读取数据的过程中会不断的调用监听器。
  • headRowNumber 需要读的表格有几行头数据。默认有一行头,也就是认为第二行开始起为数据。
  • head  与clazz二选一。读取文件头对应的列表,会根据列表匹配数据,建议使用class。
  • clazzhead二选一。读取文件的头对应的class,也可以使用注解。如果两个都不指定,则会读取全部数据。
  • autoTrim 字符串、表头等数据自动trim
  • password 读的时候是否需要使用密码

ReadWorkbook(理解成excel对象)参数

  • excelType 当前excel的类型 默认会自动判断
  • inputStreamfile二选一。读取文件的流,如果接收到的是流就只用,不用流建议使用file参数。因为使用了inputStream easyexcel会帮忙创建临时文件,最终还是file
  • fileinputStream二选一。读取文件的文件。
  • autoCloseStream 自动关闭流。
  • readCache 默认小于5M用 内存,超过5M会使用 EhCache,这里不建议使用这个参数。
  • useDefaultListener @since 2.1.4 默认会加入ModelBuildEventListener 来帮忙转换成传入class的对象,设置成false后将不会协助转换对象,自定义的监听器会接收到Map<Integer,CellData>对象,如果还想继续接听到class对象,请调用readListener方法,加入自定义的beforeListenerModelBuildEventListener、 自定义的afterListener即可。

ReadSheet(就是excel的一个Sheet)参数

  • sheetNo 需要读取Sheet的编码,建议使用这个来指定读取哪个Sheet
  • sheetName 根据名字去匹配Sheet,excel 2003不支持根据名字去匹配
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。