Javaを使用して巨大なExcelファイルを記述するAPI
-
18-09-2019 - |
質問
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();
明らかに、〜20k行を書く(各行に10〜20列の列)は、恐ろしい「java.lang.outofmemoryerror:Java Heap Space」を与えてくれます。
XMSおよびXMXパラメーターをXMS512MおよびXMX1024として使用して、JVMの初期豪華と最大ヒープサイズを増やしてみました。それでもファイルに15万行以上を書き込むことはできません。
ディスクに書き込む前に、ファイル全体をメモリ内に構築する代わりにExcelファイルにストリーミングする方法を探しています。代替のAPIまたはソリューションは大歓迎ですが、Javaの使用に制限されています。ありがとう! :)
解決
既存のすべてのJava APIは、ドキュメント全体を一度に作成しようとします。代わりに、新しいXSLXファイル形式に適合するXMLファイルを記述してみてください。開始するために、Excelで目的のフォームで小さなファイルを構築して保存することをお勧めします。次に、それを開き、構造を調べ、必要な部品を交換します。
ウィキペディアには 全体的な形式に関する良い記事.
他のヒント
使用してみてください SXSSF ワークブック、それは巨大なXLSドキュメント、そのビルドドキュメントに最適なものであり、NIOを使用しているため、まったくRAMを食べないでください
ヒープスペースの例外を克服するために、ファイルをいくつかのExcelファイルに分割する必要がありました。 22列の約5k列がそれについてであると考えたので、5k行ごとにファイルを終了し、新しいものを開始し、それに応じてファイルを数値にするだけで、ロジックを作成しました。
20k +行が書かれている場合、データを表す4つ以上の異なるファイルがあります。
を見てください HSSFシリアナー Cocoonプロジェクトから。
HSSFシリアイザーはSAXイベントをキャッチし、Microsoft Excelが使用するXLS形式でスプレッドシートを作成します
Jexcelapiもありますが、より多くのメモリを使用しています。 .csvファイルを作成し、Excelで開く必要があると思います。多くのデータを渡すことができますが、「Excel Magic」を実行することはできません。
CSV形式の使用を検討してください。これにより、メモリに制限されなくなりました - おそらく、CSVのデータを事前に設定する際のみですが、これも効率的に行うことができます。 LIMIT/OFFSET
そして、ラインを書く前に、DBテーブルの内容全体をJavaのメモリに運搬する代わりに、すぐにそれを書き込みます。 1つの「シート」での列の量のExcel制限は、約100万に増加します。
とはいえ、データが実際にDBから来ている場合、Javaがこのための適切なツールであるかどうかを高度に再考します。ほとんどのまともなDBには、このタスクをより効率的に行うことができるエクスポートツーCSV関数があります。たとえばMySQLの場合、 LOAD DATA INFILE
このためのコマンド。
この目的のためにJavaライブラリを開発しましたが、現在はオープンソースプロジェクトとして利用できます https://github.com/jbaliuka/x4j-analytic 。運用レポートに使用します。私たちは巨大なExcelファイルを生成します。〜200,000は問題なく動作するはずです。Excelはそのようなファイルも開くことができます。私たちのコードはPOIを使用してテンプレートをロードしますが、生成されたコンテンツは、メモリ内のXMLまたはオブジェクトモデルレイヤーなしでファイルに直接ストリーミングされます。
このメモリの問題は、データをセルに挿入するとき、またはデータの計算/生成を実行するときに発生しますか?
事前定義された静的テンプレート形式で構成されるExcelにファイルをロードする場合は、テンプレートを保存して複数の時間を再利用することをお勧めします。通常、テンプレートのケースは、毎日の販売レポートなどを生成するときに発生します...
それ以外の場合、新しい行、境界線、列などをゼロから作成する必要があるたびに。
これまでのところ、Apache Poiは私が見つけた唯一の選択肢です。
「明らかに、〜20k行を書く(各行に10〜20列の列)は、恐ろしい「java.lang.outofmemoryerror:java heap space」」を与えてくれます。
「エンタープライズIT」
できることは、バッチデータ挿入を実行することです。 Queetaskテーブルを作成し、1ページを生成するたびに数秒間休み、2番目の部分を続行します。キュータスク中に動的なデータが変更されることを心配している場合は、最初にプライマリキーをExcelに入れることができます(ユーザービューから列を隠してロックすることで)。最初の実行はプライマリキーを挿入し、次に2番目のキューランをノートパッドから読み取り、タスク部分を部分的に実行します。
私たちは非常に似たような、同じ量のデータを行いました。POIはリソースに非常に重いため、Jexcelapiに切り替える必要がありました。 jexcelapiを試してみてください、大きなエクセルファイルを操作する必要があるとき、あなたはそれを後悔することはありません!