Skip to main content
Skip table of contents

Nested tables

These examples were written in answer to questions such as:


nestedtableproblem

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.colors.ColorConstants;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.borders.SolidBorder;
import com.itextpdf.layout.element.Cell;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.properties.HorizontalAlignment;
import com.itextpdf.layout.properties.UnitValue;

import java.io.File;

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

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

        new NestedTableProblem().manipulatePdf(DEST);
    }

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

        doc.setMargins(30, 21, 35, 21);

        // inner table
        Table innerTable = new Table(UnitValue.createPercentArray(1));
        innerTable.setWidth(UnitValue.createPercentValue(80));
        innerTable.setHorizontalAlignment(HorizontalAlignment.LEFT);
        innerTable.addCell(new Cell().setBorder(new SolidBorder(ColorConstants.RED, 1))
                .add(new Paragraph("Goodbye World")));

        // outer table
        Table outerTable = new Table(UnitValue.createPercentArray(1)).useAllAvailableWidth();
        outerTable.setHorizontalAlignment(HorizontalAlignment.LEFT);

        Cell cell = new Cell();
        cell.setBorder(new SolidBorder(ColorConstants.BLACK, 1));
        cell.add(new Paragraph("Hello World"));
        cell.add(innerTable);
        cell.add(new Paragraph("Hello World"));

        outerTable.addCell(cell);
        doc.add(outerTable);

        doc.close();
    }
}

C#

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

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

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

            new NestedTableProblem().ManipulatePdf(DEST);
        }

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

            doc.SetMargins(30, 21, 35, 21);

            // inner table
            Table innerTable = new Table(UnitValue.CreatePercentArray(1));
            innerTable.SetWidth(UnitValue.CreatePercentValue(80));
            innerTable.SetHorizontalAlignment(HorizontalAlignment.LEFT);
            innerTable.AddCell(new Cell().SetBorder(new SolidBorder(ColorConstants.RED, 1))
                .Add(new Paragraph("Goodbye World")));

            // outer table
            Table outerTable = new Table(UnitValue.CreatePercentArray(1)).UseAllAvailableWidth();
            outerTable.SetHorizontalAlignment(HorizontalAlignment.LEFT);

            Cell cell = new Cell();
            cell.SetBorder(new SolidBorder(ColorConstants.BLACK, 1));
            cell.Add(new Paragraph("Hello World"));
            cell.Add(innerTable);
            cell.Add(new Paragraph("Hello World"));

            outerTable.AddCell(cell);
            doc.Add(outerTable);

            doc.Close();
        }
    }
}


nestedtableroundedborder

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.borders.Border;
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.CellRenderer;
import com.itextpdf.layout.renderer.DrawContext;
import com.itextpdf.layout.renderer.IRenderer;

import java.io.File;

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

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

        new NestedTableRoundedBorder().manipulatePdf(DEST);
    }

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

        // outer table
        Table outertable = new Table(UnitValue.createPercentArray(1)).useAllAvailableWidth();

        // inner table 1
        Table innertable = new Table(UnitValue.createPercentArray(new float[]{8, 12, 1, 4, 12})).useAllAvailableWidth();

        // first row
        // column 1
        Cell cell = new Cell().add(new Paragraph("Record Ref:"));
        cell.setBorder(Border.NO_BORDER);
        innertable.addCell(cell);

        // column 2
        cell = new Cell().add(new Paragraph("GN Staff"));
        cell.setPaddingLeft(2);
        innertable.addCell(cell);

        // spacing
        cell = new Cell();
        cell.setBorder(Border.NO_BORDER);
        innertable.addCell(cell);

        // column 4
        cell = new Cell().add(new Paragraph("Date: "));
        cell.setBorder(Border.NO_BORDER);
        innertable.addCell(cell);

        // column 5
        cell = new Cell().add(new Paragraph("30/4/2015"));
        cell.setPaddingLeft(2);
        innertable.addCell(cell);

        // spacing
        cell = new Cell(1, 5);
        cell.setHeight(3);
        cell.setBorder(Border.NO_BORDER);
        innertable.addCell(cell);

        // second row
        // column 1
        cell = new Cell().add(new Paragraph("Hospital:"));
        cell.setBorder(Border.NO_BORDER);
        innertable.addCell(cell);

        // column 2
        cell = new Cell().add(new Paragraph("Derby Royal"));
        cell.setPaddingLeft(2);
        innertable.addCell(cell);

        // spacing
        cell = new Cell();
        cell.setBorder(Border.NO_BORDER);
        innertable.addCell(cell);

        // column 4
        cell = new Cell().add(new Paragraph("Ward: "));
        cell.setBorder(Border.NO_BORDER);
        cell.setPaddingLeft(5);
        innertable.addCell(cell);

        // column 5
        cell = new Cell().add(new Paragraph("21"));
        cell.setPaddingLeft(2);
        innertable.addCell(cell);

        // spacing
        cell = new Cell(1, 5);
        cell.setHeight(3);
        cell.setBorder(Border.NO_BORDER);
        innertable.addCell(cell);

        // first nested table
        cell = new Cell().add(innertable);
        cell.setNextRenderer(new RoundedBorderCellRenderer(cell));
        cell.setBorder(Border.NO_BORDER);
        cell.setPadding(8);
        outertable.addCell(cell);

        // inner table 2
        innertable = new Table(UnitValue.createPercentArray(new float[]{3, 17, 1, 16}));
        innertable.setWidth(UnitValue.createPercentValue(100));

        // first row
        // column 1
        cell = new Cell();
        cell.setBorder(Border.NO_BORDER);
        innertable.addCell(cell);

        // column 2
        cell = new Cell().add(new Paragraph("Name"));
        cell.setBorder(Border.NO_BORDER);
        innertable.addCell(cell);

        // column 3
        cell = new Cell();
        cell.setBorder(Border.NO_BORDER);
        innertable.addCell(cell);

        // column 4
        cell = new Cell().add(new Paragraph("Signature: "));
        cell.setBorder(Border.NO_BORDER);
        innertable.addCell(cell);

        // spacing
        cell = new Cell(1, 4);
        cell.setHeight(3);
        cell.setBorder(Border.NO_BORDER);
        innertable.addCell(cell);

        // subsequent rows
        for (int i = 1; i < 4; i++) {

            // column 1
            cell = new Cell().add(new Paragraph(String.format("%s:", i)));
            cell.setBorder(Border.NO_BORDER);
            innertable.addCell(cell);

            // column 2
            cell = new Cell();
            innertable.addCell(cell);

            // column 3
            cell = new Cell();
            cell.setBorder(Border.NO_BORDER);
            innertable.addCell(cell);

            // column 4
            cell = new Cell();
            innertable.addCell(cell);

            // spacing
            cell = new Cell(1, 4);
            cell.setHeight(3);
            cell.setBorder(Border.NO_BORDER);
            innertable.addCell(cell);
        }

        // second nested table
        cell = new Cell().add(innertable);
        cell.setNextRenderer(new RoundedBorderCellRenderer(cell));
        cell.setBorder(Border.NO_BORDER);
        cell.setPaddingLeft(8);
        cell.setPaddingTop(8);
        cell.setPaddingRight(8);
        cell.setPaddingBottom(8);
        outertable.addCell(cell);

        // add the table
        doc.add(outertable);

        doc.close();
    }


    private static class RoundedBorderCellRenderer extends CellRenderer {
        public RoundedBorderCellRenderer(Cell 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 RoundedBorderCellRenderer((Cell) modelElement);
        }

        @Override
        public void draw(DrawContext drawContext) {
            drawContext.getCanvas().roundRectangle(getOccupiedAreaBBox().getX() + 1.5f, getOccupiedAreaBBox().getY() + 1.5f,
                    getOccupiedAreaBBox().getWidth() - 3, getOccupiedAreaBBox().getHeight() - 3, 4);
            drawContext.getCanvas().stroke();
            super.draw(drawContext);
        }
    }
}

C#

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

namespace iText.Samples.Sandbox.Tables
{
    public class NestedTableRoundedBorder
    {
        public static readonly String DEST = "results/sandbox/tables/nested_table_rounded_border.pdf";

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

            new NestedTableRoundedBorder().ManipulatePdf(DEST);
        }

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

            // outer table
            Table outerTable = new Table(UnitValue.CreatePercentArray(1)).UseAllAvailableWidth();

            // inner table 1
            Table innerTable = new Table(UnitValue.CreatePercentArray(new float[] {8, 12, 1, 4, 12}))
                .UseAllAvailableWidth();

            // first row
            // column 1
            Cell cell = new Cell().Add(new Paragraph("Record Ref:"));
            cell.SetBorder(Border.NO_BORDER);
            innerTable.AddCell(cell);

            // column 2
            cell = new Cell().Add(new Paragraph("GN Staff"));
            cell.SetPaddingLeft(2);
            innerTable.AddCell(cell);

            // spacing
            cell = new Cell();
            cell.SetBorder(Border.NO_BORDER);
            innerTable.AddCell(cell);

            // column 4
            cell = new Cell().Add(new Paragraph("Date: "));
            cell.SetBorder(Border.NO_BORDER);
            innerTable.AddCell(cell);

            // column 5
            cell = new Cell().Add(new Paragraph("30/4/2015"));
            cell.SetPaddingLeft(2);
            innerTable.AddCell(cell);

            // spacing
            cell = new Cell(1, 5);
            cell.SetHeight(3);
            cell.SetBorder(Border.NO_BORDER);
            innerTable.AddCell(cell);

            // second row
            // column 1
            cell = new Cell().Add(new Paragraph("Hospital:"));
            cell.SetBorder(Border.NO_BORDER);
            innerTable.AddCell(cell);

            // column 2
            cell = new Cell().Add(new Paragraph("Derby Royal"));
            cell.SetPaddingLeft(2);
            innerTable.AddCell(cell);

            // spacing
            cell = new Cell();
            cell.SetBorder(Border.NO_BORDER);
            innerTable.AddCell(cell);

            // column 4
            cell = new Cell().Add(new Paragraph("Ward: "));
            cell.SetBorder(Border.NO_BORDER);
            cell.SetPaddingLeft(5);
            innerTable.AddCell(cell);

            // column 5
            cell = new Cell().Add(new Paragraph("21"));
            cell.SetPaddingLeft(2);
            innerTable.AddCell(cell);

            // spacing
            cell = new Cell(1, 5);
            cell.SetHeight(3);
            cell.SetBorder(Border.NO_BORDER);
            innerTable.AddCell(cell);

            // first nested table
            cell = new Cell().Add(innerTable);
            cell.SetNextRenderer(new RoundedBorderCellRenderer(cell));
            cell.SetBorder(Border.NO_BORDER);
            cell.SetPadding(8);
            outerTable.AddCell(cell);

            // inner table 2
            innerTable = new Table(UnitValue.CreatePercentArray(new float[] {3, 17, 1, 16}));
            innerTable.SetWidth(UnitValue.CreatePercentValue(100));

            // first row
            // column 1
            cell = new Cell();
            cell.SetBorder(Border.NO_BORDER);
            innerTable.AddCell(cell);

            // column 2
            cell = new Cell().Add(new Paragraph("Name"));
            cell.SetBorder(Border.NO_BORDER);
            innerTable.AddCell(cell);

            // column 3
            cell = new Cell();
            cell.SetBorder(Border.NO_BORDER);
            innerTable.AddCell(cell);

            // column 4
            cell = new Cell().Add(new Paragraph("Signature: "));
            cell.SetBorder(Border.NO_BORDER);
            innerTable.AddCell(cell);

            // spacing
            cell = new Cell(1, 4);
            cell.SetHeight(3);
            cell.SetBorder(Border.NO_BORDER);
            innerTable.AddCell(cell);

            // subsequent rows
            for (int i = 1; i < 4; i++)
            {
                // column 1
                cell = new Cell().Add(new Paragraph(string.Format("{0}:", i)));
                cell.SetBorder(Border.NO_BORDER);
                innerTable.AddCell(cell);

                // column 2
                cell = new Cell();
                innerTable.AddCell(cell);

                // column 3
                cell = new Cell();
                cell.SetBorder(Border.NO_BORDER);
                innerTable.AddCell(cell);

                // column 4
                cell = new Cell();
                innerTable.AddCell(cell);

                // spacing
                cell = new Cell(1, 4);
                cell.SetHeight(3);
                cell.SetBorder(Border.NO_BORDER);
                innerTable.AddCell(cell);
            }

            // second nested table
            cell = new Cell().Add(innerTable);
            cell.SetNextRenderer(new RoundedBorderCellRenderer(cell));
            cell.SetBorder(Border.NO_BORDER);
            cell.SetPaddingLeft(8);
            cell.SetPaddingTop(8);
            cell.SetPaddingRight(8);
            cell.SetPaddingBottom(8);
            outerTable.AddCell(cell);

            // add the table
            doc.Add(outerTable);

            doc.Close();
        }

        private class RoundedBorderCellRenderer : CellRenderer
        {
            public RoundedBorderCellRenderer(Cell 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 RoundedBorderCellRenderer((Cell) modelElement);
            }

            public override void Draw(DrawContext drawContext)
            {
                drawContext.GetCanvas().RoundRectangle(GetOccupiedAreaBBox().GetX() + 1.5f,
                    GetOccupiedAreaBBox().GetY() + 1.5f, GetOccupiedAreaBBox().GetWidth() - 3,
                    GetOccupiedAreaBBox().GetHeight() - 3, 4);
                drawContext.GetCanvas().Stroke();
                base.Draw(drawContext);
            }
        }
    }
}


nestedtables

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.geom.PageSize;
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 java.io.File;

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

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

        new NestedTables().manipulatePdf(DEST);
    }

    protected void manipulatePdf(String dest) throws Exception {
        PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
        Document doc = new Document(pdfDoc, PageSize.A4.rotate());

        float[] columnWidths = {150, 40, 90, 51, 35, 25, 35, 35, 35, 32, 32, 33, 35, 60, 46, 26};
        Table table = new Table(columnWidths);
        table.setWidth(770F);

        buildNestedTables(table);

        doc.add(new Paragraph("Add table straight to another table"));
        doc.add(table);

        doc.close();
    }

    private static void buildNestedTables(Table outerTable) {
        Table innerTable1 = new Table(UnitValue.createPercentArray(1)).useAllAvailableWidth();
        Table innerTable2 = new Table(UnitValue.createPercentArray(2)).useAllAvailableWidth();

        innerTable1.addCell("Cell 1");
        innerTable1.addCell("Cell 2");
        outerTable.addCell(innerTable1);

        innerTable2.addCell("Cell 3");
        innerTable2.addCell("Cell 4");
        outerTable.addCell(innerTable2);

        Cell cell = new Cell(1, 14);
        outerTable.addCell(cell);
    }
}

C#

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

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

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

            new NestedTables().ManipulatePdf(DEST);
        }

        private void ManipulatePdf(string dest)
        {
            PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
            Document doc = new Document(pdfDoc, PageSize.A4.Rotate());

            float[] columnWidths = {150, 40, 90, 51, 35, 25, 35, 35, 35, 32, 32, 33, 35, 60, 46, 26};
            Table table = new Table(columnWidths);
            table.SetWidth(770F);

            BuildNestedTables(table);

            doc.Add(new Paragraph("Add table straight to another table"));
            doc.Add(table);

            doc.Close();
        }

        private static void BuildNestedTables(Table outerTable)
        {
            Table innerTable1 = new Table(UnitValue.CreatePercentArray(1)).UseAllAvailableWidth();
            Table innerTable2 = new Table(UnitValue.CreatePercentArray(2)).UseAllAvailableWidth();
            
            innerTable1.AddCell("Cell 1");
            innerTable1.AddCell("Cell 2");
            outerTable.AddCell(innerTable1);

            innerTable2.AddCell("Cell 3");
            innerTable2.AddCell("Cell 4");
            outerTable.AddCell(innerTable2);

            Cell cell = new Cell(1, 14);
            outerTable.AddCell(cell);
        }
    }
}


nestedtables2

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 NestedTables2 {
    public static final String DEST = "./target/sandbox/tables/nested_tables2.pdf";

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

        new NestedTables2().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(new float[] {1, 15}));

        for (int i = 1; i <= 20; i++) {
            table.addCell(String.valueOf(i));
            table.addCell("It is not smart to use iText 2.1.7!");
        }

        Table innertable = new Table(UnitValue.createPercentArray(new float[] {1, 15}));

        for (int i = 0; i < 90; i++) {
            innertable.addCell(String.valueOf(i + 1));
            innertable.addCell("Upgrade if you're a professional developer!");
        }

        table.addCell("21");
        table.addCell(innertable);

        for (int i = 22; i <= 40; i++) {
            table.addCell(String.valueOf(i));
            table.addCell("It is not smart to use iText 2.1.7!");
        }

        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 NestedTables2
    {
        public static readonly string DEST = "results/sandbox/tables/nested_tables2.pdf";

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

            new NestedTables2().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(new float[] {1, 15}));

            for (int i = 1; i <= 20; i++)
            {
                table.AddCell(i.ToString());
                table.AddCell("It is not smart to use iText 2.1.7!");
            }

            Table innertable = new Table(UnitValue.CreatePercentArray(new float[] {1, 15}));

            for (int i = 0; i < 90; i++)
            {
                innertable.AddCell((i + 1).ToString());
                innertable.AddCell("Upgrade if you're a professional developer!");
            }

            table.AddCell("21");
            table.AddCell(innertable);

            for (int i = 22; i <= 40; i++)
            {
                table.AddCell(i.ToString());
                table.AddCell("It is not smart to use iText 2.1.7!");
            }

            doc.Add(table);

            doc.Close();
        }
    }
}


nestedtables3

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.geom.PageSize;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
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.Property;
import com.itextpdf.layout.properties.UnitValue;
import com.itextpdf.layout.renderer.AbstractRenderer;
import com.itextpdf.layout.renderer.DrawContext;
import com.itextpdf.layout.renderer.IRenderer;
import com.itextpdf.layout.renderer.TableRenderer;

import java.io.File;

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

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

        new NestedTables3().manipulatePdf(DEST);
    }

    protected void manipulatePdf(String dest) throws Exception {
        PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
        Document doc = new Document(pdfDoc, PageSize.A4.rotate());

        // Creates outer table
        Table table = new Table(UnitValue.createPercentArray(2)).useAllAvailableWidth();

        // Draws header for every nested table.
        // That header will be repeated on every page.
        table.setNextRenderer(new InnerTableRenderer(table, new Table.RowRange(0, 0)));

        Cell cell = new Cell(1, 2).add(new Paragraph("This outer header is repeated on every page"));
        table.addHeaderCell(cell);

        // Creates the first inner table
        Table inner1 = new Table(UnitValue.createPercentArray(1)).useAllAvailableWidth();

        // Creates an empty header cell for the header content drawn by outer table renderer
        cell = new Cell();
        cell.setHeight(20);
        inner1.addHeaderCell(cell);

        // Creates header cell that will be repeated only on pages, where that table has content
        cell = new Cell().add(new Paragraph("This inner header won't be repeated on every page"));
        inner1.addHeaderCell(cell);

        for (int i = 0; i < 10; i++) {
            inner1.addCell(new Cell().add(new Paragraph("test")));
        }

        cell = new Cell().add(inner1);
        table.addCell(cell.setPadding(0));

        // Creates the second inner table
        Table inner2 = new Table(UnitValue.createPercentArray(1)).useAllAvailableWidth();

        // Creates an empty header cell for the header content drawn by outer table renderer
        cell = new Cell();
        cell.setHeight(20);
        inner2.addHeaderCell(cell);

        // Creates header cell that will be repeated only on pages, where that table has content
        cell = new Cell().add(new Paragraph("This inner header may be repeated on every page"));
        inner2.addHeaderCell(cell);

        for (int i = 0; i < 35; i++) {
            inner2.addCell("test");
        }

        cell = new Cell().add(inner2);
        table.addCell(cell.setPadding(0));

        doc.add(table);

        doc.close();
    }

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

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

        @Override
        public void drawChildren(DrawContext drawContext) {
            super.drawChildren(drawContext);

            for (IRenderer renderer : childRenderers) {
                PdfCanvas canvas = drawContext.getCanvas();
                canvas.beginText();
                Rectangle box = ((AbstractRenderer) renderer).getInnerAreaBBox();
                UnitValue fontSize = this.getPropertyAsUnitValue(Property.FONT_SIZE);
                canvas.moveText(box.getLeft(), box.getTop() - (fontSize.isPointValue() ? fontSize.getValue() : 12f));
                canvas.setFontAndSize(this.getPropertyAsFont(Property.FONT),
                        fontSize.isPointValue() ? fontSize.getValue() : 12f);
                canvas.showText("This inner table header will always be repeated");
                canvas.endText();
                canvas.stroke();
            }
        }

        // 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 InnerTableRenderer((Table) modelElement);
        }
    }
}

C#

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

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

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

            new NestedTables3().ManipulatePdf(DEST);
        }

        private void ManipulatePdf(string dest)
        {
            PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
            Document doc = new Document(pdfDoc, PageSize.A4.Rotate());

            // Creates outer table
            Table table = new Table(UnitValue.CreatePercentArray(2)).UseAllAvailableWidth();
            
            // Draws header for every nested table.
            // That header will be repeated on every page.
            table.SetNextRenderer(new InnerTableRenderer(table, new Table.RowRange(0, 0)));

            Cell cell = new Cell(1, 2).Add(new Paragraph("This outer header is repeated on every page"));
            table.AddHeaderCell(cell);

            // Creates the first inner table 
            Table inner1 = new Table(UnitValue.CreatePercentArray(1)).UseAllAvailableWidth();

            // Creates an empty header cell for the header content drawn by outer table renderer
            cell = new Cell();
            cell.SetHeight(20);
            inner1.AddHeaderCell(cell);

            // Creates header cell that will be repeated only on pages, where that table has content
            cell = new Cell().Add(new Paragraph("This inner header won't be repeated on every page"));
            inner1.AddHeaderCell(cell);

            for (int i = 0; i < 10; i++)
            {
                inner1.AddCell(new Cell().Add(new Paragraph("test")));
            }

            cell = new Cell().Add(inner1);
            table.AddCell(cell.SetPadding(0));

            // Creates the second inner table 
            Table inner2 = new Table(UnitValue.CreatePercentArray(1)).UseAllAvailableWidth();

            // Creates an empty header cell for the header content drawn by outer table renderer
            cell = new Cell();
            cell.SetHeight(20);
            inner2.AddHeaderCell(cell);

            // Creates header cell that will be repeated only on pages, where that table has content
            cell = new Cell().Add(new Paragraph("This inner header may be repeated on every page"));
            inner2.AddHeaderCell(cell);

            for (int i = 0; i < 35; i++)
            {
                inner2.AddCell("test");
            }

            cell = new Cell().Add(inner2);
            table.AddCell(cell.SetPadding(0));

            doc.Add(table);

            doc.Close();
        }

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

            protected InnerTableRenderer(Table modelElement)
                : base(modelElement)
            {
            }
            
            public override void DrawChildren(DrawContext drawContext)
            {
                base.DrawChildren(drawContext);

                foreach (IRenderer renderer in childRenderers)
                {
                    PdfCanvas canvas = drawContext.GetCanvas();
                    canvas.BeginText();
                    Rectangle box = ((AbstractRenderer) renderer).GetInnerAreaBBox();
                    UnitValue fontSize = GetPropertyAsUnitValue(Property.FONT_SIZE);
                    canvas.MoveText(box.GetLeft(),
                        box.GetTop() - (fontSize.IsPointValue() ? fontSize.GetValue() : 12f));
                    canvas.SetFontAndSize(GetPropertyAsFont(Property.FONT),
                        fontSize.IsPointValue() ? fontSize.GetValue() : 12f);
                    canvas.ShowText("This inner table header will always be repeated");
                    canvas.EndText();
                    canvas.Stroke();
                }
            }           
            
            // 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 InnerTableRenderer((Table) modelElement);
            }
        }
    }
}


nestedtablesaligned

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.geom.PageSize;
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.HorizontalAlignment;
import com.itextpdf.layout.properties.UnitValue;

import java.io.File;

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

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

        new NestedTablesAligned().manipulatePdf(DEST);
    }

    protected void manipulatePdf(String dest) throws Exception {
        PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
        Document doc = new Document(pdfDoc, PageSize.A4.rotate());

        float[] columnWidths = {200f, 200f, 200f};

        Table table = new Table(columnWidths);
        buildNestedTables(table);

        doc.add(table);

        doc.close();
    }

    private static void buildNestedTables(Table outerTable) {
        Table innerTable1 = new Table(UnitValue.createPercentArray(1));
        innerTable1.setWidth(100f);
        innerTable1.setHorizontalAlignment(HorizontalAlignment.LEFT);
        innerTable1.addCell("Cell 1");
        innerTable1.addCell("Cell 2");
        outerTable.addCell(innerTable1);

        Table innerTable2 = new Table(UnitValue.createPercentArray(2));
        innerTable2.setWidth(100f);
        innerTable2.setHorizontalAlignment(HorizontalAlignment.CENTER);
        innerTable2.addCell("Cell 3");
        innerTable2.addCell("Cell 4");
        outerTable.addCell(innerTable2);

        Table innerTable3 = new Table(UnitValue.createPercentArray(2));
        innerTable3.setWidth(100f);
        innerTable3.setHorizontalAlignment(HorizontalAlignment.RIGHT);
        innerTable3.addCell("Cell 5");
        innerTable3.addCell("Cell 6");
        outerTable.addCell(innerTable3);
    }
}

C#

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

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

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

            new NestedTablesAligned().ManipulatePdf(DEST);
        }

        private void ManipulatePdf(String dest)
        {
            PdfDocument pdfDoc = new PdfDocument(new PdfWriter(dest));
            Document doc = new Document(pdfDoc, PageSize.A4.Rotate());

            float[] columnWidths = {200f, 200f, 200f};

            Table table = new Table(columnWidths);
            BuildNestedTables(table);

            doc.Add(table);

            doc.Close();
        }

        private static void BuildNestedTables(Table outerTable)
        {
            Table innerTable1 = new Table(UnitValue.CreatePercentArray(1));
            innerTable1.SetWidth(100f);
            innerTable1.SetHorizontalAlignment(HorizontalAlignment.LEFT);
            innerTable1.AddCell("Cell 1");
            innerTable1.AddCell("Cell 2");
            outerTable.AddCell(innerTable1);

            Table innerTable2 = new Table(UnitValue.CreatePercentArray(2));
            innerTable2.SetWidth(100f);
            innerTable2.SetHorizontalAlignment(HorizontalAlignment.CENTER);
            innerTable2.AddCell("Cell 3");
            innerTable2.AddCell("Cell 4");
            outerTable.AddCell(innerTable2);

            Table innerTable3 = new Table(UnitValue.CreatePercentArray(2));
            innerTable3.SetWidth(100f);
            innerTable3.SetHorizontalAlignment(HorizontalAlignment.RIGHT);
            innerTable3.AddCell("Cell 5");
            innerTable3.AddCell("Cell 6");
            outerTable.AddCell(innerTable3);
        }
    }
}
JavaScript errors detected

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

If this problem persists, please contact our support.