Skip to main content
Skip table of contents

Repeating rows

Example that explains how to meet the very specific requirement explained in the following question: How to repeat the last 5 rows of a table on the next page?


headerrowrepeated

JAVA

JAVA
/*
    This file is part of the iText (R) project.
    Copyright (c) 1998-2023 Apryse Group NV
    Authors: Apryse Software.

    For more information, please contact iText Software at this address:
    sales@itextpdf.com
 */
package com.itextpdf.samples.sandbox.tables;

import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.properties.UnitValue;

import java.io.File;

public class HeaderRowRepeated {
    public static final String DEST = "./target/sandbox/tables/header_row_repeated.pdf";

    public static void main(String[] args) throws Exception {
        File file = new File(DEST);
        file.getParentFile().mkdirs();

        new HeaderRowRepeated().manipulatePdf(DEST);
    }

    protected void manipulatePdf(String dest) throws Exception {
        PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
        Document doc = new Document(pdfDoc);

        // table with 2 columns:
        Table table = new Table(UnitValue.createPercentArray(2)).useAllAvailableWidth();

        // header row:
        table.addHeaderCell("Key");
        table.addHeaderCell("Value");
        table.setSkipFirstHeader(true);

        // many data rows:
        for (int i = 1; i < 51; i++) {
            table.addCell("key: " + i);
            table.addCell("value: " + i);
        }

        doc.add(table);

        doc.close();
    }
}

C#

C#
using System;
using System.IO;
using iText.Kernel.Pdf;
using iText.Layout;
using iText.Layout.Element;
using iText.Layout.Properties;

namespace iText.Samples.Sandbox.Tables
{
    public class HeaderRowRepeated
    {
        public static readonly string DEST = "results/sandbox/tables/header_row_repeated.pdf";

        public static void Main(String[] args)
        {
            FileInfo file = new FileInfo(DEST);
            file.Directory.Create();

            new HeaderRowRepeated().ManipulatePdf(DEST);
        }

        private void ManipulatePdf(string dest)
        {
            PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
            Document doc = new Document(pdfDoc);

            // table with 2 columns:
            Table table = new Table(UnitValue.CreatePercentArray(2)).UseAllAvailableWidth();

            // header row:
            table.AddHeaderCell("Key");
            table.AddHeaderCell("Value");
            table.SetSkipFirstHeader(true);

            // many data rows:
            for (int i = 1; i < 51; i++)
            {
                table.AddCell("key: " + i);
                table.AddCell("value: " + i);
            }

            doc.Add(table);

            doc.Close();
        }
    }
}


repeatlastrows

JAVA

JAVA
/*
    This file is part of the iText (R) project.
    Copyright (c) 1998-2023 Apryse Group NV
    Authors: Apryse Software.

    For more information, please contact iText Software at this address:
    sales@itextpdf.com
 */
package com.itextpdf.samples.sandbox.tables;

import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Cell;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.properties.UnitValue;
import com.itextpdf.layout.renderer.IRenderer;
import com.itextpdf.layout.renderer.TableRenderer;

import java.io.File;

public class RepeatLastRows {
    public static final String DEST = "./target/sandbox/tables/repeat_last_rows.pdf";

    public static void main(String[] args) throws Exception {
        File file = new File(DEST);
        file.getParentFile().mkdirs();

        new RepeatLastRows().manipulatePdf(DEST);
    }

    protected void manipulatePdf(String dest) throws Exception {
        PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
        Document doc = new Document(pdfDoc);

        Table table = new Table(UnitValue.createPercentArray(1)).useAllAvailableWidth();
        table.setNextRenderer(new RepeatTableRenderer(table, new Table.RowRange(0, 113)));

        for (int i = 1; i < 115; i++) {
            table.addCell(new Cell().add(new Paragraph("row " + i)));
        }

        doc.add(table);

        doc.close();
    }


    private static class RepeatTableRenderer extends TableRenderer {
        public RepeatTableRenderer(Table modelElement, Table.RowRange rowRange) {
            super(modelElement, rowRange);
        }

        protected RepeatTableRenderer(Table modelElement) {
            super(modelElement);
        }

        // If a renderer overflows on the next area, iText uses #getNextRenderer() method to create a new renderer for the overflow part.
        // If #getNextRenderer() isn't overridden, the default method will be used and thus the default rather than the custom
        // renderer will be created
        @Override
        public IRenderer getNextRenderer() {
            return new RepeatTableRenderer((Table) modelElement);
        }

        @Override
        protected TableRenderer[] split(int row) {
            RepeatTableRenderer splitRenderer = (RepeatTableRenderer) createSplitRenderer(
                    new Table.RowRange(rowRange.getStartRow(), rowRange.getStartRow() + row));
            splitRenderer.rows = rows.subList(0, row);

            RepeatTableRenderer overflowRenderer;

            if (rows.size() - row > 5) {
                overflowRenderer = (RepeatTableRenderer) createOverflowRenderer(
                        new Table.RowRange(rowRange.getStartRow() + row, rowRange.getFinishRow()));
                overflowRenderer.rows = rows.subList(row, rows.size());
            } else {
                overflowRenderer = (RepeatTableRenderer) createOverflowRenderer(
                        new Table.RowRange(rowRange.getFinishRow() - 5, rowRange.getFinishRow()));
                overflowRenderer.rows = rows.subList(rows.size() - 5, rows.size());
            }

            splitRenderer.occupiedArea = occupiedArea;

            return new TableRenderer[] {splitRenderer, overflowRenderer};
        }
    }
}

C#

C#
using System;
using System.IO;
using System.Linq;
using iText.Kernel.Pdf;
using iText.Layout;
using iText.Layout.Element;
using iText.Layout.Properties;
using iText.Layout.Renderer;

namespace iText.Samples.Sandbox.Tables
{
    public class RepeatLastRows
    {
        public static readonly string DEST = "results/sandbox/tables/repeat_last_rows.pdf";

        public static void Main(String[] args)
        {
            FileInfo file = new FileInfo(DEST);
            file.Directory.Create();

            new RepeatLastRows().ManipulatePdf(DEST);
        }

        private void ManipulatePdf(String dest)
        {
            PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
            Document doc = new Document(pdfDoc);

            Table table = new Table(UnitValue.CreatePercentArray(1)).UseAllAvailableWidth();
            table.SetNextRenderer(new RepeatTableRenderer(table, new Table.RowRange(0, 113)));

            for (int i = 1; i < 115; i++)
            {
                table.AddCell(new Cell().Add(new Paragraph("row " + i)));
            }

            doc.Add(table);
            
            doc.Close();
        }

        private class RepeatTableRenderer : TableRenderer
        {
            public RepeatTableRenderer(Table modelElement, Table.RowRange rowRange)
                : base(modelElement, rowRange)
            {
            }

            protected RepeatTableRenderer(Table modelElement)
                : base(modelElement)
            {
            }            
            
            // If renderer overflows on the next area, iText uses getNextRender() method to create a renderer for the overflow part.
            // If getNextRenderer isn't overriden, the default method will be used and thus a default rather than custom
            // renderer will be created
            public override IRenderer GetNextRenderer()
            {
                return new RepeatTableRenderer((Table) modelElement);
            }

            protected override TableRenderer[] Split(int row)
            {
                RepeatTableRenderer splitRenderer = (RepeatTableRenderer) CreateSplitRenderer
                    (new Table.RowRange(rowRange.GetStartRow(), rowRange.GetStartRow() + row));
                splitRenderer.rows = rows.ToList().GetRange(0, row);

                RepeatTableRenderer overflowRenderer;

                if (rows.Count - row > 5)
                {
                    overflowRenderer = (RepeatTableRenderer) CreateOverflowRenderer(
                        new Table.RowRange(rowRange.GetStartRow() + row, rowRange.GetFinishRow()));
                    overflowRenderer.rows = rows.ToList().GetRange(row, rows.Count);
                }
                else
                {
                    overflowRenderer = (RepeatTableRenderer) CreateOverflowRenderer(
                        new Table.RowRange(rowRange.GetFinishRow() - 5, rowRange.GetFinishRow()));
                    overflowRenderer.rows = rows.ToList().GetRange(rows.Count - 5, rows.Count);
                }

                splitRenderer.occupiedArea = occupiedArea;

                return new TableRenderer[] {splitRenderer, overflowRenderer};
            }
        }
    }
}


repeatlastrows2

JAVA

JAVA
/*
    This file is part of the iText (R) project.
    Copyright (c) 1998-2023 Apryse Group NV
    Authors: Apryse Software.

    For more information, please contact iText Software at this address:
    sales@itextpdf.com
 */
package com.itextpdf.samples.sandbox.tables;

import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Cell;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.element.Table;

import com.itextpdf.layout.properties.UnitValue;
import com.itextpdf.layout.renderer.IRenderer;
import com.itextpdf.layout.renderer.TableRenderer;

import java.io.File;

public class RepeatLastRows2 {
    public static final String DEST = "./target/sandbox/tables/repeat_last_rows2.pdf";

    public static void main(String[] args) throws Exception {
        File file = new File(DEST);
        file.getParentFile().mkdirs();

        new RepeatLastRows2().manipulatePdf(DEST);
    }

    protected void manipulatePdf(String dest) throws Exception {
        PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
        Document doc = new Document(pdfDoc);

        Table table = new Table(UnitValue.createPercentArray(1)).useAllAvailableWidth();
        table.setNextRenderer(new RepeatTableRenderer(table, new Table.RowRange(0, 100)));

        for (int i = 1; i < 100; i++) {
            table.addCell(new Cell().add(new Paragraph("row " + i)));
        }

        doc.add(table);

        doc.close();
    }


    private static class RepeatTableRenderer extends TableRenderer {
        public RepeatTableRenderer(Table modelElement, Table.RowRange rowRange) {
            super(modelElement, rowRange);
        }

        protected RepeatTableRenderer(Table modelElement) {
            super(modelElement);
        }

        // If a renderer overflows on the next area, iText uses #getNextRenderer() method to create a new renderer for the overflow part.
        // If #getNextRenderer() isn't overridden, the default method will be used and thus the default rather than the custom
        // renderer will be created
        @Override
        public IRenderer getNextRenderer() {
            return new RepeatTableRenderer((Table) modelElement);
        }

        @Override
        protected TableRenderer[] split(int row) {
            RepeatTableRenderer splitRenderer = (RepeatTableRenderer) createSplitRenderer(
                    new Table.RowRange(rowRange.getStartRow(), rowRange.getStartRow() + row));
            splitRenderer.rows = rows.subList(0, row);

            RepeatTableRenderer overflowRenderer;

            if (row > 5) {
                overflowRenderer = (RepeatTableRenderer) createOverflowRenderer(
                        new Table.RowRange(rowRange.getStartRow() - 5 + row, rowRange.getFinishRow()));
                overflowRenderer.rows = rows.subList(row - 5, rows.size());
            } else {
                overflowRenderer = (RepeatTableRenderer) createOverflowRenderer(
                        new Table.RowRange(rowRange.getStartRow() + row, rowRange.getFinishRow()));
                overflowRenderer.rows = rows.subList(row, rows.size());
            }

            splitRenderer.occupiedArea = occupiedArea;

            return new TableRenderer[] {splitRenderer, overflowRenderer};
        }
    }
}

C#

C#
using System;
using System.IO;
using System.Linq;
using iText.Kernel.Pdf;
using iText.Layout;
using iText.Layout.Element;
using iText.Layout.Properties;
using iText.Layout.Renderer;

namespace iText.Samples.Sandbox.Tables
{
    public class RepeatLastRows2
    {
        public static readonly string DEST = "results/sandbox/tables/repeat_last_rows2.pdf";

        public static void Main(String[] args)
        {
            FileInfo file = new FileInfo(DEST);
            file.Directory.Create();

            new RepeatLastRows2().ManipulatePdf(DEST);
        }

        private void ManipulatePdf(String dest)
        {
            PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
            Document doc = new Document(pdfDoc);

            Table table = new Table(UnitValue.CreatePercentArray(1)).UseAllAvailableWidth();
            table.SetNextRenderer(new RepeatTableRenderer(table, new Table.RowRange(0, 100)));

            for (int i = 1; i < 100; i++)
            {
                table.AddCell(new Cell().Add(new Paragraph("row " + i)));
            }

            doc.Add(table);

            doc.Close();
        }

        private class RepeatTableRenderer : TableRenderer
        {
            public RepeatTableRenderer(Table modelElement, Table.RowRange rowRange)
                : base(modelElement, rowRange)
            {
            }

            protected RepeatTableRenderer(Table modelElement)
                : base(modelElement)
            {
            }            
            
            // If renderer overflows on the next area, iText uses getNextRender() method to create a renderer for the overflow part.
            // If getNextRenderer isn't overriden, the default method will be used and thus a default rather than custom
            // renderer will be created
            public override IRenderer GetNextRenderer()
            {
                return new RepeatTableRenderer((Table) modelElement);
            }

            protected override TableRenderer[] Split(int row)
            {
                RepeatTableRenderer splitRenderer = (RepeatTableRenderer) CreateSplitRenderer(
                    new Table.RowRange(rowRange.GetStartRow(), rowRange.GetStartRow() + row));
                splitRenderer.rows = rows.ToList().GetRange(0, row);

                RepeatTableRenderer overflowRenderer;
                
                if (row > 5)
                {
                    overflowRenderer = (RepeatTableRenderer) CreateOverflowRenderer(
                        new Table.RowRange(rowRange.GetStartRow() - 5 + row, rowRange.GetFinishRow()));
                    overflowRenderer.rows = rows.ToList().GetRange(row - 5, rows.Count);
                }
                else
                {
                    overflowRenderer = (RepeatTableRenderer) CreateOverflowRenderer(
                        new Table.RowRange(rowRange.GetStartRow() + row, rowRange.GetFinishRow()));
                    overflowRenderer.rows = rows.ToList().GetRange(row, rows.Count);
                }

                splitRenderer.occupiedArea = occupiedArea;

                return new TableRenderer[] {splitRenderer, overflowRenderer};
            }
        }
    }
}
JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.