poi SXSSFWorkbook大数据量导出实践

poi SXSSFWorkbook大数据量导出实践

viEcho Lv5

最近公司做一个生成审批附件的功能,算是对老的功能的一个改造,之前使用的XSSF 和HSSF ;但是一旦数据量超过万级别了,导出的性能就差强人意了;要想快那就必须要要用到poi的SXSSFWorkbook了;

用到的依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<!-- List 操作相关-->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>29.0-jre</version>
</dependency>
<!--poi 导入导出相关-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>

示范代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
public class TestPoi {

public static void main(String[] args) throws Exception{
Long start = System.currentTimeMillis();
List<UserInfo> userInfoList =new ArrayList<>();
for(int i=1;i<=20*10000;i++){
UserInfo userInfo = new UserInfo();
userInfo.setId(Long.getLong(Integer.toString(i)))
.setName("echo"+i)
.setPassword(UUID.randomUUID().toString());
userInfoList.add(userInfo);
}
String fileUrl = "/Users/echo/Desktop/testExcel.xlsx";
FileInputStream fs;
FileOutputStream os = null;
try {
File excel=new File(fileUrl);
fs=new FileInputStream(excel);
XSSFWorkbook workbook = new XSSFWorkbook(fs);
SXSSFWorkbook wb = new SXSSFWorkbook(workbook,1000);//内存中保留 1000 条数据,以免内存溢出,其余写入 硬盘
//获得该工作区的第一个sheet 如果已有模板 和模板名字一致即可
//Sheet sheet1 = wb.createSheet("test");
Sheet sheet1 = wb.getSheetAt(0);
int excelRow = 1;
// List<String> columnList = new ArrayList<>();
// columnList.add("id");
// columnList.add(" 姓名");
// columnList.add("密码");
// //标题行
// Row titleRow = (Row) sheet1.createRow(excelRow++);
// for (int i = 0; i < columnList.size(); i++) {
// Cell cell = titleRow.createCell(i);
// cell.setCellValue(columnList.get(i));
// }
//明细行
List<List<UserInfo>> reParam = Lists.partition(userInfoList, 1000);
for (int x = 0;x<reParam.size();x++) {
List<UserInfo> userInfos = reParam.get(x);
for (int j = 0; j < userInfos.size(); j++) {
Row contentRow = sheet1.createRow(excelRow++);
Cell cell0 = contentRow.createCell(0);
cell0.setCellValue(userInfos.get(j).getPassword());

Cell cell1 = contentRow.createCell(1);
cell1.setCellValue(userInfos.get(j).getName());
Cell cell2 = contentRow.createCell(2);
cell2.setCellValue(userInfos.get(j).getPassword());
}
}
os = new FileOutputStream(fileUrl);
wb.write(os);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (os != null) {
os.close();
}
} catch (IOException e) {
e.printStackTrace();
} // 关闭输出流
}
System.out.println("导20万数据耗时:"+(System.currentTimeMillis()-start));
}
}

总结

SXSSFWorkbook 有个缓存区,所以上面定义为1000,后面的数据就需要按1000拆分写到excel中,如果不设定此值有可能OOM,按1000拆分后,注意创建行的行号就行了!

  • Title: poi SXSSFWorkbook大数据量导出实践
  • Author: viEcho
  • Created at : 2021-04-23 19:55:09
  • Updated at : 2024-01-18 14:53:56
  • Link: https://viecho.github.io/2021/0423/poi-big-count-datas-export.html
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments
On this page
poi SXSSFWorkbook大数据量导出实践