此文章以独家授权一下公众号 :

【新华前后端开发】

【脚本之家】

快速、简单避免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。我们只需要实现这个接口并重写他的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

write

加入战队

# 加入战队

微信公众号

史上最全的excel读写技术分享的更多相关文章

  1. 史上最全的Java高级技术点,全是Java高级进阶技术,几乎包含了Java后端的所有知识点

    史上最全的Java高级技术点,全是Java高级进阶技术,几乎包含了Java后端的所有知识点 1

  2. 史上最全的Excel数据编辑处理技巧(转)

    史上最全的数据编辑处理技巧,让你在日常数据分析处理的疯魔状态中解放出来. 一.隐藏行列 “不得了了,Excel出现灵异事件,部分区域消失不见了!”办公室里的一个MM跑过来大声喊叫着,着实吓了俺一跳.待 ...

  3. 34张史上最全IT架构师技术知识图谱 最新下载

    本文是笔者多年来积累和收集的知识技能图谱,小编极力推荐分享给身边的技术人儿,希望这份技术知识图谱能够帮助到每一位奋斗在技术路上的小伙伴. 下面是笔者多年来积累和收集的知识技能图谱,有的是笔者原创总结的 ...

  4. 史上最全的java随机数生成算法分享(转)

    这篇文章主要介绍了史上最全的java随机数生成算法,我分享一个最全的随机数的生成算法,最代码的找回密码的随机数就是用的这个方法 String password = RandomUtil.generat ...

  5. 史上最全的Excel导入导出之easyexcel

    喝水不忘挖井人,感谢阿里巴巴项目组提供了easyexcel工具类,github地址:https://github.com/alibaba/easyexcel 文章目录 环境搭建 读取excel文件 小 ...

  6. 了解iOS消息推送一文就够:史上最全iOS Push技术详解

    本文作者:陈裕发, 腾讯系统测试工程师,由腾讯WeTest整理发表. 1.引言 开发iOS系统中的Push推送,通常有以下3种情况: 1)在线Push:比如QQ.微信等IM界面处于前台时,聊天消息和指 ...

  7. 你想找的Python资料这里全都有!没有你找不到!史上最全资料合集

    你想找的Python资料这里全都有!没有你找不到!史上最全资料合集 2017年11月15日 13:48:53 技术小百科 阅读数:1931   GitHub 上有一个 Awesome - XXX 系列 ...

  8. 吐血总结|史上最全的MySQL学习资料!!

    在日常工作与学习中,无论是开发.运维.还是测试,对于数据库的学习是不可避免的,同时也是日常工作的必备技术之一.在互联网公司,开源产品线比较多,互联网企业所用的数据库占比较重的还是MySQL. 在刚刚出 ...

  9. 优秀后端架构师必会知识:史上最全MySQL大表优化方案总结

    本文原作者“ manong”,原创发表于segmentfault,原文链接:segmentfault.com/a/1190000006158186 1.引言   MySQL作为开源技术的代表作之一,是 ...

随机推荐

  1. el-table实现行列拖拽

    element ui 表格没有自带的拖拽排序的功能,只能借助第三方插件Sortablejs来实现. 实现步骤: 安装Sortable.js npm install sortablejs --save ...

  2. 个性化推荐产品功能的设计和B端产品的功能策划方式

    宜信科技中心财富管理产品部负责人Bob,与大家一起聊聊个性化推荐产品功能的设计和B端产品的功能策划方式. 拓展阅读:回归架构本质,重新理解微服务|专访宜信开发平台(SIA)负责人梁鑫 智慧金融时代,大 ...

  3. BT面板安装php报错configure: error: C preprocessor “/lib/cpp” fails sanity check

    使用宝塔面板安装扩展时已经显示添加安装成功了,待我刷新浏览器之后没有安装成功.看了一下执行日志. 缺少必要的C++库,如下命令重装解决. yum reinstall glibc-headers gcc ...

  4. 洛谷 1552 [APIO2012]派遣

    题目背景 在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿. 题目描述 在这个帮派里,有一名忍者被称之为Master.除了Master以外,每名忍者都有且仅有一个上级.为保密 ...

  5. Django2.1.3 urls.py path模块配置

    learning_log/urls.py learning_logs/urls.py django2.0和1.x的区别是非常明显的,2.0开始使用path和re_path代替原来的url,而且用法有了 ...

  6. eventfd(2) 结合 select(2) 源码分析

    eventfd(2) 结合 select(2) 源码分析 本文代码选自内核 4.17 eventfd(2) - 创建一个文件描述符用于事件通知. 使用 源码分析 参考 #include <sys ...

  7. IT爱心求助站

    最近发生的一些事情,让我对自己的专业有了另外一层认识. 小尹同学,你是做软件的是吗?能否帮我看一下我的电脑问题? 老同学,我的电脑安装一个软件这么都装不上,能否帮我看一下呢? 邻居你好,我的手机怎么没 ...

  8. 你必须知道的容器监控 (1) Docker自带子命令与Weave Scope

    本篇已加入<.NET Core on K8S学习实践系列文章索引>,可以点击查看更多容器化技术相关系列文章.本篇会介绍几个目前比较常用且流行的容器监控工具,首先我们来看看Docker自带的 ...

  9. 一张图看懂Rxjava的原理

    前言 Rxjava是NetFlix出品的Java框架, 官方描述为 a library for composing asynchronous and event-based programs usin ...

  10. HTML CSS整理笔记

    ——修改placeholder提示的样式: 1.除IE外通用写法 类名或标签名::placeholder {color: red;}2.加兼容前缀写法 css超出一行显示省略号:给定宽度(width: ...