7 votes

Comment réparer la fonction SpreadSheetAddRows qui plante lors de l'ajout d'une requête importante?

EDIT3: Grâce à l'aide de @Leigh, j'ai réduit le problème aux colonnes de date dans la requête. En utilisant le jeu de code d'origine et POI, la page plante lorsque SpreadSheetAddRows() tente d'ajouter une requête très volumineuse contenant des cellules de type date. J'ai fait un rapport de bug ici: https://bugbase.adobe.com/index.cfm?event=bug&id=3432184.


J'ai une requête que j'ajoute à un objet feuille de calcul qui semble générer une erreur lorsque la requête contient un nombre considérablement élevé de lignes (18583 dans cet exemple). L'erreur exacte est la suivante:

java.lang.ArrayIndexOutOfBoundsException: -32735
at java.util.ArrayList.get(ArrayList.java:324)
at org.apache.poi.hssf.model.WorkbookRecordList.get(WorkbookRecordList.j ava:50)
at org.apache.poi.hssf.model.Workbook.getExFormatAt(Workbook.java:787)
at org.apache.poi.hssf.usermodel.HSSFCell.getCellStyle(HSSFCell.java:901 )
at org.apache.poi.hssf.usermodel.HSSFSheet.autoSizeColumn(HSSFSheet.java :1727)
at coldfusion.excel.Excel.autoResize(Excel.java:1246)
at coldfusion.excel.Excel.autoResize(Excel.java:1240)
at coldfusion.excel.Excel.addRows(Excel.java:1214)
at coldfusion.runtime.CFPage.SpreadSheetAddRows(CFPage.java:7089) at coldfusion.runtime.CFPage.SpreadSheetAddRows(CFPage.java:7076)

Voici le code pertinent:


EDIT: J'ai déjà utilisé cfspreadsheet avec succès, mais cela ne produit pas de feuille de calcul avec des en-têtes (et a également l'inconvénient de devoir créer un fichier temporaire pour le servir.)


EDIT2: Suite à la suggestion de @Leigh, j'ai mis à jour le POI dans mon dossier CF9/lib. Les erreurs sont maintenant les suivantes:

Donne le message suivant: org.apache.poi.hssf.util.HSSFColor.getIndexHash()Ljava/util/Hashtable;

Code d'erreur:

java.lang.NoSuchMethodError:
org.apache.poi.hssf.util.HSSFColor.getIndexHash()Ljava/util/Hashtable;
at coldfusion.excel.Excel.getHSSFColor(Excel.java:2094)
at coldfusion.excel.Excel.findFont(Excel.java:2237)
at coldfusion.excel.Excel.getCellStyle(Excel.java:2318)
at coldfusion.excel.Excel.formatRow(Excel.java:2948)
at coldfusion.excel.Excel.formatRow(Excel.java:2963)
at coldfusion.excel.Excel.formatRow(Excel.java:2981)
at coldfusion.runtime.CFPage.SpreadSheetFormatRow(CFPage.java:7268)

En commentant cette ligne, cela plante à nouveau sur:

Code d'erreur:

java.lang.IllegalStateException: Le nombre maximum de styles de cellules a été dépassé. Vous pouvez définir jusqu'à 4000 styles dans un classeur .xls 
at org.apache.poi.hssf.usermodel.HSSFWorkbook.createCellStyle(HSSFWorkbook.java:1120) 
at org.apache.poi.hssf.usermodel.HSSFWorkbook.createCellStyle(HSSFWorkbook.java:73) 
at coldfusion.excel.Excel.addRow(Excel.java:1323)
at coldfusion.excel.Excel.addRows(Excel.java:1203) 
at coldfusion.runtime.CFPage.SpreadSheetAddRows(CFPage.java:7089) 
at coldfusion.runtime.CFPage.SpreadSheetAddRows(CFPage.java:7076)

3voto

Leigh Points 16126

Je soupçonne que cela n'a rien à voir avec la version de CF ou de JRE. Du moins pas directement. Cela ressemble à un bug dans POI.

Si vous regardez l'exception, elle montre clairement que le problème se produit lorsque CF invoque une méthode POI qui tente de redimensionner automatiquement les colonnes (après avoir ajouté les données de la requête). Une rapide recherche a révélé plusieurs rapports d'erreurs similaires ArrayIndexOutOfBoundsException avec HSSFSheet.autoSizeColumn comme celui-ci (qui mentionne juste ColdFusion) :

Si vous tentez d'utiliser org.apache.poi.hssf.usermodel.HSSFSheet et la méthode autosizecolumn(int) sur une colonne après avoir défini plus de 32767 cellules alors ArrayOutOfBoundsException est déclenchée.

D'après le rapport de bug, le problème existait dans la version 3.5, qui est la même (version majeure) incluse dans ColdFusion 9. Un des développeurs de POI suggère que le problème a été corrigé dans les versions ultérieures. Vous pourriez donc essayer de mettre à jour le fichier jar POI. À part cela, si vous pouvez mettre en place un cas de test reproduisant le problème, vous pouvez envisager de créer un rapport de bug.

J'utilisais auparavant cfspreadsheet avec succès, mais cela ne produit pas une feuille de calcul avec des en-têtes (et cela a également l'inconvénient de devoir créer un fichier temporaire pour le servir.)

cfspreadsheet ne tente probablement pas de redimensionner automatiquement les colonnes comme le fait spreadsheetAddRows, donc aucune erreur ne se produit. Donc la solution évidente (mais pas géniale) est d'éviter les fonctions qui tentent de redimensionner les largeurs des colonnes.

1voto

Miguel-F Points 6540

Si vous reculez un peu du code et examinez simplement l'erreur lancée, vous obtenez ceci à partir de la documentation Java et voici une autre référence

Lancé pour indiquer qu'un tableau a été accédé avec un index illégal. L'index est soit négatif, soit supérieur ou égal à la taille du tableau.

L'erreur vous montre également la valeur d'index illégale qui a été tentée: -32735

Maintenant, votre problème est que vous ne spécifiez pas les valeurs d'index dans votre code en soi car vous utilisez une fonction ColdFusion. Cette fonction (SpreadsheetAddRows) essaie de convertir le résultat de votre requête en un tableau, puis d'ajouter chacune de ces valeurs dans des lignes d'une feuille de calcul Excel. Elle utilise le runtime Java sous-jacent pour effectuer ces tâches et c'est ce qui lance une erreur. Je crains donc que vous soyez un peu bloqué avec cette limitation que vous rencontrez. Vous pourriez essayer de mettre à jour la version de JRE sur laquelle votre installation ColdFusion fonctionne pour voir si le problème a été résolu dans une version plus récente. Je crois que ColdFusion 9 est livré avec Java 1.6.0_14 voir ici. Vous devriez de toute façon exécuter au moins la version 1.6.0_24 en raison d'un correctif de vulnérabilité DOS. Il semble qu'ils en soient à 1.6.0_38 maintenant mais vous devrez vérifier auprès du support Adobe pour cela.

Si la mise à niveau de JRE ne résout pas le problème, je pense que vous devrez modifier votre code ColdFusion pour éviter cet problème. Vous avez déclaré avoir réussi en utilisant la balise CFSpreadSheet. Ou peut-être pouvez-vous jouer avec différentes façons de passer les résultats de votre requête à la fonction SpreadsheetAddRows. (Bien que je suppose que vous ayez déjà épuisé cette voie.) Peut-être en bouclant sur la requête et en construisant votre propre tableau ou en bouclant sur la requête et en ajoutant les lignes une par une. Je réalise que cela peut ne pas être optimal mais après avoir essayé quelques façons différentes, l'une devrait être la bonne.

Je vais également ajouter la balise ColdFusion (sans le numéro de version) à votre publication pour attirer plus d'attention.

MISE À JOUR

Je voulais juste faire un suivi sur la version de Java supportée pour ColdFusion 9. J'ai trouvé cet article de blog de Charlie Arehart qui discute de la position d'Adobe sur la mise à niveau de Java pour les serveurs ColdFusion. Cela renvoie au message officiel d'Adobe ici qui indique que toute mise à jour mineure sera prise en charge. Donc pour ColdFusion 9 "toutes les versions futures de JDK 1.6.0_x sont supportées".

1voto

dellasavia Points 70

(extraits de http://poi.apache.org/spreadsheet/quick-guide.html)

Notez que le nombre maximum de polices uniques dans un classeur est limité à 32767 (le short positif maximum). Vous devriez réutiliser les polices dans vos applications au lieu de créer une police pour chaque cellule. Exemples:

Faux:

for (int i = 0; i < 10000; i++) {
    Row row = sheet.createRow(i);
    Cell cell = row.createCell((short) 0);

    CellStyle style = workbook.createCellStyle();
    Font font = workbook.createFont();
    font.setBoldweight(Font.BOLDWEIGHT_BOLD);
    style.setFont(font);
    cell.setCellStyle(style);
}

Correct:

CellStyle style = workbook.createCellStyle();
Font font = workbook.createFont();
font.setBoldweight(Font.BOLDWEIGHT_BOLD);
style.setFont(font);
for (int i = 0; i < 10000; i++) {
    Row row = sheet.createRow(i);
    Cell cell = row.createCell((short) 0);
    cell.setCellStyle(style);
}

De toute façon, vous pouvez également essayer ceci:

org.apache.poi.hssf.usermodel.HSSFOptimiser.optimiseCellStyles(HSSFWorkbook)

0voto

BGM Points 2427

Dans mon expérience avec les tableaux, lorsque vous avez une exception OutOfBounds, c'est généralement parce que j'ai "débordé" le tableau - c'est-à-dire, j'ai bouclé une fois de plus que le nombre total d'éléments dans l'indice. Cela arrive généralement parce que j'oublie que lorsque le tableau commence à 0, je ne dois boucler que jusqu'à la longueur du tableau - 1.

Assurez-vous de ne pas boucler au-delà de la longueur de votre tableau.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X