/ / Apache POI Java Excel Wydajność dla dużych arkuszy kalkulacyjnych - java, wydajność, excel, apache-poi

Apache POI Java Excel Wydajność dla dużych arkuszy kalkulacyjnych - java, performance, excel, apache-poi

Mam arkusz kalkulacyjny, który próbuję czytać za pomocą POI(Mam zarówno formaty xls, jak i xlsx), ale w tym przypadku problem dotyczy pliku xls. Mój arkusz kalkulacyjny ma około 10 000 wierszy i 75 kolumn, a jego odczytanie może potrwać kilka minut (chociaż program Excel otworzy się w ciągu kilku sekund). Korzystam z odczytu opartego na zdarzeniu, zamiast odczytywać cały plik do pamięci. Mięso mojego kodu jest poniżej. W tej chwili jest trochę niechlujny, ale tak naprawdę jest to tylko długa instrukcja przełączania, która została w większości skopiowana z Przykłady punktów POI.

Czy jest to typowe dla wyników POI, w których model zdarzeń jest tak wolny? Czy jest coś, co mogę zrobić, aby to przyspieszyć? Myślę, że kilka minut będzie nie do przyjęcia dla mojej aplikacji.

    POIFSFileSystem poifs = new POIFSFileSystem(fis);
InputStream din = poifs.createDocumentInputStream("Workbook");
try
{
HSSFRequest req = new HSSFRequest();
listener = new FormatTrackingHSSFListener(new HSSFListener() {
@Override
public void processRecord(Record rec)
{
thisString = null;
int sid = rec.getSid();
switch (sid)
{
case SSTRecord.sid:
strTable = (SSTRecord) rec;
break;
case LabelSSTRecord.sid:
LabelSSTRecord labelSstRec = (LabelSSTRecord) rec;
thisString = strTable.getString(labelSstRec
.getSSTIndex()).getString();
row = labelSstRec.getRow();
col = labelSstRec.getColumn();
break;
case RKRecord.sid:
RKRecord rrk = (RKRecord) rec;
thisString = "";
row = rrk.getRow();
col = rrk.getColumn();
break;
case LabelRecord.sid:
LabelRecord lrec = (LabelRecord) rec;
thisString = lrec.getValue();
row = lrec.getRow();
col = lrec.getColumn();
break;
case BlankRecord.sid:
BlankRecord blrec = (BlankRecord) rec;
thisString = "";
row = blrec.getRow();
col = blrec.getColumn();
break;
case BoolErrRecord.sid:
BoolErrRecord berec = (BoolErrRecord) rec;
row = berec.getRow();
col = berec.getColumn();
byte errVal = berec.getErrorValue();
thisString = errVal == 0 ? Boolean.toString(berec
.getBooleanValue()) : ErrorConstants
.getText(errVal);
break;
case FormulaRecord.sid:
FormulaRecord frec = (FormulaRecord) rec;
switch (frec.getCachedResultType())
{
case Cell.CELL_TYPE_NUMERIC:
double num = frec.getValue();
if (Double.isNaN(num))
{
// Formula result is a string
// This is stored in the next record
outputNextStringRecord = true;
}
else
{
thisString = formatNumericValue(frec, num);
}
break;
case Cell.CELL_TYPE_BOOLEAN:
thisString = Boolean.toString(frec
.getCachedBooleanValue());
break;
case Cell.CELL_TYPE_ERROR:
thisString = HSSFErrorConstants
.getText(frec.getCachedErrorValue());
break;
case Cell.CELL_TYPE_STRING:
outputNextStringRecord = true;
break;
}
row = frec.getRow();
col = frec.getColumn();
break;
case StringRecord.sid:
if (outputNextStringRecord)
{
// String for formula
StringRecord srec = (StringRecord) rec;
thisString = srec.getString();
outputNextStringRecord = false;
}
break;
case NumberRecord.sid:
NumberRecord numRec = (NumberRecord) rec;
row = numRec.getRow();
col = numRec.getColumn();
thisString = formatNumericValue(numRec, numRec
.getValue());
break;
case NoteRecord.sid:
NoteRecord noteRec = (NoteRecord) rec;
row = noteRec.getRow();
col = noteRec.getColumn();
thisString = "";
break;
case EOFRecord.sid:
inSheet = false;
}
if (thisString != null)
{
// do something with the cell value
}
}
});
req.addListenerForAllRecords(listener);
HSSFEventFactory factory = new HSSFEventFactory();
factory.processEvents(req, din);

Odpowiedzi:

6 dla odpowiedzi № 1

Zrobiłem też trochę przetwarzania z tysiącamiduże pliki Excela i moim zdaniem UM jest bardzo szybki. Ładowanie plików tego programu Excel również zajmuje około 1 minuty w samym programie Excel. Chciałbym więc potwierdzić, że problem leży w kodzie POI


12 dla odpowiedzi nr 2

Jeśli używasz Apache POI do generowania dużego pliku programu Excel, zwróć uwagę na następujący wiersz:

sheet.autoSizeColumn((short) p);

Ponieważ obniży to wydajność.


2 dla odpowiedzi nr 3

Spróbowałbym użyć streaming hssf, jak również wprowadzony w poi-beta3. Pomogło to w problemach z pamięcią w dużych arkuszach kalkulacyjnych z ponad 1000 kolumnami.


1 dla odpowiedzi nr 4

Zrobiłem trochę bardziej szczegółowego profilowania i wygląda na to, że problem dotyczy kodu poza POI. Po prostu założyłem, że to było wąskie gardło, ale uważam, że jest to nieprawidłowe.


1 dla odpowiedzi nr 5

Jeśli używasz Apache POI do generowania dużego pliku programu Excel, zwróć uwagę na arkusz.autoSizeColumn ((krótki) p); linii, ponieważ wpłynie to na wydajność.

http://stanicblog.blogspot.sg/2013/07/generate-large-excel-report-by-using.html