史上最全的excel读写技术分享

此文章以独家受权一下公众号 :
【新华先后端开发】
【脚本之家】git

快速、简单避免OOM的java处理Excel工具】 github上关于项目的介绍github

简介

poi使用userModel模式,这个模式的特色就是上手很容易。代码写起来很复杂。并且公用的地方不多。致使每次读写excel都须要从新编写。
EasyExcel使用SAX模式使得easyexcel能够节省内存。并且easyexcel解决了内存泄漏问题。若是想了解SAX模式开发那成本须要3~5天学习。数据库

导出excel经常使用的几种方法

经过Java读写excel大概有如下几种:
poi、csv、jxl、jxls 、easyPoi 、easyExcel
根据性能他们的排序:
jxl 、 easyexcel 、 csv 、  poi 、  easypoi 、  jxlsapache

POI

  • POI是apache的一个开源项目。他是基于微软提供对Java程序的一个API。经过它咱们能控制excel的单元格的内容及样式的读取写入。
  • 可是正是由于他的细节之处致使咱们开发起来代码不少。并且没法抽离。

CSV

  • csv实际上就是一个文本,只不过经过office可以打开的一中文本。真正的excel对象若是经过普通的文本工具打开你会发现实际是一个二进制文件。由于csv是一个文本,因此在读写他的时候实际就是文本的读取。没有POI的workbook、sheet、row 、cell 之说。因此读写的效率仍是很快的。
  • 可是由于是文本因此咱们没法控制单元格的样式。好比样式、加下拉框、合并单元格之类的。

jxl

  • jxl实际和POI差很少。二者的理念同样,都是经过表格对象--》单元页--》行--》列--》单元格的逻辑去操做读写的。基本上经常使用的功能都是提供方法的。不一样的是方法的传参顺序的不一样。二者在性能上的比较jxl性能更佳。
  • 由于POI的风靡。jxl并非很熟知。笔者也是整理的时候发现jxl。暂时不知道jxl的缺点。非要指出缺点那么就是他和poi的逻辑不同。编写起来有点别扭。

jxls

  • 这里须要值得注意的是jxls和jxl一点关系都没有。二者的使用方法的逻辑也是天差万别的。jxls更佳侧重的是excel自己的模板的编写。jxls是经过模板在注入数据进行渲染的一个框架。他的最大的有点就是代码量不多。基本上咱们只须要准备好数据就能够进行导出了。
  • 由于是基于模板的。因此jxls实现导出的很简单。可是实现读取数据这里就很很差办了。这里笔者暂时不知道如何实现。 这个问题就留给聪明的读者吧!!!windows

    easypoi

  • easypoi和easyexcel很类似。二者都是经过注解的方式实现excel表头与实体对象的一种映射。一个@Excel 另外一个是@ExcelProperty . 相对easyexcel,easypoi功能就相对单一点。
  • 二者均可以在自身的功能不足的状况下,经过POI的功能实现自定义功能后端

easyexcel

  • easyexcel是重点对象。他基于注解的方式将之前POI的复杂的代码进模块抽离。咱们基本上的需求只须要在excelproperty注解中就能够解决。
    - easyexcel最大的特色就是解决了内存泄漏的问题。以上几种poi在导出excel的时候都受到了数据的影响.并且性能上还不是很好。easyexcel是POI系列产品的最佳之选

快速入门

easyexcel名字很是的符合他的个性。他是真的很easy.下面咱们来实现一个导出学生信息的代码api

String fileName = EasyExcelTools.class.getResource("/").getPath() + "student" + System.currentTimeMillis() + ".xlsx";
ExcelWriterBuilder excelWriterBuilder = EasyExcel.write(fileName, Student.class);
//excelWriterBuilder.registerConverter(new SexConverter()).registerWriteHandler(new AgeRowHandler()).registerWriteHandler(new SexCellWriteHandler());
ExcelWriter excelWriter = excelWriterBuilder.build();
WriteSheet writeSheet = EasyExcel.writerSheet("中化安元").build();
try {
    excelWriter.write(ts, writeSheet);
} catch (Exception e) {
    e.printStackTrace();
}finally {
    excelWriter.finish();
}

代码解读

  • Student是导出须要的实体。里面配置了表格的一些基本信息
  • ts 是Student数据的一个集合
  • fileName 是导出的文件地址缓存

    student

public class Student {

/**
  * 学生索引id
  */
@ExcelProperty(value = {HeadConstant.FIRSTNAME,HeadConstant.SECONDNAME,"学号"})
private String id;
/**
  * 姓名
  */
@ExcelProperty(value = {HeadConstant.FIRSTNAME,HeadConstant.SECONDNAME,"姓名"})
private String userName;

/**
  * 用户昵称
  */
@ExcelProperty(value = {HeadConstant.FIRSTNAME,HeadConstant.SECONDNAME,"昵称"})
@ExcelIgnore
private String userNick;

/**
  * 年龄
  */
@ExcelProperty(value = {HeadConstant.FIRSTNAME,HeadConstant.SECONDNAME,"年龄"})
private Integer age;
/**
  * 性别 true : 男  ; false : 女
  */
@ExcelProperty(value = {HeadConstant.FIRSTNAME,HeadConstant.SECONDNAME,"性别"})
private boolean sex;
/**
  * 生日
  */
@ExcelProperty(value = {HeadConstant.FIRSTNAME,HeadConstant.SECONDNAME,"生日"})
private Date birth;
/**
  * 身高
  */
@ExcelProperty(value = {HeadConstant.FIRSTNAME,HeadConstant.SECONDNAME,"身高"})
private Double height;

}

总结

  • 经过easyexcel导出咱们只须要准备好数据,而后两行代码导出。

经常使用API

  • EasyExcel 入口类,用于构建开始各类操做
  • ExcelReaderBuilder ExcelWriterBuilder 构建出一个 ReadWorkbook WriteWorkbook,能够理解成一个excel对象,一个excel只要构建一个
  • ExcelReaderSheetBuilder ExcelWriterSheetBuilder 构建出一个 ReadSheet WriteSheet对象,能够理解成excel里面的一页,每一页都要构建一个
  • ReadListener 在每一行读取完毕后都会调用ReadListener来处理数据
  • WriteHandler 在每个操做包括建立单元格、建立表格等都会调用WriteHandler来处理数据
  • 全部配置都是继承的,Workbook的配置会被Sheet继承,因此在用EasyExcel设置参数的时候,在EasyExcel...sheet()方法以前做用域是整个sheet,以后针对单个sheet

单元格样式

  • 由于被封装了一层。若是easyexcel知足不了咱们的话,咱们能够经过workbook去具体操做单元格内容和样式。这种方法是万不得已在使用。就好比咱们想改变单元格样式。easyexcel提供了开发接口CellWriteHandler。咱们只须要实现这个接口并重写他的beforeCellCreateafterCellCreateafterCellDispose.其中afterCellDispose方法是在单元格建立后销毁前的一个时机。这时候咱们能够改变单元格内容。easyExcel提供了四种时间捕捉接口
    CellWriteHandler
    WorkbookWriteHandler
    SheetWriteHandler
    RowWriteHandler

合并单元格

  • 在POI中咱们实现合并单元格咱们须要指定合并的范围。可是在easyexcel中咱们只须要在ExcelProperty注解中加入表头的时候在对应位置加入相同的内容就会自动的合并单元格。


数据样式

  • 数据样式使咱们Java开发中常常遇到的。好比说学生信息中的性别咱们粗在数据库中大部分状况都是经过0、1来控制的。可是咱们导出的时候确定是不能直接展现01的。这个时候咱们就须要数据样式了。说的在明白点就是数据格式转换。在easyexcel中提供了Converter接口。
    convertToJavaData : excel数据转换成Java对象
    convertToExcelData: Java对象转换成excel数据

多sheet设置

  • 多sheet页实际上就是建立多个sheet。每一个sheet有不一样的编号。剩下的操做都是同样的。

单元格添加超连接

  • 经过CellWriteHandler实如今afterCellDispose方法中实现
CreationHelper createHelper = writeSheetHolder.getSheet().getWorkbook().getCreationHelper();
Hyperlink hyperlink = createHelper.createHyperlink(HyperlinkType.URL);
hyperlink.setAddress("https://gitee.com/zxhTom");
cell.setHyperlink(hyperlink);

依赖

<dependency>
   <groupId>net.sourceforge.javacsv</groupId>
   <artifactId>javacsv</artifactId>
   <version>2.0</version>
</dependency>

使用版本

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>2.1.0-beta4</version>
</dependency>

中流砥柱

  • ExcelProperty: 实体属性配置注解
  • BaseRowModel : 编写实体继承的实体类
  • WriteHandler : 用来控制单元格输出,包括样式和数据格式设置
  • ExcelWriter : 用于导出excel

notes

系统时间

1900 windowing 1900年日期系统
1904 windowing 1904年日期系统
Excel for windows 使用1900
Excel2008 for mac 和以前版本 1904
excel 2016 for mac ; excel for mac 2011 1900微信

读写数据格式内置转换器

  • BigDecimalBooleanConverter()
  • BigDecimalNumberConverter();
  • BigDecimalStringConverter();
  • BooleanBooleanConverter();
  • BooleanNumberConverter();
  • BooleanStringConverter();
  • ByteBooleanConverter();
  • ByteNumberConverter();
  • ByteStringConverter();
  • DateNumberConverter();
  • DateStringConverter();
  • DoubleBooleanConverter();
  • DoubleNumberConverter();
  • DoubleStringConverter();
  • FloatBooleanConverter();
  • FloatNumberConverter();
  • FloatStringConverter();
  • IntegerBooleanConverter();
  • IntegerNumberConverter();
  • IntegerStringConverter();
  • LongBooleanConverter();
  • LongNumberConverter();
  • LongStringConverter();
  • ShortBooleanConverter();
  • ShortNumberConverter(Converter 数据转换接口);
  • ShortStringConverter();
  • StringBooleanConverter();
  • StringNumberConverter();
  • StringStringConverter();
  • StringErrorConverter();

ModelBuildEventListener

  • ModelBuildEventListener 默认的也是第一个数据监听器,主要功能就是将读取到的当前行数据转换成实体或者map

write

  • FileUtils.createPoiFilesDirectory();
    在初始化时建立临时缓存目录以免POI并发写入错误

读写流程分析

read

./easyexcel

write

./easyexcel

加入战队

# 加入战队

微信公众号

微信公众号

相关文章
相关标签/搜索