为什么选择Alibaba EasyExcel
优势:

EasyExcel 重写了poi对07版Excel的解析,并且再大的excel也不会出现内存溢出

简单使用
一、写

1:引入依赖

         <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.1.0</version></dependency>

2:写一个文件地址工具类

import java.io.File;
import java.io.InputStream;public class TestFileUtil {public static InputStream getResourcesFileInputStream(String fileName) {return Thread.currentThread().getContextClassLoader().getResourceAsStream("" + fileName);}public static String getPath() {return "C:/Users/Administrator/Desktop/测试/";
//        return TestFileUtil.class.getResource("/").getPath();}public static File createNewFile(String pathName) {File file = new File(getPath() + pathName);if (file.exists()) {file.delete();} else {if (!file.getParentFile().exists()) {file.getParentFile().mkdirs();}}return file;}public static File readFile(String pathName) {return new File(getPath() + pathName);}public static File readUserHomeFile(String pathName) {return new File(System.getProperty("user.home") + File.separator + pathName);}
}
简单写
 String fileName = TestFileUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".xlsx";// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭// 如果这里想使用03 则 传入excelType参数即可EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(() -> {// 分页查询数据//这里面可以放入查询数据的逻辑,通过return 将数据返过去,导出return data();});

可以通过一个对象来设置所导出的表头名称

@Data
@NoArgsConstructor
@AllArgsConstructor
public class DemoData {@ExcelProperty("字符串标题")private String string;@ExcelProperty("日期标题")private Date date;@ExcelProperty("数字标题")private Double doubleData;/*** 忽略这个字段*/@ExcelIgnoreprivate String ignore;
}

@ExcelProperty 可以设置所导出字段的表头名称

对导出数据进行格式化

@Testpublic void converterWrite() {String fileName = TestFileUtil.getPath()  +"数据格式化3" + ".xlsx";// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭EasyExcel.write(fileName, ConverterData.class).sheet("模板").doWrite(data());}private List<DemoData> data() {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.5600);list.add(data);}return list;}
@Data
@NoArgsConstructor
@AllArgsConstructor
@ColumnWidth(40)//列宽
public class ConverterData {/*** 我想写到excel 用年月日的格式*/@DateTimeFormat("yyyy-mm-dd HH:MM:ss")@ExcelProperty("日期标题")private Date date;/*** 我想写到excel 用百分比表示*/@NumberFormat("0.00%")@ExcelProperty(value = "数字标题")private Double doubleData;
}
复杂表头导出 可以对某几个字段进行一个总标题合并

效果图如下

   @Testpublic void complexHeadWrite() {String fileName = TestFileUtil.getPath() + "complexHeadWrite" + System.currentTimeMillis() + ".xlsx";// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭EasyExcel.write(fileName, ComplexHeadData.class).sheet("模板").doWrite(data());//可以指定导出的sheet}private List<DemoData> data() {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);}return list;}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ComplexHeadData {@ExcelProperty({"主标题", "字符串标题"})private String string;@ExcelProperty({"主标题", "日期标题"})private Date date;@ExcelProperty({"主标题", "数字标题"})private Double doubleData;@ExcelProperty("测试")private String test;}
合并单元格导出-通过对象设定合并单元格规则
@Testpublic void mergeWrite() {// 方法1 注解String fileName = TestFileUtil.getPath() + "合并单元格" + ".xlsx";// 在DemoStyleData里面加上ContentLoopMerge注解// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭EasyExcel.write(fileName, DemoMergeData.class).sheet("模板").doWrite(data());}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class DemoMergeData {// 这一列 每隔2行 合并单元格@ContentLoopMerge(eachRow = 2)@ExcelProperty("字符串标题")private String string;@ExcelProperty("日期标题")private Date date;@ExcelProperty("数字标题")private Double doubleData;
}

效果如下:

合并单元格导出-第二种方式
// 方法2 自定义合并单元格策略fileName = TestFileUtil.getPath() + "自定义合并单元格"  + ".xlsx";// 每隔2行会合并 把eachColumn 设置成 3 也就是我们数据的长度,所以就第一列会合并。当然其他合并策略也可以自己写LoopMergeStrategy loopMergeStrategy = new LoopMergeStrategy(3, 0);// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭EasyExcel.write(fileName, DemoData.class).registerWriteHandler(loopMergeStrategy).sheet("模板").doWrite(data());

效果如下:

导出到多个sheet
   @Testpublic void repeatedWrite() {// 方法3 如果写到不同的sheet 不同的对象String   fileName = TestFileUtil.getPath() + "多sheet"  + ".xlsx";// 这里 指定文件try (ExcelWriter excelWriter = EasyExcel.write(fileName).build()) {WriteSheet writeSheet = EasyExcel.writerSheet(0, "测试一").head(DemoData.class).build();List<DemoData> data = data();excelWriter.write(data, writeSheet);WriteSheet writeSheet1 = EasyExcel.writerSheet(1, "测试二").head(DemoData.class).build();List<DemoData> data1 = data();excelWriter.write(data1, writeSheet1);WriteSheet writeSheet2 = EasyExcel.writerSheet(2, "测试三").head(DemoData.class).build();List<DemoData> data2 = data();excelWriter.write(data2, writeSheet2);WriteSheet writeSheet3 = EasyExcel.writerSheet(3, "测试四").head(DemoData.class).build();List<DemoData> data3 = data();excelWriter.write(data3, writeSheet3);}}private List<DemoData> data() {List<DemoData> list = ListUtils.newArrayList();for (int i = 0; i < 1000; i++) {DemoData data = new DemoData();data.setString("字符串" + i);data.setDate(new Date());data.setDoubleData(0.56);list.add(data);}return list;}
二、读操作
普通的读-可以读指定的sheet
 @Testpublic void simpleRead() {// 写法1:JDK8+ ,不用额外写一个DemoDataListener// since: 3.0.0-beta1String fileName = TestFileUtil.getPath() + File.separator + "多sheet.xlsx";// 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭// 这里每次会读取100条数据 然后返回过来 直接调用使用数据就行EasyExcel.read(fileName, DemoData.class, new PageReadListener<DemoData>(dataList -> {for (DemoData demoData : dataList) {log.info("读取到一条数据{}", JSON.toJSONString(demoData));}})).sheet("测试").doRead();}
读取多个sheet
@Testpublic void repeatedRead() {String fileName = TestFileUtil.getPath() + File.separator + "多sheet.xlsx";// 读取全部sheet// 这里需要注意 DemoDataListener的doAfterAllAnalysed 会在每个sheet读取完毕后调用一次。然后所有sheet都会往同一个DemoDataListener里面写EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).doReadAll();// 读取部分sheetfileName = TestFileUtil.getPath() + File.separator + "多sheet.xlsx";// 写法1try (ExcelReader excelReader = EasyExcel.read(fileName).build()) {// 这里为了简单 所以注册了 同样的head 和Listener 自己使用功能必须不同的ListenerReadSheet readSheet1 =EasyExcel.readSheet(0).head(DemoData.class).registerReadListener(new DemoDataListener()).build();ReadSheet readSheet2 =EasyExcel.readSheet(1).head(DemoData.class).registerReadListener(new DemoDataListener()).build();ReadSheet readSheet3 =EasyExcel.readSheet(2).head(DemoData.class).registerReadListener(new DemoDataListener()).build();ReadSheet readSheet4 =EasyExcel.readSheet(3).head(DemoData.class).registerReadListener(new DemoDataListener()).build();// 这里注意 一定要把sheet1 sheet2 一起传进去,不然有个问题就是03版的excel 会读取多次,浪费性能excelReader.read(readSheet1, readSheet2,readSheet3,readSheet4);}}
不创建对象的读
  @Testpublic void noModelRead() {String fileName = TestFileUtil.getPath() +  "测试.xlsx";// 这里 只要,然后读取第一个sheet 同步读取会自动finishEasyExcel.read(fileName, new NoModelDataListener()).sheet().doRead();Set<Channel> channelSet = ExcelUtil.channelSet;int count = 0;for (Channel channel : channelSet) {count++;System.out.println("第"+count+"个"+channel);}}
@Slf4j
public class NoModelDataListener extends AnalysisEventListener<Map<Integer, String>> {/*** 每隔5条存储数据库,实际使用中可以100条,然后清理list ,方便内存回收*/private static final int BATCH_COUNT = 5;private List<Map<Integer, String>> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);@Overridepublic void invoke(Map<Integer, String> data, AnalysisContext context) {//        log.info("解析到一条数据:{}", JSON.toJSONString(data));cachedDataList.add(data);if (cachedDataList.size() >= BATCH_COUNT) {saveData();cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);}}@Overridepublic void doAfterAllAnalysed(AnalysisContext context) {saveData();log.info("所有数据解析完成!");}/*** 加上存储数据库*/private void saveData() {for (Map<Integer, String> map : cachedDataList) {String pid = "0";int size = map.size();for (int i = 0; i < size; i++) {String value = map.get(i);if (value == null) {continue;}int index = value.indexOf(",");Channel channel = new Channel();if (index < 0) {channel.setPid(pid);channel.setId(value);channel.setName(value);pid = value;} else {String name = value.substring(0, index);channel.setPid(pid);String id = value.substring(index + 1);channel.setId(id);channel.setName(name);pid = id;}ExcelUtil.channelSet.add(channel);}}}

阿里巴巴EasyExcel学习笔记相关推荐

  1. EasyExcel 学习笔记 - 读Excel

    EasyExcel 学习笔记 - 读Excel pom.xml 添加依赖 测试数据 实体类 自定义转换器 最简单的读 写法1 写法2 写法3 写法4 多行头(跳过N行) 读多个sheet 读全部 sh ...

  2. EasyExcel学习笔记——本地excel的导入导出、Web端excel的导入导出

    EasyExcel学习笔记 EasyExcel 用于 Java解析.生成Excel,是一个基于Java的简单.省内存的读写Excel的开源项目.在尽可能节约内存的情况下支持读写百M的Excel. 官方 ...

  3. EasyExcel学习笔记

    一.初识EasyExcel 1. Apache POI 有过报表导入导出经验的同学,应该有听说或使用过POI. Apache POI是Apache软件基金会的开源函式库,提供跨平台的Java API实 ...

  4. 阿里巴巴canal学习笔记

    目前主流数据同步工具: https://zhuanlan.zhihu.com/p/346176776 https://zhangzhenquan.blog.csdn.net/article/detai ...

  5. 【代码质量】-阿里巴巴java开发手册(代码质量提升神器)学习笔记

    前言:<阿里巴巴 Java 开发手册>是阿里巴巴集团技术团队的集体智慧结晶和经验总结,有了这些前人总结的经验,可以帮助我们写出高质量的代码,同时可以减少Bug数量,少踩坑,提高代码的可读性 ...

  6. 5214页PDF的进阶架构师学习笔记,阿里巴巴内部Jetpack宝典意外流出

    背景 在深度使用 Flutter 开发过程中,我们遇到了业务代码耦合严重,代码可维护性糟糕,如入泥泞.我们需要一个统一的应用框架来摆脱当下的开发困境,而这也是 Flutter 领域空缺的一块处女地. ...

  7. 尚硅谷谷粒学院学习笔记(防坑点的总结部分勘误)

    谷粒学院学习笔记 部分勘误 数据库设计规约 模块说明 环境搭建 创建一个Spring Boot 的父工程,版本使用:2.2.1.RELEASE 父工程pom.xml里面添加 在pom.xml中添加依赖 ...

  8. 尚医通项目学习笔记Part1

    尚医通项目学习笔记 前言 一.目前学习进度 二.学习记录 1.项目简介 1.1 项目所会用到的技术栈 1.2 业务流程 2.项目学习笔记 2.1MyBatis-Plus相关 2.2搭建项目框架 2.3 ...

  9. JDBC学习笔记03【JDBC事务管理、数据库连接池、JDBCTemplate】

    黑马程序员-JDBC文档(腾讯微云)JDBC笔记.pdf:https://share.weiyun.com/Kxy7LmRm JDBC学习笔记01[JDBC快速入门.JDBC各个类详解.JDBC之CR ...

  10. OpenResty简介及学习笔记

    OpenResty简介及学习笔记 摘要 简介 一.OpenResty综述 二.指令说明: *_by_lua *_by_lua_block {lua_script} *_by_lua_file 三.登陆 ...

最新文章

  1. linux内核二当家,Linux PWN从入门到熟练(二)
  2. C#并行编程(1):理解并行
  3. [机器学习笔记]Note15--大规模机器学习
  4. CVPR 2019 | 步步为营!通过迭代式模糊核预测提高超分辨质量
  5. 通過腳本實現zabbix的安裝
  6. android4.4 ssl版本查看,OkHttp在4.4及以下不支持TLS协议的解决方法
  7. HTML 5 input placeholder 属性 实现搜索框提示文字点击输入后消失
  8. Linux下线程同步对象(3)——条件变量
  9. 很不错的js幻灯片代码分享
  10. 阿里巴巴矢量图标库的引入——symbol类型的使用——阿里图标组件封装
  11. YUI3学习(一)---入门
  12. 2021起重机作业 (Q)模拟考试题库及软件
  13. 打印机提示连接计算机,电脑突然不识别连接的打印机,打印机突然显示未连接...
  14. [Qualcomm][Audio] 高通Audio Bringup Guide
  15. 从pwn-summoner理解first fit
  16. 骁龙8gen1Plus和骁龙8gen1区别
  17. MATLAB实现分支定界法求解整数规划
  18. c#-线程-取消架构-Task-简单实验
  19. 【ESP8266-NodeMCU软硬串口通讯】
  20. 在vue项目中使用AntV L7地图下钻,异步调用不重复生成

热门文章

  1. app banner设计
  2. 【数学:杂谈.xxx.一些概念公式笔记】
  3. matlab更新64位api,升级 MEX 文件以使用 64 位 API
  4. WEB网站开发前端命名及书写规范小结
  5. Typora使用指南
  6. 六大最臭名昭著的51%攻击:适者生存才是加密货币的丛林法则
  7. linux创建表单命令,从Linux命令行编写电子表格 | MOS86
  8. 梭子鱼推出AI解决方案实时防御鱼叉式网络钓鱼和网络欺诈
  9. 关于熊掌号对网站SEO的影响
  10. 利用二维图像的深度估计