Apache POI Java Excel Performance pour de Grandes feuilles de calcul
J'ai une feuille de calcul, je suis en train de lire avec POI (j'ai à la fois aux formats xls et xlsx formats), mais dans ce cas, le problème est avec le fichier xls. Ma feuille de calcul a environ 10 000 lignes et 75 colonnes, et de la lecture il peut prendre plusieurs minutes (si Excel s'ouvre en quelques secondes). Je suis à l'aide de l'événement en fonction de la lecture, plutôt que de lire tout le fichier en mémoire. La viande de mon code est ci-dessous. C'est un peu brouillon, mais c'est vraiment juste une longue instruction switch qui a surtout été copié à partir de la PI exemples.
Il est typique pour les PI performances en utilisant le modèle d'événement pour être si lent? Est-il quelque chose que je faire pour accélérer les choses? Je pense que plusieurs minutes peut être inacceptable pour mon application.
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);
xlsx est encore plus lente. Je voulais simplement dire que je suis à l'aide de PI au lieu de quelque chose comme JExcel parce que j'ai besoin de traiter à la fois aux formats xls et xlsx.
OriginalL'auteur Jeff Storey | 2011-05-13
Vous devez vous connecter pour publier un commentaire.
Je l'ai fait aussi un traitement avec des milliers de grands fichiers excel et à mon avis PVE est très rapide. Chargement de fichiers excel touques également environ 1 minute dans Excel lui-même. Donc, je voudrais confirmer que le problème vient de POI code
OriginalL'auteur ludwigm
f vous utilisez Apache POI pour générer un grand fichier excel, veuillez prendre note de la ligne suivante :
sheet.autoSizeColumn((short) p);
Parce que cela va dégrader les performances.
Cela m'a vraiment aidé, j'ai été l'exécution d'un simple 3000 sortie de la ligne de la prise de 10 minutes à 2 secondes (littéralement). Vous remarquerez que cette question comme votre code ralentit à l'écrire. Merci @sams
OriginalL'auteur sarath
J'essaie d'utiliser le streaming hssf ainsi introduit dans poi-beta3. Ce qui a aidé les problèmes de mémoire sur de grandes feuilles de calcul avec+ de 1000 colonnes.
OriginalL'auteur Matt Kim
J'ai fait un peu plus détaillée de profilage et il semble que le problème est en fait dans le code de l'extérieur de la PI. J'ai juste supposé que c'était le goulot d'étranglement, mais je crois que c'est incorrect.
C'était mon propre code. J'ai été à tort d'essayer de faire quelques très inefficace de l'analyse des champs de texte pour voir s'ils avaient des valeurs de date (pour quand les utilisateurs d'entrée de texte, des dates dans les cellules qui n'ont pas un format de date).
OriginalL'auteur Jeff Storey
Si vous utilisez Apache POI pour générer un grand fichier excel, veuillez prendre note de la feuille.autoSizeColumn((court) p); ligne, car cela aura un impact sur la performance.
http://stanicblog.blogspot.sg/2013/07/generate-large-excel-report-by-using.html
OriginalL'auteur stanicmail