目录
简介
导出 Excel 常用的几种方法
- POI
- CSV
- jxl
- jxls
- easyexcel
快速入门
代码解读
总结
常用 API
单元格样式
合并单元格
数据样式
多 sheet 设置
单元格添加超链接
依赖
使用版本
中流砥柱
notes
系统时间
读写数据格式内置转换器
- ModelBuildEventListener
- write
读写流程分析
- read
- write
- # 加入战队
微信公众号
此文章以独家授权一下公众号 :
[新华前后端开发]
[脚本之家]
[快速, 简单避免 OOM 的 java 处理 Excel 工具] 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 , jxls
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 实现导出的很简单. 但是实现读取数据这里就很不好办了. 这里笔者暂时不知道如何实现. 这个问题就留给聪明的读者吧!!!
easypoi
easypoi 和 easyexcel 很相似. 两者都是通过注解的方式实现 Excel 表头与实体对象的一种映射. 一个 @Excel 另一个是 @ExcelProperty . 相对 easyexcel,easypoi 功能就相对单一点.
两者都可以在自身的功能不足的情况下, 通过 POI 的功能实现自定义功能
easyexcel
easyexcel 是重点对象. 他基于注解的方式将以前POI的复杂的代码进模块抽离. 我们基本上的需求只需要在excelproperty注解中就可以解决.
- easyexcel 最大的特点就是解决了内存泄漏的问题. 以上几种poi在导出excel的时候都受到了数据的影响. 而且性能上还不是很好.easyexcel是POI系列产品的最佳之选
快速入门
easyexcel 名字非常的符合他的个性. 他是真的很easy. 下面我们来实现一个导出学生信息的代码
- 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. 我们只需要实现这个接口并重写他的 beforeCellCreate,afterCellCreate,afterCellDispose. 其中 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
write
加入战队
# 加入战队
微信公众号
来源: https://www.cnblogs.com/zhangxinhua/p/11833582.html