我试图用几个表(大小未知)创建一个PDF。
在一定数量的表之后(在本示例中为18个),将引发以下异常:

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)


我正在使用iText 7的快照版本(3月24日起为7.0.3-SNAPSHOT)。

有什么解决方法,还是我做错了什么?

触发错误的示例代码:

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;
        }

    }
}

最佳答案

这确实是当前快照中的错误。解决方法是,如果您知道将不再有行,请不要调用startNewRow()

对于您的示例,可以通过以下方式应用解决方法:

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();
    }
}


传递一个参数,指示这是否将是createRow的最后一行。在您的示例中,呼叫为createRow(i == 9, cellElement);

10-04 15:35