16

我希望使用 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 heap space”。

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

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

4

9 回答 9

10

尝试使用SXSSF工作簿,这对于巨大的 xls 文档来说是件好事,它的构建文档根本不吃内存,因为使用 nio

于 2013-08-08T08:10:06.970 回答
7

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

维基百科有一篇关于整体格式的好文章

于 2009-09-28T09:31:56.207 回答
4

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

在我有 20k + 行要写入的情况下,我将有 4+ 个不同的文件表示数据。

于 2009-12-21T12:17:27.013 回答
3

查看cocoon 项目中的HSSF 序列化程序。

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

于 2009-09-28T12:41:43.610 回答
2

还有 JExcelApi,但它使用更多的内存。我认为您应该创建 .csv 文件并在 excel 中打开它。它允许您传递大量数据,但您将无法执行任何“excel 魔术”。

于 2009-09-28T09:31:02.000 回答
2

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

也就是说,如果数据实际上来自数据库,那么我会高度重新考虑 Java 是否是正确的工具。大多数体面的数据库都有一个导出到 CSV 的功能,可以毫无疑问地更有效地完成这项任务。例如,在 MySQL 的情况下,您可以使用该LOAD DATA INFILE命令。

于 2009-12-09T16:53:50.863 回答
1

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

于 2013-10-04T14:22:51.307 回答
0

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

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

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

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

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

“企业信息化”

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

于 2009-09-28T09:22:49.123 回答
0

我们做了一些非常相似的事情,同样数量的数据,我们不得不切换到 JExcelapi,因为 POI 的资源太重了。试试 JexcelApi,当你不得不操作大的 Excel 文件时,你不会后悔的!

于 2009-09-28T10:13:54.027 回答