使用java编写大量excel文件的API

时间:2009-09-28 09:15:53

标签: java excel apache-poi

我希望使用Java以编程方式编写excel(.xls MS Excel 2003格式)文件。 excel输出文件可能包含~200,000行,我打算将其分成多张(每张64k行,由于excel限制)。

我尝试过使用apache POI API,但由于API对象模型,它似乎是一个内存耗尽。我被迫将单元格/工作表添加到内存中的工作簿对象中,只有添加了所有数据后,我才能将工作簿写入文件!以下是apache建议如何使用API​​编写excel文件的示例:

Workbook wb = new HSSFWorkbook();
Sheet sheet = wb.createSheet("new sheet");

//Create a row and put some cells in it
Row row = sheet.createRow((short)0);

// Create a cell and put a value in it.
Cell cell = row.createCell(0);
cell.setCellValue(1);

// Write the output to a file
FileOutputStream fileOut = new FileOutputStream("workbook.xls");
wb.write(fileOut);
fileOut.close();

显然,编写~20k行(每行有10-20列)给了我可怕的“java.lang.OutOfMemoryError:Java堆空间”。

我尝试使用Xms和Xmx参数将XVM初始堆大小和最大堆大小增加为Xms512m和Xmx1024。仍然无法在文件中写入超过150k行。

我正在寻找一种流式传输到excel文件的方法,而不是在将其写入磁盘之前在内存中构建整个文件,这有望节省大量内存。任何替代API或解决方案都将受到赞赏,但我仅限于使用java。谢谢! :)

9 个答案:

答案 0 :(得分:9)

尝试使用SXSSF工作簿,这对于巨大的xls文档,它的构建文档来说很棒,并且根本不吃RAM,因为使用了nio

答案 1 :(得分:6)

所有现有的Java API都尝试一次在RAM中构建整个文档。尝试编写符合新xslx文件格式的XML文件。为了帮助您入门,我建议您在Excel中以所需的形式构建一个小文件并保存。然后打开它并检查结构并更换所需的部件。

维基百科有good article about the overall format

答案 2 :(得分:4)

我不得不将我的文件拆分成几个excel文件,以克服堆空间异常。我认为大约有5k行,有22列是关于它的,所以我只是制作了我的逻辑,以便每5k行我将结束文件,启动一个新的并且只是相应地计算文件。

在我要写20k +行的情况下,我会有4个以上的不同文件代表数据。

答案 3 :(得分:3)

查看cocoon项目中的HSSF serializer

  

HSSF序列化程序捕获SAX事件并以Microsoft Excel使用的XLS格式创建电子表格

答案 4 :(得分:2)

还有JExcelApi,但它使用更多内存。我认为你应该创建.csv文件并在excel中打开它。它允许你传递大量数据,但你不能做任何“excel magic”。

答案 5 :(得分:1)

考虑使用CSV格式。这样你就不再受内存的限制了 - 也许只是在预先填充CSV的数据时,这也可以有效地完成,例如使用例如LIMIT/OFFSET查询来自DB的行的子集并立即将其写入文件,而不是在写入任何行之前将整个数据库表内容拖入Java的内存中。一个“工作表”中行数量的Excel限制将增加到大约一百万。

也就是说,如果数据实际来自数据库,那么我会高度重新考虑Java是否是正确的工具。最优秀的数据库具有导出到CSV功能,可以毫无效地完成这项任务。例如,对于MySQL,您可以使用LOAD DATA INFILE命令。

答案 6 :(得分:1)

我们为此目的开发了一个java库,目前它可以作为开源项目https://github.com/jbaliuka/x4j-analytic使用。我们将其用于运营报告。 我们生成巨大的Excel文件,大约200,000应该没有问题,Excel也设法打开这样的文件。 我们的代码使用POI加载模板,但生成的内容直接流式传输到文件而没有内存中的XML或对象模型层。

答案 7 :(得分:0)

将数据插入单元格或执行数据计算/生成时会发生此内存问题吗?

如果要将文件加载到包含预定义静态模板格式的Excel中,则最好保存模板并重复使用多次。通常情况下,模板案例会在您要生成每日销售报告等时发生......

否则,每次你需要从头开始创建新的行,边框,列等。

到目前为止,Apache POI是我找到的唯一选择。

“很明显,编写~20k行(每行有10-20列)给了我可怕的”java.lang.OutOfMemoryError:Java堆空间“。”

“企业IT”

您可以做的是 - 执行批量数据插入。创建一个queuetask表,每次生成1页后,休息几秒钟,然后继续第二部分。如果您担心队列任务期间的动态数据更改,您可以先将主键放入Excel中(通过隐藏和锁定用户视图中的列)。首先运行将插入主键,然后第二个运行的队列将从记事本中读出并按部分执行任务。

答案 8 :(得分:0)

我们做了类似的,相同数量的数据,我们不得不切换到JExcelapi,因为POI对资源非常重视。试试JexcelApi,当你不得不操纵大型Excel文件时,你不会后悔!