EasyExcel写⼊百万级数据到多sheet---⾮注解⽅式EasyExcel是什么?
碧欧泉隔离霜价格快速、简单避免OOM的java处理Excel⼯具
⼀、项⽬需求
从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、测试代码
vitech.product.datahub.util;
import l.EasyExcelFactory;
import l.ExcelReader;
import l.ExcelWriter;
import l.context.AnalysisContext;
import l.context.WriteContext; import l.event.AnalysisEventListener; import l.event.WriteHandler; import l.metadata.Sheet; import l.metadata.Table; import l.support.ExcelTypeEnum; import
l.write.ExcelBuilderImpl; import org.apache.poi.ss.usermodel.*; import java.io.*; import flect.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 = Writer(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(); l.metadata.Font font = new l.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,但是不知道怎么隐藏⾏。测试代码如下:
(1)隐藏列,通过⾃定义
public static void writeExcelToSheet(String excelFile, Sheet sheet) throws IOException {
// ⽂件输出位置
OutputStream out = new FileOutputStream(excelFile);
ExcelWriter writer = WriterWithTempAndHandler(null, out, ExcelTypeEnum.XLS, true, new WriteHandler() { @Override
public void sheet(int i, org.apache.poi.ss.usermodel.Sheet sheet) {
sheet.setColumnHidden(0,true);
sheet.setColumnHidden(1,true);
}
@Override
public void row(int i, Row row) {
System.out.println("row : " + RowNum());
}
@Override
public void cell(int i, Cell cell) {
System.out.println("cell : " + i);
}
});
Table table1 = new Table(1);
table1.setHead(createTestListStringHead());// 写数据
2009年感动中国十大人物writer.write1(createDynamicModelList(0), sheet, table1);
// 将上下⽂中的最终 outputStream 写⼊到指定⽂件中
writer.finish();
// 关闭流
out.close();
}
(2)隐藏sheet页,通过反射获取Workbook,⽤wb来设置隐藏sheet页
/**
* **获取workbook**
* 因为EasyExcel这个库设计的原因
* 只能使⽤反射获取workbook
*
* @param writer
* @return
*/
private static Workbook getWorkbook(ExcelWriter writer) {
Workbook workbook = null;
try {
Class<?> clazz1 = Class.forName("l.ExcelWriter");
Field[] fs = DeclaredFields();
for (Field field : fs) {
/
/ 要设置属性可达,不然会抛出IllegalAccessException异常
field.setAccessible(true);
if ("excelBuilder".Name())) {
ExcelBuilderImpl excelBuilder = (ExcelBuilderImpl) (writer);
Class<?> clazz2 = Class.forName("l.write.ExcelBuilderImpl"); Field[] fs2 = DeclaredFields();考驾照科目一技巧大全
for (Field field2 : fs2) {
field2.setAccessible(true);
if ("context".Name())) {
大学生年度自我鉴定WriteContext context = (WriteContext) (excelBuilder);
workbook = Workbook();
}
}
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return workbook;
}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论