web-dev-qa-db-ja.com

java)を使用して巨大なExcelファイルを書き込むAPI

Javaを使用してプログラムでExcel(.xls MS Excel 2003形式)ファイルに書き込むことを検討しています。 Excelの出力ファイルには最大200,000行が含まれている可能性があり、これをシート数に分割する予定です(Excelの制限により、シートあたり64k行)。

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();

明らかに、最大2万行(各行に10〜20列)を書き込むと、恐ろしい「Java.lang.OutOfMemoryError:Javaヒープスペース」」が得られます。

XmsおよびXmxパラメーターをXms512mおよびXmx1024として使用して、JVMの初期ヒープサイズと最大ヒープサイズを増やしてみました。それでもファイルに15万行以上を書き込むことはできません。

ファイル全体をメモリにビルドしてからディスクに書き込むのではなく、Excelファイルにストリーミングする方法を探しています。これにより、メモリ使用量を大幅に節約できます。代替のAPIまたはソリューションをいただければ幸いですが、私はJavaの使用に制限されています。ありがとう! :)

16
Jaskirat

既存のすべてのJava APIは、ドキュメント全体をRAMで一度にビルドしようとします。代わりに、新しいxslxファイル形式に準拠するXMLファイルを作成してみてください。はじめに、Excelで目的の形式の小さなファイルを作成して保存することをお勧めします。次に、それを開いて構造を調べ、必要な部分を置き換えます。

ウィキペディアには 全体的なフォーマットに関する良い記事 があります。

7
Aaron Digulla

[〜#〜] sxssf [〜#〜] ワークブックを使用してみてください。これは、巨大なxlsドキュメント、そのビルドドキュメントに最適で、食べないでくださいRAM atすべて、nioを使用する場合

9

ヒープスペースの例外を克服するために、ファイルをいくつかのExcelファイルに分割する必要がありました。 22列の約5k行がそれについてであると考えたので、5k行ごとにファイルを終了し、新しいファイルを開始し、それに応じてファイルを数えるようにロジックを作成しました。

20k以上の行を書き込む場合、データを表す4つ以上の異なるファイルがあります。

4
Chris Dale

繭プロジェクトの HSSFシリアライザー をご覧ください。

HSSFシリアライザーはSAXイベントをキャッチし、MicrosoftExcelで使用されるXLS形式でスプレッドシートを作成します

3
pgras

CSV形式の使用を検討してください。これにより、メモリによる制限がなくなります。おそらく、CSVのデータを事前入力している間だけですが、たとえばLIMIT/OFFSETを使用してDBから行のサブセットをクエリするなど、これも効率的に実行できます。行を書き込む前に、DBテーブルの内容全体をJavaのメモリに取り込むのではなく、ファイルに書き込みます。 1つの「シート」の行数に対するExcelの制限は、約100万に増加します。

そうは言っても、データが実際にDBからのものである場合、Javaがこれに適したツールであるかどうかを強く再考します。ほとんどのまともなDBには、CSVへのエクスポート機能があります。このタスクは間違いなくはるかに効率的です。たとえばMySQLの場合、これには LOAD DATA INFILE コマンドを使用できます。

2
BalusC

JExcelApiもありますが、より多くのメモリを使用します。 .csvファイルを作成してExcelで開く必要があると思います。大量のデータを渡すことができますが、「Excelの魔法」を実行することはできません。

2
IAdapter

この目的のためにJavaライブラリを開発し、現在はオープンソースプロジェクトとして利用可能です https://github.com/jbaliuka/x4j-analytic 。使用しています。運用レポート用。巨大なExcelファイルを生成します。最大200,000は問題なく動作し、Excelはそのようなファイルも開くことができます。コードはPOIを使用してテンプレートを読み込みますが、生成されたコンテンツはXMLまたはメモリ内のオブジェクトモデルレイヤーなしでファイルに直接ストリーミングされます。

1
jbaliuka

このメモリの問題は、セルにデータを挿入するとき、またはデータの計算/生成を実行するときに発生しますか?

事前定義された静的テンプレート形式で構成されるファイルをExcelにロードする場合は、テンプレートを保存して複数回再利用することをお勧めします。通常、テンプレートケースは、毎日の売上レポートなどを生成するときに発生します。

それ以外の場合は、新しい行、境界線、列などを最初から作成する必要があるたびに。

これまでのところ、ApachePOIが私が見つけた唯一の選択肢です。

「明らかに、最大2万行(各行に10〜20列)を書き込むと、恐ろしい「Java.lang.OutOfMemoryError:Javaヒープスペース」」が得られます。」

「エンタープライズIT」

あなたができることは-バッチデータ挿入を実行することです。 1ページを生成した後、毎回キュータスクテーブルを作成し、数秒間休んでから、2番目の部分を続行します。キュータスク中の動的データの変更が心配な場合は、最初に主キーをExcelに取得できます(ユーザービューから列を非表示にしてロックすることにより)。最初の実行は主キーの挿入であり、次に2番目のキューの実行はメモ帳から読み取られ、タスクを部分的に実行します。

0
i need help

非常によく似た同じ量のデータを実行しましたが、POIはリソースに非常に負荷がかかるため、JExcelapiに切り替える必要がありました。 JexcelApiを試してみてください。大きなExcelファイルを操作する必要があるときに後悔することはありません。

0
fvu