EasyExcel写入百万级数据到多sheet---非注解方式
时间:2019-08-30
本文章向大家介绍EasyExcel写入百万级数据到多sheet---非注解方式,主要包括EasyExcel写入百万级数据到多sheet---非注解方式使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
EasyExcel是什么?
快速、简单避免OOM的java处理Excel工具
参考 https://segmentfault.com/a/1190000019472781,https://github.com/alibaba/easyexcel
一、项目需求
从mongo库中查询数据,导出到excel文件中。但是动态导出的excel有多少列、列名是什么、有多少sheet页都需要动态获取。所以生成的excel也必须是动态生成,不能通过注解配置对象映射。而且写入的数据量,有可能达到100W级,使用传统的POI工具,需要把excel数据全部加载到内存空间,内存空间很容易OOM。所以选择了阿里的EasyExcel,据说可以高效的解决POI的OOM问题。
二、测试Demo
1、引入的pom依赖
<dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>1.1.2-beta5</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.17</version> </dependency>
2、测试代码
package com.movitech.product.datahub.util;
import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.context.WriteContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.event.WriteHandler;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.metadata.Table;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.ExcelBuilderImpl;
import org.apache.poi.ss.usermodel.*;
import java.io.*;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
/**
* @Author JAY
* @Date 2019/8/29 11:00
* @Description TODO
**/
public class EasyExcelUtil {
public static String excelFilePath = "C:\\Users\\lenovo\\Desktop\\Jay01-(jay01)-v5自定义导入数据.xls";
public static void main(String[] args) {
try {
writeExcel(excelFilePath);
} catch (IOException e) {
e.printStackTrace();
}
}
public static void writeExcel(String excelFile) throws IOException {
// 文件输出位置
OutputStream out = new FileOutputStream(excelFile);
ExcelWriter writer = EasyExcelFactory.getWriter(out);
// 动态添加表头,适用一些表头动态变化的场景
Sheet sheet1 = new Sheet(1, 0);
sheet1.setSheetName("第一个sheet");
// 创建一个表格,用于 Sheet 中使用
Table table1 = new Table(1);
// 无注解的模式,动态添加表头
table1.setHead(createTestListStringHead());
// 写数据
writer.write1(new ArrayList<>(), sheet1, table1);
// 动态添加表头,适用一些表头动态变化的场景
Sheet sheet2 = new Sheet(2, 0);
sheet2.setSheetName("第2个sheet");
/*
添加TableStyle属性会使内存OOM,没办法满足分批插入100W条数据
TableStyle tableStyle = new TableStyle();
com.alibaba.excel.metadata.Font font = new com.alibaba.excel.metadata.Font();
font.setBold(true);
tableStyle.setTableContentFont(font);
sheet2.setTableStyle(tableStyle);
*/
// 创建一个表格,用于 Sheet 中使用
Table table2 = new Table(2);
// 无注解的模式,动态添加表头
table2.setHead(createTestListStringHead());
writer.write1(new ArrayList<>(), sheet2, table2);
int x = 0;
while (x < 1000000) {
// 模拟分批写入数据到excel,每次写入100条
System.out.println("x = " + x);
Table tableX = new Table(1);
// 每次从sheet的第几行开始写入
sheet1.setStartRow(x);
writer.write1(createDynamicModelList(x), sheet1, tableX);
Table tableX2 = new Table(1);
sheet2.setStartRow(x);
writer.write1(createDynamicModelList(x), sheet2, tableX2);
x = x + 100;
}
// 将上下文中的最终 outputStream 写入到指定文件中
writer.finish();
// 关闭流
out.close();
}
private static List<List<Object>> createDynamicModelList(int x) {
List<List<Object>> rows = new ArrayList<>();
for (int i= x; i < 100 + x; i++){
List<Object> row = new ArrayList<>();
row.add("字符串-" + i);
row.add(Long.valueOf(187837834L) + i);
row.add(Integer.valueOf(2233 + i));
row.add("宁-" + i);
row.add("微信公众号: demo");
rows.add(row);
}
return rows;
}
private static List<List<String>> createTestListStringHead() {
// 模型上没有注解,表头数据动态传入
List<List<String>> head = new ArrayList<List<String>>();
List<String> headCoulumn1 = new ArrayList<String>();
List<String> headCoulumn2 = new ArrayList<String>();
List<String> headCoulumn3 = new ArrayList<String>();
List<String> headCoulumn4 = new ArrayList<String>();
List<String> headCoulumn5 = new ArrayList<String>();
headCoulumn1.add("第1列");
headCoulumn2.add("第2列");
headCoulumn3.add("第3列");
headCoulumn4.add("第4列");
headCoulumn5.add("第5列");
head.add(headCoulumn1);
head.add(headCoulumn2);
head.add(headCoulumn3);
head.add(headCoulumn4);
head.add(headCoulumn5);
return head;
}
}
3、执行结果
总结:
此测试代码可以直接运行测试查看结果。
我配置的jvm运行参数,
我只给了10M空间,但是往excel中写入100W数据,程序并没有出现OOM。可以看到,使用EasyExcel,确实解决了OOM问题。
但是实际情况,EasyExcel不足以满足我的业务需求。因为除了百万级的数据导出之外,还需要进行sheet页隐藏、行隐藏、列隐藏等操作。目前EasyExcel的API,还没有那么多的功能变化。不过,easyExcel提供了自定义拦截器的功能,貌似可以给excel做样式处理。更详细的,我还没有深入研究。大致测试了一下,可以隐藏sheet,但是不知道怎么隐藏列和行。后面待解决吧
原文地址:https://www.cnblogs.com/ningJJ/p/11435465.html
- Jquery闪烁提示特效
- mstsc 远程序桌面登录的 c#开发
- 突然顿悟的Javascript中的this
- 解决Electron加载带jquery的项目报错问题
- dedecms利用addfields body在首页调用文章内容
- 如何设置dedecms自定义表单必填项?
- 如何用<dl>标签做表格而不用table标签
- Gulp使用指南
- Gulp Error: Cannot find module 'jshint/src/cli'
- 自学如何使用Python和Keras构建你自己专属的AlphaZero系统
- 用Visual Studio Code写Node.j
- 帝国CMS搜索页伪静态实现方法
- 5步搭建GO环境
- 你真的了解如何将 Nginx 配置为Web服务器吗
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法