Java操作Excel - Easy Excel
一、介绍
官网 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相关推荐
- Java操作poi导出Excel自定义字体颜色
Java操作poi导出Excel自定义字体颜色 功能介绍 POI操作Excel 第一步创建一个导出的工具类 整体定义表格字体样式 自定义表格字体样式 总结 功能介绍 Apache POI 是用Java ...
- java操作word、excel、pdf 下载添加水印
1.pdf添加水印 pom文件引入依赖 <dependency><groupId>com.itextpdf</groupId><artifactId>i ...
- Easy Excel生成压缩包文件,自定义表头样式
Excel 文件内容形如下图! 需求场景 导出超10w左右的数据,涉及 源数据查. 组装业务数据 解析数据库中的json数据内容,并组装相应的信息 生成Excel文件内容到磁盘 将文件压缩,并写回到浏 ...
- java写excel_java写excel文件工具
之前写过一个用java操作csv与excel文件的工具<操作CSV与EXCEL的工具>,它写入几十.几百行数据都没有问题.但如果写几万行,就有些吃力了,速度太慢.另外也没有抽出工具代码,与 ...
- Easy Excel
Easy Excel Easy Excel 1. 为什么有使用easyexcle 2. easvexcel拟解决的问题 3. 工作原理 4. ORM根据数据库表创建实体类的一个小技巧 5. 写exce ...
- 一小时教你轻松学会使用Java 整合 Easy Excel 操作 Excel 文件
文章目录 一.Apache POI简介 二.POI操作Excel 构建maven项目导入依赖 使用POI实现基本写操作 使用POI实现大数据量写操作 使用POI实现基本读操作 使用POI读取不同类型的 ...
- java excel读取操作,Java 操作 Excel (读取Excel2003 2007,Poi兑现)
Java 操作 Excel (读取Excel2003 2007,Poi实现) 一. Apache POI 简介( http://poi.apache.org/) 使用Java程序读写Microsoft ...
- java操作poi如何更改excel中的数据
http://www.myexception.cn/j2ee/17951.html 修改文件最后还需要通过IO流操作来保存更改,这其实是很关键的一步,你代码里面没有IO的关闭操作,导致了数据的修改没有 ...
- Java程序员从笨鸟到菜鸟之(一百零四)java操作office和pdf文件(二)利用POI实现数据导出excel报表...
在上一篇博客中,我们简单介绍了java读取word,excel和pdf文档内容 ,但在实际开发中,我们用到最多的是把数据库中数据导出excel报表形式.不仅仅简单的读取office中的数据.尤其是在生 ...
最新文章
- java表单 mysql 乱码_java web当中表单提交到后台出现乱码的解决方法
- TCP/IP的四元组 五元组 七元组
- glance系列一:glance基础
- 实战并发编程 - 05等效不可变对象CopyOnWriteArrayList适用场景剖析_写时复制COW
- 设计模式--门面(Facade)模式
- java方法criterion_java – JPA Criteria谓词条件
- Jmeter当获取正则表达式匹配数字为负数时获取所有匹配的值
- How is Attachment property retrieved
- java中treemap_Java中TreeMap集合讲解
- matlab 万能,matlab 万能实用的线性曲线拟合方法
- flume学习(八):自定义拦截器
- 如何编写大数据分析师简历
- x3850x5服务器内存_有图有真相 IBM System x3850 X5拆机秀
- 激活Windows10,激活软件被报出,软件存在威胁或者恶意程序?
- 计算机辅助工程分析及应用论文,浅谈计算机辅助工程(CAE) 毕业设计(论文).doc...
- 100%可用的总裁主题授权版 WordPress付费资源素材下载主题
- win7下 文件名太长无法删除,无法更名问题
- 线段树(lazy用法)
- JAVA 使用POI读取文档
- 人人都有发言权的新媒体时代 内容审核需亮剑
热门文章
- hash函数原理实现
- java中写html标签,java写html剔出标签
- 给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。
- Excel 多条件筛选 与 数据透视表 实现
- Python requests模块高级用法
- 一日一命令:find 命令详解
- android曲面屏点击事件无响应,都说曲面屏中看不中用,主要原因有四点,第三点是关键!...
- freesurfer运行完recon-all怎么快速查看有没有报错?——核心命令tail重定向
- Flying Saucer 不支持中文,换行,粗体,CheckBox多选框的解决方案
- 这家安全厂商避谈“软件定义”,我却要为它的“反骨”点赞