2017-03-27 6 views
0

J'ai essayé de créer un PDF avec plusieurs tables (de taille inconnue). Après un certain nombre de tables (dans cet exemple: 18), l'exception suivante est levée:IndexOutOfBoundsException lors de l'ajout de tables à un fichier itext 7 pdf

Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 20, Size: 20 
    at java.util.ArrayList$SubList.rangeCheck(Unknown Source) 
    at java.util.ArrayList$SubList.get(Unknown Source) 
    at com.itextpdf.layout.renderer.CollapsedTableBorders.collapseAllBordersAndEmptyRows(CollapsedTableBorders.java:77) 
    at com.itextpdf.layout.renderer.CollapsedTableBorders.updateBordersOnNewPage(CollapsedTableBorders.java:617) 
    at com.itextpdf.layout.renderer.TableRenderer.layout(TableRenderer.java:248) 
    at com.itextpdf.layout.renderer.RootRenderer.addChild(RootRenderer.java:111) 
    at com.itextpdf.layout.RootElement.add(RootElement.java:108) 
    at com.itextpdf.layout.Document.add(Document.java:143) 
    at com.test.MinimalITextTest.createPdf(MinimalITextTest.java:83) 
    at com.test.MinimalITextTest.main(MinimalITextTest.java:66) 

J'utilise la version instantanée des iText 7 (7.0.3-SNAPSHOT du 24 Mars).

Y at-il une solution de contournement ou suis-je juste faire quelque chose de mal?

Exemple de code qui déclenche l'erreur:

package com.test; 

import java.io.FileOutputStream; 
import java.io.IOException; 
import java.util.ArrayList; 
import java.util.List; 

import com.itextpdf.kernel.color.Color; 
import com.itextpdf.kernel.pdf.PdfDocument; 
import com.itextpdf.kernel.pdf.PdfWriter; 
import com.itextpdf.layout.Document; 
import com.itextpdf.layout.border.SolidBorder; 
import com.itextpdf.layout.element.Cell; 
import com.itextpdf.layout.element.Paragraph; 
import com.itextpdf.layout.element.Table; 
import com.itextpdf.layout.property.HorizontalAlignment; 
import com.itextpdf.layout.property.TextAlignment; 
import com.itextpdf.layout.property.UnitValue; 

public class MinimalITextTest { 

    private static final int numberOfColumns=8; 
    private static final UnitValue[] columnWeight; 
    private static final int NUMBER_OF_TABLES = 18; //Does work with 17 

    static { 
     float[] percentArray = new float[numberOfColumns]; 
     for(int i=0; i<percentArray.length;i++) 
     { 
      percentArray[i] = 100.0f/numberOfColumns; 
     } 
     columnWeight=UnitValue.createPercentArray(percentArray); 
    } 


    private final List<Table> tables=new ArrayList<>(); 
    private Table currentTable; 


    public MinimalITextTest() 
    { 
     currentTable=new Table(columnWeight) 
      .setWidthPercent(100) 
      .setTextAlignment(TextAlignment.CENTER) 
      .setHorizontalAlignment(HorizontalAlignment.CENTER); 
     tables.add(currentTable); 
    } 

    public static void main(String[] args) throws IOException 
    { 
     final char[] charArray="Minimal Example".toCharArray(); 
     final MinimalITextTest test = new MinimalITextTest(); 
     for(int k=0;k<NUMBER_OF_TABLES;k++) 
     { 
      for(int i=0;i<10;i++) 
      { 
       CellElement[] cellElement=new CellElement[charArray.length]; 
       for(int j=0;j<charArray.length;j++) 
       { 
        cellElement[j] = new CellElement(String.valueOf(charArray[j])); 
       } 
       test.createRow(cellElement); 
      } 
      test.createNewTable(); 
     } 
     test.createPdf("Minimal_test.pdf"); 
    } 

    private void createNewTable() { 
     currentTable=new Table(columnWeight) 
      .setWidthPercent(100) 
      .setTextAlignment(TextAlignment.CENTER) 
      .setHorizontalAlignment(HorizontalAlignment.CENTER); 
     tables.add(currentTable); 
    } 

    public void createPdf(String destinationFile) throws IOException { 
     PdfWriter pw = new PdfWriter(new FileOutputStream(destinationFile)); 

     Document document = new Document(new PdfDocument(pw)); 
     for(Table t : tables) 
     { 
      document.add(t); 
     } 
     document.close(); 
    } 

    public void createRow(CellElement... cells) 
    { 
     boolean addedACell=false; 
     for(CellElement currentCell : cells) 
     { 
      if(currentCell==null) 
      { 
       continue; 
      } 
      addedACell = true; 
      Cell cell = new Cell(); 
      cell.add(new Paragraph(currentCell.getText())) 
       .setBorder(new SolidBorder(Color.BLACK, 0.5f)) 
       .setBackgroundColor(currentCell.getBackgroundColor()); 
      currentTable.addCell(cell); 
     } 
     if(addedACell) 
     { 
      currentTable.startNewRow(); 
     } 
    } 

    public static class CellElement 
    { 
     private final String text; 
     private final Color color; 

     public CellElement() 
     { 
      this.text = ""; 
      this.color = Color.WHITE; 
     } 


     public CellElement(String text) 
     { 
      this.text = text; 
      this.color = Color.WHITE; 
     } 

     public CellElement(String text, Color color) 
     { 
      this.text = text; 
      this.color = color; 
     } 

     public String getText() { 
      return text; 
     } 

     public Color getBackgroundColor() { 
      return color; 
     } 

    } 
} 
+0

Bienvenue sur SO. TL; DR; S'il vous plaît voir [MCVE] – c0der

+1

Veuillez utiliser une version stable (7.0.2), sauf demande explicite contraire par le support iText. –

Répondre

1

Ceci est en effet un bug dans l'instantané actuel. Pour contourner ce problème, n'appelez pas startNewRow() si vous savez qu'il n'y aura plus de lignes.

Pour votre exemple, la solution pourrait être appliquée de la manière suivante:

public void createRow(boolean lastRow, CellElement... cells) 
{ 
    for(CellElement currentCell : cells) 
    { 
     if(currentCell==null) 
     { 
      continue; 
     } 
     Cell cell = new Cell(); 
     cell.add(new Paragraph(currentCell.getText())) 
       .setBorder(new SolidBorder(Color.BLACK, 0.5f)) 
       .setBackgroundColor(currentCell.getBackgroundColor()); 
     currentTable.addCell(cell); 
    } 
    if (!lastRow) { 
     currentTable.startNewRow(); 
    } 
} 

passer un paramètre indiquant si ce sera la dernière ligne à createRow. Dans votre exemple, l'appel serait createRow(i == 9, cellElement);.

+0

Merci beaucoup pour votre réponse rapide. Juste pour le compte rendu, j'utilisais l'instantané, à cause de ce bogue: http://stackoverflow.com/questions/42627711/errors-with-itext7 –

0

Salut et merci pour la question.

Le problème a été résolu. Vous pouvez trouver des changements dans notre version de l'instantané 7.0.3-SNAPSHOT.