40

大きな(30k以上の行)xlsxファイルのすべての行を自動調整する必要があります。

apache poiを介した次のコードは、小さなファイルでは機能しますが、OutOfMemoryError大きなファイルでは機能しません。

Workbook workbook = WorkbookFactory.create(inputStream);
Sheet sheet = workbook.getSheetAt(0);

for (Row row : sheet) {
    row.setHeight((short) -1);
}

workbook.write(outputStream);

更新:残念ながら、ヒープサイズを増やすことはオプションではありません-OutOfMemoryErrorに表示され-Xmx1024m、30k行は上限ではありません。

4

9 に答える 9

36

イベントAPIを使用してみてください。詳細については、POIドキュメントのイベントAPI(HSSFのみ)およびXSSFとSAX(イベントAPI)を参照してください。そのページからの引用のカップル:

HSSF:

イベントAPIはユーザーAPIよりも新しいです。これは、低レベルのAPI構造を少し学ぶことをいとわない中級の開発者を対象としています。使い方は比較的簡単ですが、Excelファイルの各部分の基本的な理解(または学習意欲)が必要です。提供される利点は、比較的小さなメモリフットプリントでXLSを読み取ることができることです。

XSSF:

メモリフットプリントが問題になる場合は、XSSFの場合、基になるXMLデータを取得して、自分で処理できます。これは、.xlsxファイルの低レベルの構造を少し習得し、JavaでXMLを処理することに満足している中級の開発者を対象としています。使い方は比較的簡単ですが、ファイル構造の基本を理解している必要があります。提供される利点は、比較的小さなメモリフットプリントでXLSXファイルを読み取ることができることです。

出力については、1つの可能なアプローチがブログ投稿Streamingxlsxfilesで説明されています。(基本的に、XSSFを使用してコンテナーXMLファイルを生成し、実際のコンテンツをプレーンテキストとしてxlsx zipアーカイブの適切なxml部分にストリーミングします。)

于 2011-02-18T06:58:46.267 に答える
11

ストリームの代わりにファイルを使用することで、メモリ使用量を劇的に改善できます。(ストリーミングAPIを使用することをお勧めしますが、ストリーミングAPIには制限があります。http://poi.apache.org/spreadsheet/index.htmlを参照してください)

だから代わりに

Workbook workbook = WorkbookFactory.create(inputStream);

行う

Workbook workbook = WorkbookFactory.create(new File("yourfile.xlsx"));

これは次のとおりです:http://poi.apache.org/spreadsheet/quick-guide.html#FileInputStream

ファイルとInputStreams

「.xlsHSSFWorkbookまたは.xlsxXSSFWorkbookのいずれかのワークブックを開くとき、ワークブックはファイルまたはInputStreamのいずれかからロードできます。Fileオブジェクトを使用すると、メモリ消費量を減らすことができますが、InputStreamはより多くのメモリを必要とします。ファイル全体をバッファリングします。」

于 2013-07-09T07:29:41.057 に答える
3

私は、行がはるかに少ないが文字列が大きいという同じ問題を抱えていました。

データをロードしておく必要がないので、XSSFの代わりにSXSSFを使用できることがわかりました。

それらは同様のインターフェースを持っており、すでにたくさんのコードを書いている場合に役立ちます。ただし、SXSSFを使用すると、ロードし続ける行の量を設定できます。

ここにリンクがあります。 http://poi.apache.org/spreadsheet/how-to.html#sxssf

于 2013-05-23T04:34:19.710 に答える
2

スタイルを自動調整または設定したり、すべての行を大きな(30k行以上)xlsxファイルに書き込んだりする場合は、SXSSFWorkbookを使用してください。これが役立つサンプルコードです...

SXSSFWorkbook wb = new SXSSFWorkbook();
            SXSSFSheet sheet = (SXSSFSheet) wb.createSheet("writetoexcel");
            Font font = wb.createFont();
                font.setBoldweight((short) 700);
                // Create Styles for sheet.
                XSSFCellStyle Style = (XSSFCellStyle) wb.createCellStyle();
                Style.setFillForegroundColor(new XSSFColor(java.awt.Color.LIGHT_GRAY));
                Style.setFillPattern(XSSFCellStyle.SOLID_FOREGROUND);
                Style.setFont(font);
                //iterating r number of rows
            for (int r=0;r < 30000; r++ )
            {
                Row row = sheet.createRow(r);
                //iterating c number of columns
                for (int c=0;c < 75; c++ )
                {
                    Cell cell = row.createCell(c);
                    cell.setCellValue("Hello"); 
                    cell.setCellStyle(Style);
                }
    }
            FileOutputStream fileOut = new FileOutputStream("E:" + File.separator + "NewTest.xlsx");
于 2015-02-28T06:54:21.347 に答える
1

HSSFファイル(.xls)にEvent APIを使用しましたが、レコードの順序に関するドキュメントがひどく不足していることがわかりました。

于 2011-03-17T01:28:24.947 に答える
0

XLSXに書き込む場合は、同じExcelファイルの別のシートに書き込むことで改善が見られました。また、別のExcelファイルに書き込むことで改善が見られる場合があります。ただし、最初に別のシートに書き込んでみてください。

于 2013-08-04T18:00:37.793 に答える
0

この最良の例は、次のスタックオーバーフロースレッドで説明されています 。ApachePOIを介した大きなExcelファイル(xlsx)の読み取り中にエラーが発生しました

そのトピックのメインアンサーのコードスニペットは、SAXxml解析をラップするApachePOIと、すべてのシートを簡単にループしてから個々のセルをループする方法を示しています。

endRow()APIは処理が終了した現在の行番号を提供するため、コードはApachePOIAPIの現在の実装では古くなっています。

そのコードスニペットを使用すると、大きなXLSXファイルをセルごとに解析するのは簡単です。例:各シート; 行セルごと。行はイベントを終了しました。各行のでcolumneNameからcellValueへのマップを作成するアプリロジックを簡単に作成できます。

于 2016-01-18T15:10:08.607 に答える
0

XSSFが1GBのヒープを割り当てる800,000セルと3M文字でも同じ問題が発生しました。

Pythonを使用しopenpyxlnumpyxlsxファイル(Javaコードから)を読み取り、最初にそれを通常のテキストに変換しました。次に、テキストファイルをJavaでロードしました。オーバーヘッドが大きいように見えるかもしれませんが、確かに高速です。

Pythonスクリプトは次のようになります

import openpyxl as px
import numpy as np

# xlsx file is given through command line foo.xlsx
fname = sys.argv[1]
W = px.load_workbook(fname, read_only = True)
p = W.get_sheet_by_name(name = 'Sheet1')

a=[]
# number of rows and columns
m = p.max_row
n = p.max_column

for row in p.iter_rows():
    for k in row:
        a.append(k.value)

# convert list a to matrix (for example maxRows*maxColumns)
aa= np.resize(a, [m, n])

# output file is also given in the command line foo.txt
oname = sys.argv[2]
print (oname)
file = open(oname,"w")
mm = m-1
for i in range(mm):
    for j in range(n):
        file.write( "%s " %aa[i,j]  )
    file.write ("\n")

# to prevent extra newline in the text file
for j in range(n):
    file.write("%s " %aa[m-1,j])

file.close()

それから私のJavaコードで、私は書いた

try {
  // `pwd`\python_script  foo.xlsx  foo.txt
  String pythonScript =  System.getProperty("user.dir") + "\\exread.py ";
  String cmdline = "python " + pythonScript +
                    workingDirectoryPath + "\\" + fullFileName + " " + 
                    workingDirectoryPath + "\\" + shortFileName + ".txt";
  Process p = Runtime.getRuntime().exec(cmdline);
  int exitCode = p.waitFor();
  if (exitCode != 0) {
    throw new IOException("Python command exited with " + exitCode);
  }
} catch (IOException e) {
  System.out.println( e.getMessage() );
} catch (InterruptedException e) {
  ReadInfo.append(e.getMessage() );
}

その後、foo.xlsxに似ていますが、テキスト形式のfoo.txtが取得されます。

于 2017-05-05T18:44:26.397 に答える
0

XML構造を処理するためにSAXパーサーを使用しました。XLSXファイルで機能します。

https://stackoverflow.com/a/44969009/4587961

于 2017-07-07T10:57:07.660 に答える