Excel-Boot(一款Excel导入导出解决方案组成的轻量级开源组件)
easy-poi
工具链接
github:https://github.com/programmeres/easy-poi
码云:https://gitee.com/nw1992/easy-poi
easy-poi是一款excel导入导出解决方案组成的轻量级开源组件。
(如果喜欢或愿意使用, 请star并且watch本项目, 如果是企业使用, 请通过修改本文件的企业列表告诉我企业名称, 借此给我们鼓励及动力持续维护本项目。)
发现解决bug并已自测,pullrequest后,可以通过邮件告知我们(magic_app@126.com), 第一时间合并并且发布最新版本
使用企业列表:
功能简介
浏览器导出excel文件(支持单/多sheet)
浏览器导出excel模板文件
指定路径生成excel文件(支持单/多sheet)
返回excel文件(支持单/多sheet)的outputstream, 一般用于将excel文件上传到远程, 例如ftp
导入excel文件(支持单/多sheet)
解决的问题
1.解决导出大量数据造成的内存溢出问题(支持分页查询数据库、采用poi官方推荐api(sxssfworkbook), 实现指定行数刷新到磁盘)
2.解决导入大量数据造成的内存溢出问题(分页插入数据库、采用poi官方推荐api(xssf and sax),采用sax模式一行行读取到内存当中去)
3.解决含有占位符的空假行造成的读空值问题
4.解决long类型或者bigdecimal的精度不准问题
组件特色
1.导入可以自定义解析成功或失败的处理逻辑
2.导出支持分页查询、全量查询, 自定义每条数据的处理逻辑
3.内置缓存,3万条11列数据,第一次导出2.2s左右、第二次导出在1.4s左右;第一次导入3.5s左右、第二次导入2.5s左右
4.注解操作, 轻量且便捷
5.内置常用正则表达式类regexconst(身份证号、手机号、金额、邮件)
6.适配单元格宽度(单元格内容最长不得超过20个汉字)
7.假如出现异常,sheet、行、列位置也都一并打印
8.注解中的用户自定义字符串信息以及excel信息已全部trim,不用担心存在前后空格的风险
9.excel样式简洁、大方、美观
组件需知
导入和导出只支持尾缀为xlsx的excel文件、标注注解的属性顺序即excel列的排列顺序、时间转化格式(dateformat)默认为“yyyy-mm-dd hh:mm:ss“.
导入
1.当导入excel, 读取到空行, 则停止读取当前sheet的后面数据行
2.导入excel文件, 单元格格式使用文本或者常规, 防止出现不可预测异常
3.导入字段类型支持:date、short(short)、integer(int)、double(double)、long(long)、float(float)、bigdecimal、string类型
4.导入bigdecimal字段精度默认为2, roundingmode默认为bigdecimal.round_half_even
5.第一行有效单元格内必须包含内容并且以第一行为依据, 导入excel文件列数必须等于标注注解的属性数量
6.date类型字段,excel与时间转化格式(dateformat)相比,格式要保持一致(反例:2018/12/31和“yyyy-mm-dd“)并且长度要一致或更长(反例:"2018-12-31"和yyyy-mm-dd hh:mm:ss"),否则simpledateformat将解析失败,报 “unparseable date:”
导出
1.导出bigdecimal字段默认不进行精度格式化
2.分页查询默认从第一页开始, 每页3000条
3.excel每超过2000条数据, 将内存中的数据刷新到磁盘当中去
4.使用分sheet导出方法, 每8万行数据分sheet
5.当使用(exportresponse、exportstream、generateexcelstream)方法时, 当单个sheet超过100万条则会分sheet
6.标注属性类型要与数据库类型保持一致
扩展
继承easypoi类, 可以使用子类构造器覆盖以下默认参数
//excel自动刷新到磁盘的数量 public static final int default_row_access_window_size = 2000; //分页条数 public static final int default_page_size = 3000; //分sheet条数 public static final int default_record_count_peer_sheet = 80000;
使用手册
1.引入maven依赖
2.将需要导出或者导入的实体属性上标注@exportfield或@importfield注解
3.直接调用导出或导入api即可
/**
-
导出注解功能介绍
/**
*/
public @interface exportfield {- excel列名称
*/
string columnname();
- 默认单元格值
*/
string defaultcellvalue() default "";
- 日期格式 默认 yyyy-mm-dd hh:mm:ss
*/
string dateformat() default "yyyy-mm-dd hh:mm:ss";
- bigdecimal精度 默认:-1(默认不开启bigdecimal格式化)
*/
int scale() default -1;
- bigdecimal 舍入规则 默认:bigdecimal.round_half_even
*/
int roundingmode() default bigdecimal.round_half_even;
}java
/**
- excel列名称
导出注解demo
*/
public class exportfielddemo {
@exportfield(columnname = "id", defaultcellvalue = "1")
private integer id;
@exportfield(columnname = "姓名", defaultcellvalue = "张三")
private string name;
@exportfield(columnname = "收入金额", defaultcellvalue = "100", scale = 2, roundingmode=bigdecimal.round_half_even)
private bigdecimal money;
@exportfield(columnname = "创建时间", dateformat="yyyy-mm-dd", defaultcellvalue = "2019-01-01")
private date createtime;
}
```
@importfield
/** * 导入注解功能介绍 */ public @interface importfield { /** * @return 是否必填 */ boolean required() default false; /** * 日期格式 默认 yyyy-mm-dd hh:mm:ss */ string dateformat() default "yyyy-mm-dd hh:mm:ss"; /** * 正则表达式校验 */ string regex() default ""; /** * 正则表达式校验失败返回的错误信息, regex配置后生效 */ string regexmessage() default "正则表达式验证失败"; /** * bigdecimal精度 默认:2 */ int scale() default 2; /** * bigdecimal 舍入规则 默认:bigdecimal.round_half_even */ int roundingmode() default bigdecimal.round_half_even; }
/** * 导入注解demo */ public class importfield { @importfield(required = true) private integer id; @importfield(regex = idcard_regex, regexmessage="身份证校验失败") private string idcard; @importfield(scale = 2, roundingmode=bigdecimal.round_half_even) private bigdecimal money; @importfield(dateformat="yyyy-mm-dd") private date createtime; }
导出demo
/** * 导出demo */ public class exportdemo { /** * 浏览器导出excel * * @param httpservletresponse */ public void exportresponse(httpservletresponse httpservletresponse) { paramentity queryqaram = new paramentity(); easypoi.exportbuilder(httpservletresponse, "excel文件名", annotationentity.class).exportresponse(queryqaram, new exportfunction<paramentity, resultentity>() { /** * @param queryqaram 查询条件对象 * @param pagenum 当前页数,从1开始 * @param pagesize 每页条数,默认3000 * @return */ @override public list<resultentity> pagequery(paramentity queryqaram, int pagenum, int pagesize) { //分页查询操作 return new arraylist<>(); } /** * 将查询出来的每条数据进行转换 * * @param o */ @override public void convert(resultentity o) { //转换操作 } }); } /** * 浏览器多sheet导出excel * * @param httpservletresponse */ public void exportmultisheetresponse(httpservletresponse httpservletresponse) { paramentity queryqaram = new paramentity(); easypoi.exportbuilder(httpservletresponse, "excel文件名", annotationentity.class).exportmultisheetstream(queryqaram, new exportfunction<paramentity, resultentity>() { /** * @param queryqaram 查询条件对象 * @param pagenum 当前页数,从1开始 * @param pagesize 每页条数,默认3000 * @return */ @override public list<resultentity> pagequery(paramentity queryqaram, int pagenum, int pagesize) { //分页查询操作 return new arraylist<resultentity>(); } /** * 将查询出来的每条数据进行转换 * * @param o */ @override public void convert(resultentity o) { //转换操作 } }); } /** * 导出excel到指定路径 */ public void exportstream() throws filenotfoundexception { paramentity queryqaram = new paramentity(); easypoi.exportbuilder(new fileoutputstream(new file("c:\\users\\excel文件.xlsx")), "sheet名", annotationentity.class) .exportstream(queryqaram, new exportfunction<paramentity, resultentity>() { /** * @param queryqaram 查询条件对象 * @param pagenum 当前页数,从1开始 * @param pagesize 每页条数,默认3000 * @return */ @override public list<resultentity> pagequery(paramentity queryqaram, int pagenum, int pagesize) { //分页查询操作 return new arraylist<>(); } /** * 将查询出来的每条数据进行转换 * * @param o */ @override public void convert(resultentity o) { //转换操作 } }); } /** * 导出多sheet excel到指定路径 */ @requestmapping(value = "exportresponse") public void exportmultisheetstream() throws filenotfoundexception { paramentity queryqaram = new paramentity(); easypoi.exportbuilder(new fileoutputstream(new file("c:\\users\\excel文件.xlsx")), "sheet名", annotationentity.class) .exportmultisheetstream(queryqaram, new exportfunction<paramentity, resultentity>() { /** * @param queryqaram 查询条件对象 * @param pagenum 当前页数,从1开始 * @param pagesize 每页条数,默认3000 * @return */ @override public list<resultentity> pagequery(paramentity queryqaram, int pagenum, int pagesize) { //分页查询操作 return new arraylist<>(); } /** * 将查询出来的每条数据进行转换 * * @param o */ @override public void convert(resultentity o) { //转换操作 } }); } /** * 生成excel outputstream对象 */ public void generateexcelstream() throws filenotfoundexception { paramentity queryqaram = new paramentity(); outputstream outputstream = easypoi.exportbuilder(new fileoutputstream(new file("c:\\users\\excel文件.xlsx")), "sheet名", annotationentity.class) .generateexcelstream(queryqaram, new exportfunction<paramentity, resultentity>() { /** * @param queryqaram 查询条件对象 * @param pagenum 当前页数,从1开始 * @param pagesize 每页条数,默认3000 * @return */ @override public list<resultentity> pagequery(paramentity queryqaram, int pagenum, int pagesize) { //分页查询操作 return new arraylist<>(); } /** * 将查询出来的每条数据进行转换 * * @param o */ @override public void convert(resultentity o) { //转换操作 } }); } /** * 生成多sheet excel outputstream对象 */ public void generatemultisheetexcelstream() throws filenotfoundexception { paramentity queryqaram = new paramentity(); outputstream outputstream = easypoi.exportbuilder(new fileoutputstream(new file("c:\\users\\excel文件.xlsx")), "sheet名", annotationentity.class) .generatemultisheetexcelstream(queryqaram, new exportfunction<paramentity, resultentity>() { /** * @param queryqaram 查询条件对象 * @param pagenum 当前页数,从1开始 * @param pagesize 每页条数,默认3000 * @return */ @override public list<resultentity> pagequery(paramentity queryqaram, int pagenum, int pagesize) { //分页查询操作 return new arraylist<>(); } /** * 将查询出来的每条数据进行转换 * * @param o */ @override public void convert(resultentity o) { //转换操作 } }); } /** * 导出excel模板 */ public void exporttemplate(httpservletresponse httpservletresponse) { easypoi.exportbuilder(httpservletresponse, "excel模板名称", annotationentity.class).exporttemplate(); } }
导入demo
/** * 导入demo */ public class importdemo { public void importexcel() throws ioexception { easypoi.importbuilder(new fileinputstream(new file("c:\\users\\导入excel文件.xlsx")), annotationentity.class) .importexcel(new excelimportfunction<resultentity>() { /** * @param sheetindex 当前执行的sheet的索引, 从1开始 * @param rowindex 当前执行的行数, 从1开始 * @param resultentity excel行数据的实体 */ @override public void onprocess(int sheetindex, int rowindex, resultentity resultentity) { //对每条数据自定义校验以及操作 //分页插入:当读取行数到达用户自定义条数执行插入数据库操作 } /** * @param errorentity 错误信息实体 */ @override public void onerror(errorentity errorentity) { //操作每条数据非空和正则校验后的错误信息 } }); } }
下一篇: Ribbon源码解析