今天,一朋友问我使用JAVA有没有什么办法导出百万级的数据到Excel工作表。

  当时我的第一个念头就是这真的是一个好疯狂的念头。然后就想假如真的有这样类似的需求,我自己应该怎么做呢?

  

  ps: 首先科普一下基础知识

  Excel 2003及以下的版本。一张表最大支持65536行数据,256列。也就是说excel2003完全不可能满足百万数据导出的需求。

  Excel 2007-2010版本。一张表最大支持1048576行,16384列;

  笔者使用的是office 2010,更高的版本笔者没有使用过,暂时无法判断。

  由此看来百万级的数据量对Excel自身已经是属于接近极限的程度。

  假如我们有更大的需求怎么办呢?

  既然单表支持最大是104w条数据,那么更大的需求量我们就只能通过程序级分表操作的方式来实现了。O(∩_∩)O哈哈~

  对于操作Excel的类库。笔者其实了解的并不是很多。只是很早以前使用过POI这个类库,感觉很不错。于是决定从它入手。看看POI有没有什么比较有效的好点的解决办法。由于笔者以前使用的POI版本比较低。而且使用于excel 2003版本。所以遇到了不少问题。

  

  编辑器: Intellij IDEA 13.2

  类库需求: POI-3.10-Final

  1. 1 <dependency>
  2. 2 <groupId>org.apache.poi</groupId>
  3. 3 <artifactId>poi</artifactId>
  4. 4 <version>3.10-FINAL</version>
  5. 5 </dependency>

  新建一个Maven项目。

  根据笔者以往的经验,直接使用POI写了一份代码。执行的时候直接报错了。

  1. 1 public static void Excel2003Operate(String filePath) throws Exception {
  2. 2 HSSFWorkbook hssfWorkbook = new HSSFWorkbook(new FileInputStream(new File(filePath)));
  3. 3 HSSFSheet sheet = hssfWorkbook.getSheetAt(0);
  4. 4 for (int i = 0; i < 10000; i++) {
  5. 5 HSSFRow hssfRow = sheet.createRow(i);
  6. 6 for (int j = 0; j < 10; j++) {
  7. 7 HSSFCellUtil.createCell(hssfRow, j, String.valueOf(Math.random()));
  8. 8 }
  9. 9 }
  10. 10 FileOutputStream out = new FileOutputStream("workbook.xlsx");
  11. 11 hssfWorkbook.write(out);
  12. 12 out.close();
  13. 13 }
  1. 1 Connected to the target VM, address: '127.0.0.1:62382', transport: 'socket'
  2. 2 Exception in thread "main" org.apache.poi.poifs.filesystem.OfficeXmlFileException: The supplied data appears to be in the Office 2007+ XML. You are calling the part of POI that deals with OLE2 Office Documents. You need to call a different part of POI to process this data (eg XSSF instead of HSSF)
  3. 3 at org.apache.poi.poifs.storage.HeaderBlock.<init>(HeaderBlock.java:131)
  4. 4 at org.apache.poi.poifs.storage.HeaderBlock.<init>(HeaderBlock.java:104)
  5. 5 at org.apache.poi.poifs.filesystem.POIFSFileSystem.<init>(POIFSFileSystem.java:128)
  6. 6 at org.apache.poi.hssf.usermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:342)
  7. 7 at org.apache.poi.hssf.usermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:323)
  8. 8 at dev.tinyz.excel.POIUtil.Excel2003Operate(POIUtil.java:23)
  9. 9 at dev.tinyz.excel.Main.main(Main.java:16)
  10. 10 Disconnected from the target VM, address: '127.0.0.1:62382', transport: 'socket'

  运行直接报错了。仔细看了报错信息之后发现。POI要操作excel 2007及以上的版本需要使用XSSF来代替上面代码的HSSF。

  

  发现类库居然没有XSSF相关的类。着笔者傻眼了说。于是去POI官网查看。发现完整的POI类库包含的内容很多。于是详细了解了一下每个部分的具体作用:

  poi-ooxml和poi-ooxml-schemas是poi对2007及以上版本的扩充。于是在maven依赖中增加:

  1. 1 <dependency>
  2. 2 <groupId>org.apache.poi</groupId>
  3. 3 <artifactId>poi-ooxml</artifactId>
  4. 4 <version>3.10-FINAL</version>
  5. 5 </dependency>
  6. 6 <dependency>
  7. 7 <groupId>org.apache.poi</groupId>
  8. 8 <artifactId>poi-ooxml-schemas</artifactId>
  9. 9 <version>3.10-FINAL</version>
  10. 10 </dependency>

  赶紧修改自己的代码。实现了支持Excel 2010版本。瞬间有种大功告成的感觉,有木有。。O(∩_∩)O哈哈~。好有成就感的说。

  1. 1 public static void Excel2007AboveOperateOld(String filePath) throws IOException {
  2. 2 XSSFWorkbook workbook = new XSSFWorkbook(new FileInputStream(new File(filePath)));
  3. 3 // 获取第一个表单
  4. 4 Sheet first = workbook.getSheetAt(0);
  5. 5 for (int i = 0; i < 100000; i++) {
  6. 6 Row row = first.createRow(i);
  7. 7 for (int j = 0; j < 11; j++) {
  8. 8 if(i == 0) {
  9. 9 // 首行
  10. 10 row.createCell(j).setCellValue("column" + j);
  11. 11 } else {
  12. 12 // 数据
  13. 13 if (j == 0) {
  14. 14 CellUtil.createCell(row, j, String.valueOf(i));
  15. 15 } else
  16. 16 CellUtil.createCell(row, j, String.valueOf(Math.random()));
  17. 17 }
  18. 18 }
  19. 19 }
  20. 20 // 写入文件
  21. 21 FileOutputStream out = new FileOutputStream("workbook.xlsx");
  22. 22 workbook.write(out);
  23. 23 out.close();
  24. 24 }

  赶紧运行跑起来。第一次测试写入1w条数据。耗时8秒多点。感觉写入速度好慢,1w条8秒,100w。。我的天。这效率完全不能接受。于是测试10w,看看测试一下是不是真的写入速度过慢。测试结果让人崩溃。

  1. 1 Cast time : 49699

  测试导出10w条数据到excel耗时将近50秒。于是这种方式被暂时放弃。成就感瞬间被打落在地。

  

  再次回到POI的官网。http://poi.apache.org/spreadsheet/index.html

  官方提到自POI3.8版本开始提供了一种SXSSF的方式,用于超大数据量的操作。于是...

  原文:

  SXSSF is an API-compatible streaming extension of XSSF to be used when very large spreadsheets have to be produced...

  

    马上开动修改代码。代码如下:

  1. 1 public static void Excel2007AboveOperate(String filePath) throws IOException {
  2. 2 XSSFWorkbook workbook1 = new XSSFWorkbook(new FileInputStream(new File(filePath)));
  3. 3 SXSSFWorkbook sxssfWorkbook = new SXSSFWorkbook(workbook1, 100);
  4. 4 // Workbook workbook = WorkbookFactory.create(new FileInputStream(new File(filePath)));
  5. 5 Sheet first = sxssfWorkbook.getSheetAt(0);
  6. 6 for (int i = 0; i < 100000; i++) {
  7. 7 Row row = first.createRow(i);
  8. 8 for (int j = 0; j < 11; j++) {
  9. 9 if(i == 0) {
  10. 10 // 首行
  11. 11 row.createCell(j).setCellValue("column" + j);
  12. 12 } else {
  13. 13 // 数据
  14. 14 if (j == 0) {
  15. 15 CellUtil.createCell(row, j, String.valueOf(i));
  16. 16 } else
  17. 17 CellUtil.createCell(row, j, String.valueOf(Math.random()));
  18. 18 }
  19. 19 }
  20. 20 }
  21. 21 FileOutputStream out = new FileOutputStream("workbook.xlsx");
  22. 22 sxssfWorkbook.write(out);
  23. 23 out.close();
  24. 24 }

  多次运行测试。查看数据

  1. 1 Cast time : 11604

  看到数据的瞬间感觉,哇塞。好给力的说。居然从将近50秒缩短带11秒。。。

  为什么都是代码差距就这么大呢?

  原来,SXSSF实现了一套自动刷入数据的机制。当数据数量达到一定程度时(用户可以自己设置这个限制)。像文本中刷入部分数据。这样就缓解了程序运行时候的压力。达到高效的目的。O(∩_∩)O哈哈~

  再一次测试单表写入100w条数据。

  1. 1 Cast time : 87782

  将近90秒就完成了100w条数据的写入。O(∩_∩)O哈哈~。   虽然看上去依旧有一点慢。但是考虑到数据量这样的耗时,想来已经是可以接受的了。100w条数据生成的Excel表单居然有136mb。打开就这个文档都花了不少时间。哈哈

  晒一下成就:

  

 转自:http://www.cnblogs.com/zou90512/p/3989450.html

JAVA笔记-如何将百万级数据高效的导出到Excel表单的更多相关文章

  1. Java导出Pdf格式表单

    前言   作为开发人员,工作中难免会遇到复杂表单的导出,接下来介绍一种通过Java利用模板便捷导出Pdf表单的方式 模拟需求   需求:按照下面格式导出pdf格式的学生成绩单 准备工作 Excel软件 ...

  2. java中的数据导出到Excel表中

    整个项目中导出数据到.Excel的源码 import java.io.BufferedOutputStream; import java.io.FileInputStream; import java ...

  3. Java 添加、删除Excel表单控件

    通过表单控件,用户可以快速地将数据填写到模板文档中,轻松引用单元格数据并与其进行交互.本文通过Java代码示例介绍如何在Excel表格中添加表单控件,包括文本框.单选按钮.复选框.组合框.微调按钮等: ...

  4. BI之路学习笔记2--SSIS/ETL设计练习三:《DB->定期生成excel表》

    上次笔记记到,用sql任务给参数赋值,映射到变量,然后把数据流任务放到序列容器中进行执行,可以定期生成excel, 现在的问题是: 在EXCEL目标编辑过程中,必须选定某一个特定的excel目标,这样 ...

  5. 前端笔记之React(二)组件内部State&React实战&表单元素的受控

    一.组件内部的State 1.1 state state叫状态,是每一个类式组件都有的属性,但函数式组件,没有state. state是一个对象,什么值都可以定义. 在任何类式组件的构造函数中,可以用 ...

  6. 使用jQuery快速高效制作网页交互特效---表单校验

    表单基本验证技术 为什么需要表单验证 减轻服务器的压力 保证输入的数据符合要求 常用的表单验证 1.日期格式 2.表单元素是否为空 3.用户名和密码 4.E-mail地址 5.身份证号码 表单选择器 ...

  7. PHP百万级数据导出方案(多csv文件压缩)

    本文转自网络仅供学习之用 概述: 最近公司项目要求把数据除了页面输出也希望有导出功能,虽然之前也做过几个导出功能,但这次数据量相对比较大,差不多一天数据就20W条,要求导7天或者30天,那么数据量就轻 ...

  8. Java 创建、填充PDF表单域

    表单域,可以按用途分为多种不同的类型,常见的有文本框.多行文本框.密码框.隐藏域.复选框.单选框和下拉选择框等,目的是用于采集用户的输入或选择的数据.下面的示例中,将分享通过Java编程在PDF中添加 ...

  9. Java实现将Excel导入数据库和从数据库中导出为Excel

    实现的功能: 用Java实现从Excel导入数据库,如果存在就更新 将数据库中的数据导出为Excel 1.添加jxl.jar mysql-connector-java.1.7-bin.jar包到项目的 ...

随机推荐

  1. 下载Eclipse

    工欲善其事必先利其器,我们学习Java首先要学会下载开发工具,Eclipse就是一个很好的Java语言开发工具,那么我们首先要知道怎么下载Eclipse.相信很多Java书籍都有下载Eclipse的教 ...

  2. Spark(十五)SparkCore的源码解读

    一.启动脚本分析 独立部署模式下,主要由master和slaves组成,master可以利用zk实现高可用性,其driver,work,app等信息可以持久化到zk上:slaves由一台至多台主机构成 ...

  3. USACO 4.4 Pollutant Control (网络流求最小割割集)

    Pollutant ControlHal Burch It's your first day in Quality Control at Merry Milk Makers, and already ...

  4. HDU - 5136 2014icpc南京现场赛J 计数dp

    题目大意:给你一个树的直径k,要求每个点的度数不超过3, 问你有多少棵树满足条件. 思路:好难啊. 主要思想就是将一棵无根二叉树树划分成有根二叉树. 我们对k的分奇偶讨论: 我们定义dp[ i ] 为 ...

  5. Ext.example.msg()应用

    ①需要在开发包中包含文件夹example/shared中的example.js和example.css两个文件即可. ②在html文件中引入: <script src="../extj ...

  6. Error after SQL Server 2012 installation: Login Failure for "SQL Server Integration Services 11.0" SSIS service

    When you install SQL Server 2012 and you try to connect to SSIS services, you cannot due to that the ...

  7. 1013 Battle Over Cities (25)(25 point(s))

    problem It is vitally important to have all the cities connected by highways in a war. If a city is ...

  8. opencv 加载 修改 保存 图像

    #include <opencv2/opencv.hpp> #include <iostream> using namespace cv; /* 1 加载图像 cv::imre ...

  9. BZOJ2111 ZJOI2010排列计数

    根据Pi>Pi/2可以看出来这是一个二叉树 所以我们可以用树形DP的思想 f[i]=f[i<<1]*f[i<<1|1]*C(s[i]-1,s[i<<1]),s ...

  10. 【堆优化Dijkstra+字典序最短路方案】HDU1385-Minimum Transport Cost

    [题目大意] 给出邻接矩阵以及到达各个点需要付出的代价(起点和终点没有代价),求出从给定起点到终点的最短路,并输出字典序最小的方案. [思路] 在堆优化Dijkstra中,用pre记录前驱.如果新方案 ...