一、介绍

官网 https://easyexcel.opensource.alibaba.com/

EasyExcel是阿里巴巴开源的,一个基于Java的、快速、简洁、解决大文件内存溢出的Excel处理工具。
他能让你在不用考虑性能、内存的等因素的情况下,快速完成Excel的读、写等功能。
其特点是:

  • 快速的读取excel中的数据。
  • 映射excel和实体类,让代码变的更加简洁。
  • 在读写大文件的时候使用磁盘做缓存,更加的节约内存。

二、使用EasyExcel写

2.1 导入依赖

<!-- easyexcel依赖 -->
<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.1.1</version>
</dependency>
<!--lombok-->
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.20</version>
</dependency>
<dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version>
</dependency>

2.2 导出表格极简入门

①声明一个简单的对象

@Getter
@Setter
@EqualsAndHashCode
public class DemoData {@ExcelProperty("字符串标题") //这里默认为value属性赋值,value为导出的表格的表头private String string;@ExcelProperty("日期标题")private Date date;@ExcelProperty("数字标题")private Double doubleData;@ExcelIgnore  //忽略这个字段,生成的表格中就不会有该字段private String ignore;
}

②写一个简单的表格导出案例

public class SimpleWriteTest {@Testpublic void simpleWrite(){//1.模拟要写出数据List<DemoData> list = ListUtils.newArrayList();for (int i = 0; i < 10; i++) {DemoData data = new DemoData();data.setString("字符串" + i);data.setDate(new Date());data.setDoubleData(0.56);list.add(data);}//2.设置写出的文件路径String fileName = "demo1.xlsx";//3.利用EasyExcel写出,会自动关流//write方法的参数1:文件路径,参数2:模板对象类型EasyExcel.write(fileName, DemoData.class).sheet("模板")    //sheet页名字.doWrite(list);  //要写出的数据}
}

这样,就会在当前项目目录下生成名为demo1.xlsx的表格,内容如下:

2.3 根据参数导出指定属性

案例1:指定哪些属性不需要导出到表格中,仅导出剩余属性。

public class SimpleWriteTest {@Testpublic void excludeWrite(){//1.模拟要写出数据List<DemoData> list = ListUtils.newArrayList();for (int i = 0; i < 10; i++) {DemoData data = new DemoData();data.setString("字符串" + i);data.setDate(new Date());data.setDoubleData(0.56);list.add(data);}//2.设置导出过程中剔除的字段Set<String> excludeColumnFiledNames = new HashSet<String>();excludeColumnFiledNames.add("date");//这里剔除date属性//3.设置写出的文件路径String fileName = "demo2.xlsx";//4.写出EasyExcel.write(fileName, DemoData.class).excludeColumnFieldNames(excludeColumnFiledNames) //将要剔除的列设置给EasyExcel.sheet("模板").doWrite(list);}
}

结果如下,就没有了日期列。

案例2:指定仅导出哪些属性,剩余属性不导出。

public class SimpleWriteTest {@Testpublic void IncludeWrite(){//1.模拟要写出数据List<DemoData> list = ListUtils.newArrayList();for (int i = 0; i < 10; i++) {DemoData data = new DemoData();data.setString("字符串" + i);data.setDate(new Date());data.setDoubleData(0.56);list.add(data);}//2.设置仅导出哪些属性Set<String> includeColumnFiledNames = new HashSet<String>();includeColumnFiledNames.add("date");//3.设置写出的文件路径String fileName = "demo3.xlsx";//4.写出EasyExcel.write(fileName, DemoData.class).includeColumnFieldNames(includeColumnFiledNames) //设置给EasyExcel.sheet("模板").doWrite(list);//这里导出的表格中就只有:时间字段。}
}

2.4 指定写入的列

使用@ExcelProperty注解的index属性指定要导入列的下标。

@Getter
@Setter
@EqualsAndHashCode
public class IndexData {@ExcelProperty(value = "字符串标题", index = 0)private String string;@ExcelProperty(value = "日期标题", index = 1)private Date date;//这里设置3 会导致第三列空的@ExcelProperty(value = "数字标题", index = 3)private Double doubleData;
}
public class WriteTest {@Testpublic void writeDemo(){//1.模拟要写出数据List<IndexData> list = ListUtils.newArrayList();for (int i = 0; i < 10; i++) {IndexData data = new IndexData();data.setString("字符串" + i);data.setDate(new Date());data.setDoubleData(0.56);list.add(data);}//2.设置写出的文件路径String fileName = "demo4.xlsx";//3.写出EasyExcel.write(fileName, IndexData.class).sheet("模板").doWrite(list);}
}

能看到第三列是空的:

2.5 复杂头写入

在导出表格的时候,会因为业务需求,导出复杂的表头,咱们可以使用@ExcelProperty注解的value属性来实现这个需求。

例如我们要导出一个如图的表格:

仅需通过value属性设置即可:

@Getter
@Setter
@EqualsAndHashCode
public class ComplexHeadData {@ExcelProperty(value={"主标题", "副标题1","字符串标题"})private String string;@ExcelProperty(value={"主标题", "副标题1","日期标题"})private Date date;@ExcelProperty(value={"主标题", "副标题2","数字标题"})private Double doubleData;
}

导出的代码:

public class WriteTest {@Testpublic void complexHeadWrite() {List<ComplexHeadData> list = ListUtils.newArrayList();for (int i = 0; i < 10; i++) {ComplexHeadData data = new ComplexHeadData();data.setString("字符串" + i);data.setDate(new Date());data.setDoubleData(0.56);list.add(data);}//2.设置写出的文件路径String fileName = "demo5.xlsx";//3.导出EasyExcel.write(fileName, ComplexHeadData.class).sheet("模板").doWrite(list);}
}

2.6 写出到多个sheet

2.6.1 多个sheet中写入相同类型对象

public class WriteTest {@Testpublic void repeatedWrite() {//1.模拟要写出数据List<DemoData> list = ListUtils.newArrayList();for (int i = 0; i < 10; i++) {DemoData data = new DemoData();data.setString("字符串" + i);data.setDate(new Date());data.setDoubleData(0.56);list.add(data);}String fileName = "demo6.xlsx";//2.创建 ExcelWriter对象,并指定文件名和对象类型try (ExcelWriter excelWriter = EasyExcel.write(fileName, DemoData.class).build()) {// 这里模拟5次for (int i = 0; i < 5; i++) {// 每次都要创建writeSheet,这里注意必须指定sheetNo(sheet页编号),而且sheetName(sheet也名字)必须不一样WriteSheet writeSheet = EasyExcel.writerSheet(i, "模板" + i).build();// 将数据写入到sheet页中,最终,会生成5个sheet页excelWriter.write(list, writeSheet);}}}
}

效果见下图:

2.6.2 多个sheet中写入不同类型对象

public class WriteTest {@Testpublic void repeatedWrite1() {//1.模拟要写出数据List<DemoData> list = ListUtils.newArrayList();for (int i = 0; i < 10; i++) {DemoData data = new DemoData();data.setString("字符串" + i);data.setDate(new Date());data.setDoubleData(0.56);list.add(data);}String fileName = "demo7.xlsx";//2.创建ExcelWriter对象,仅需指定文件名,因为写入的数据是不固定的,所以不能写死try (ExcelWriter excelWriter = EasyExcel.write(fileName).build()) {// 模拟5次for (int i = 0; i < 5; i++) {// 每次都要创建writeSheet 这里注意必须指定sheetNo 而且sheetName必须不一样。// 注意:head方法中的DemoData.class 可以每次都变,我这里为了方便 所以用的同一个class,实际上可以一直变WriteSheet writeSheet = EasyExcel.writerSheet(i, "模板" + i).head(DemoData.class).build();// 写出数据excelWriter.write(list, writeSheet);}}}
}

2.7 日期、数字或者自定义格式转换

在写出数据时,如果需要对数据进行格式设置,可以为对象进行如下设置:

@Getter
@Setter
@EqualsAndHashCode
public class ConverterData {/*** 我想所有的 字符串起前面加上"自定义:"三个字*/@ExcelProperty(value = "字符串标题", converter = CustomStringStringConverter.class)private String string;/*** 我想写到excel 用年月日的格式*/@DateTimeFormat("yyyy年MM月dd日HH时mm分ss秒")@ExcelProperty("日期标题")private Date date;/*** 我想写到excel 用百分比表示*/@NumberFormat("#.##%")@ExcelProperty(value = "数字标题")private Double doubleData;
}

自定义格式:

public class CustomStringStringConverter implements Converter<String> {@Overridepublic Class<?> supportJavaTypeKey() {return String.class;}@Overridepublic CellDataTypeEnum supportExcelTypeKey() {return CellDataTypeEnum.STRING;}/*** 这里读的时候会调用,先不管*/@Overridepublic String convertToJavaData(ReadConverterContext<?> context) {return "自定义:" + context.getReadCellData().getStringValue();}/*** 这里是写的时候会调用* 会在原有内容之前拼接上:"自定义:"*/@Overridepublic WriteCellData<?> convertToExcelData(WriteConverterContext<String> context) {return new WriteCellData<>("自定义:"+context.getValue());}
}

写出的代码:

public class SimpleWriteTest {@Testpublic void converterWrite() {//1.模拟要写出数据List<ConverterData> list = ListUtils.newArrayList();for (int i = 0; i < 10; i++) {ConverterData data = new ConverterData();data.setString("字符串" + i);data.setDate(new Date());data.setDoubleData(0.56);list.add(data);}String fileName = "demo8.xlsx";//3.写出EasyExcel.write(fileName, ConverterData.class).sheet("模板").doWrite(list);}
}

效果如下:

2.8 设置列宽,行高

使用注解在对象的属性上进行设置即可

@Getter
@Setter
@EqualsAndHashCode
@ContentRowHeight(20) //内容高度为:20
@HeadRowHeight(40)    //表头高度为:40
@ColumnWidth(25)      //列宽为:25
public class WidthAndHeightData {@ExcelProperty("字符串标题")private String string;@ExcelProperty("日期标题")private Date date;//单独设置宽度为50@ColumnWidth(50)@ExcelProperty("数字标题")private Double doubleData;
}

导出代码为:

public class WriteTest {@Testpublic void widthAndHeightWrite() {//1.模拟要写出数据List<WidthAndHeightData> list = ListUtils.newArrayList();for (int i = 0; i < 10; i++) {WidthAndHeightData data = new WidthAndHeightData();data.setString("字符串" + i);data.setDate(new Date());data.setDoubleData(0.56);list.add(data);}String fileName = "demo9.xlsx";//3.写出EasyExcel.write(fileName, WidthAndHeightData.class).sheet("模板").doWrite(list);}
}

2.9 合并单元格

使用注解来设置合并规则:

@Getter
@Setter
@EqualsAndHashCode
// 将第6-7行的2-3列合并成一个单元格
// @OnceAbsoluteMerge(firstRowIndex = 5, lastRowIndex = 6, firstColumnIndex = 1, lastColumnIndex = 2)
public class DemoMergeData {// 这一列 每隔2行 合并单元格@ContentLoopMerge(eachRow = 2)@ExcelProperty("字符串标题")private String string;@ExcelProperty("日期标题")private Date date;@ExcelProperty("数字标题")private Double doubleData;
}

写出:

public class SimpleWriteTest {@Testpublic void mergeWrite() {//1.模拟要写出数据List<DemoMergeData> list = ListUtils.newArrayList();for (int i = 0; i < 10; i++) {DemoMergeData data = new DemoMergeData();data.setString("字符串" + i);data.setDate(new Date());data.setDoubleData(0.56);list.add(data);}String fileName = "demo10.xlsx";//2.写出EasyExcel.write(fileName, DemoMergeData.class).sheet("模板").doWrite(list);}
}

效果如下

2.10 在web项目中实现excel的导出

2.10.1 客户端页面

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><a href="/download">导出excel</a>
</body>
</html>

2.10.2 服务端代码

@Controller
public class DownloadController {@GetMapping("/download")public void download(HttpServletResponse response) throws IOException {//1.模拟数据List<DemoData> list = ListUtils.newArrayList();for (int i = 0; i < 10; i++) {DemoData data = new DemoData();data.setString("字符串" + i);data.setDate(new Date());data.setDoubleData(0.56);list.add(data);}//2.执行导出//设置响应类型response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");//设置编码response.setCharacterEncoding("utf-8");// 这里URLEncoder.encode可以防止文件名中文乱码,当然和easyexcel没有关系String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20");//设置文件名response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");//导出EasyExcel.write(response.getOutputStream(), DemoData.class).sheet("模板").doWrite(list);}
}

三、使用EasyExcel读

easyexcel读取表格内容是基于监听器方式实现的,我们需要实现它提供的ReadListener接口,进而实现读取的功能。

3.1 极简入门

假如有表格demo.xlsx的内容如下:

① 首先我们需要准备一个对象与之对应:

@Getter
@Setter
@EqualsAndHashCode
public class DemoData {@ExcelProperty("字符串标题")private String string;@ExcelProperty("日期标题")private Date date;@ExcelProperty("数字标题")private Double doubleData;
}

② 准备监听器

public class DemoDataListener implements ReadListener<DemoData> {/*** 每存储100条,可以存储一次数据库,然后清理list ,方便内存回收*/private static final int BATCH_COUNT = 100;/*** 用于缓存的数据的集合*/private List<DemoData> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);/* 在实际开发中我们可以使用有参构造,将自己的 dao 或者 service传进来,进而实现数据入库private DemoDAO demoDAO;public DemoDataListener(DemoDAO demoDAO) {this.demoDAO = demoDAO;}*//*** 这个每一条数据解析都会来调用*/@Overridepublic void invoke(DemoData data, AnalysisContext context) {System.out.println("每次读到内容是:"+data);cachedDataList.add(data);// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOMif (cachedDataList.size() >= BATCH_COUNT) {//1.存储数据库//demoDAO.saveBatch(cachedDataList);//2.存储完成清理 listcachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);}}/*** 所有数据解析完成了 都会来调用*/@Overridepublic void doAfterAllAnalysed(AnalysisContext context) {System.out.println("所有数据解析完成!");}
}

③ 读取表格内容

public class ReadTest {@Testpublic void simpleRead() {String fileName = "demo.xlsx";// 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).sheet().doRead();}
}

3.2 在web中的读

@PostMapping("/upload")
@ResponseBody
public String upload(MultipartFile file) throws IOException {//read方法参数说明://参数1:文件输入流//参数2:与表格数据对应的对象类型//参数3:监听器EasyExcel.read(file.getInputStream(), UploadData.class, new UploadDataListener(uploadDAO)).sheet().doRead();return "success";
}

Java操作Excel - Easy Excel相关推荐

  1. Java操作poi导出Excel自定义字体颜色

    Java操作poi导出Excel自定义字体颜色 功能介绍 POI操作Excel 第一步创建一个导出的工具类 整体定义表格字体样式 自定义表格字体样式 总结 功能介绍 Apache POI 是用Java ...

  2. java操作word、excel、pdf 下载添加水印

    1.pdf添加水印 pom文件引入依赖 <dependency><groupId>com.itextpdf</groupId><artifactId>i ...

  3. Easy Excel生成压缩包文件,自定义表头样式

    Excel 文件内容形如下图! 需求场景 导出超10w左右的数据,涉及 源数据查. 组装业务数据 解析数据库中的json数据内容,并组装相应的信息 生成Excel文件内容到磁盘 将文件压缩,并写回到浏 ...

  4. java写excel_java写excel文件工具

    之前写过一个用java操作csv与excel文件的工具<操作CSV与EXCEL的工具>,它写入几十.几百行数据都没有问题.但如果写几万行,就有些吃力了,速度太慢.另外也没有抽出工具代码,与 ...

  5. Easy Excel

    Easy Excel Easy Excel 1. 为什么有使用easyexcle 2. easvexcel拟解决的问题 3. 工作原理 4. ORM根据数据库表创建实体类的一个小技巧 5. 写exce ...

  6. 一小时教你轻松学会使用Java 整合 Easy Excel 操作 Excel 文件

    文章目录 一.Apache POI简介 二.POI操作Excel 构建maven项目导入依赖 使用POI实现基本写操作 使用POI实现大数据量写操作 使用POI实现基本读操作 使用POI读取不同类型的 ...

  7. java excel读取操作,Java 操作 Excel (读取Excel2003 2007,Poi兑现)

    Java 操作 Excel (读取Excel2003 2007,Poi实现) 一. Apache POI 简介( http://poi.apache.org/) 使用Java程序读写Microsoft ...

  8. java操作poi如何更改excel中的数据

    http://www.myexception.cn/j2ee/17951.html 修改文件最后还需要通过IO流操作来保存更改,这其实是很关键的一步,你代码里面没有IO的关闭操作,导致了数据的修改没有 ...

  9. Java程序员从笨鸟到菜鸟之(一百零四)java操作office和pdf文件(二)利用POI实现数据导出excel报表...

    在上一篇博客中,我们简单介绍了java读取word,excel和pdf文档内容 ,但在实际开发中,我们用到最多的是把数据库中数据导出excel报表形式.不仅仅简单的读取office中的数据.尤其是在生 ...

最新文章

  1. java表单 mysql 乱码_java web当中表单提交到后台出现乱码的解决方法
  2. TCP/IP的四元组 五元组 七元组
  3. glance系列一:glance基础
  4. 实战并发编程 - 05等效不可变对象CopyOnWriteArrayList适用场景剖析_写时复制COW
  5. 设计模式--门面(Facade)模式
  6. java方法criterion_java – JPA Criteria谓词条件
  7. Jmeter当获取正则表达式匹配数字为负数时获取所有匹配的值
  8. How is Attachment property retrieved
  9. java中treemap_Java中TreeMap集合讲解
  10. matlab 万能,matlab 万能实用的线性曲线拟合方法
  11. flume学习(八):自定义拦截器
  12. 如何编写大数据分析师简历
  13. x3850x5服务器内存_有图有真相 IBM System x3850 X5拆机秀
  14. 激活Windows10,激活软件被报出,软件存在威胁或者恶意程序?
  15. 计算机辅助工程分析及应用论文,浅谈计算机辅助工程(CAE) 毕业设计(论文).doc...
  16. 100%可用的总裁主题授权版 WordPress付费资源素材下载主题
  17. win7下 文件名太长无法删除,无法更名问题
  18. 线段树(lazy用法)
  19. JAVA 使用POI读取文档
  20. 人人都有发言权的新媒体时代 内容审核需亮剑

热门文章

  1. hash函数原理实现
  2. java中写html标签,java写html剔出标签
  3. 给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。
  4. Excel 多条件筛选 与 数据透视表 实现
  5. Python requests模块高级用法
  6. 一日一命令:find 命令详解
  7. android曲面屏点击事件无响应,都说曲面屏中看不中用,主要原因有四点,第三点是关键!...
  8. freesurfer运行完recon-all怎么快速查看有没有报错?——核心命令tail重定向
  9. Flying Saucer 不支持中文,换行,粗体,CheckBox多选框的解决方案
  10. 这家安全厂商避谈“软件定义”,我却要为它的“反骨”点赞