C#: How to layout a PDF document with rowspan, colspan, and nested tables using PDFFlow

Tags: csharp, dotnet
Published: 2021-08-26 14:26:59

This tutorial will show you when to use rowspan, colspan, and nested tables to get particular layouts and will guide you step-by-step to easily layout your PDF with the help of these options using the C# PDF generation library PDFFlow.

Layouting using rowspans, colspans and nested tables allows you to arrange data into rows and columns. They are commonly used to display tabular data like product listings, customer details, financial reports, tickets, and so on.

Use rowspan and colspan parameters if you need to get a table with cells spanning several rows and columns. Setting rowspan and colspan for table cells allow you to create simple well-organized layouts.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7nhqvoq14qg3oht5f9ws.png)

Use a nested table if you need to get a table with a more complex structure. For complex cases, you should divide your table into several logical parts and add them as nested tables. nested tables allow you to create bigger, more complex but well-ordered layouts.
In the following example, the nested table is highlighted in blue.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hcgnfadek1mjv0w1v95k.png)

Getting started
First, we need to create a new console application project "MyLayoutingDoc" in Visual Studio and choose Language “C#”.
Then we need to add the Gehtsoft.PDFFlowlib library to our project. You can download it as a NuGet package from NuGet Gallery | Gehtsoft.PDFFlowLib.
You can also install it from the Visual Studio NuGet Package Manager: 
1. In Solution Explorer, right-click either References or a project and select Manage NuGet Packages.
2. Go to the Browse tab and search for the Gehtsoft.PDFFlowLib package using the search box on the upper left. 
3. Select the package from the list and click Install.

When to use rowspan
When you want to place components in a single table cell vertically spanning several rows.
How to create a layout with rowspan 
Let’s create a table with 4 rows and 4 columns and make the first cell span 4 rows.
First, use the AddColumnToTable() method to define how many columns you need to create in your table, and the AddRow() method to define how many rows you need to create.
To add cells to rows, you need to use the method AddCellToRow(), you can also add text to cells using the same method by adding your text in parentheses: AddCellToRow(“your text here”).
Now to make one cell span 2 or more rows, first, you need to use the AddCell() method, then use the SetRowSpan(number of rows to span here) method, then the ToRow() method.
Ex: .AddCell("row span").SetRowSpan(4).ToRow()

Also, you can use the method AddCell and pass its 3 parameters Text, colspan, and rowspan to set how many rows and columns should the cell span.
Ex:  .AddCell("text here", 1, 3).ToRow()
The following code will create a table with 4 rows and 4 columns, with the first cell spanning 4 rows:

DocumentBuilder.New().AddSection().AddTable()
// add 4 columns to the table
                                   .AddColumnToTable().AddColumnToTable()
                                   .AddColumnToTable().AddColumnToTable()
// add the first row
                                   .AddRow()
// add the first cell and make it span 4 rows
                                       .AddCell("row span").SetRowSpan(4).ToRow()
                                       .AddCellToRow()
                                       .AddCellToRow()
                                       .AddCellToRow().ToTable()
// add the second row
                                   .AddRow()
                                       .AddCellToRow()
                                       .AddCellToRow()
                                       .AddCellToRow()
                                       .AddCellToRow().ToTable()
//  add the third row
                                   .AddRow()
                                       .AddCellToRow()
                                       .AddCellToRow()
                                       .AddCellToRow()
                                       .AddCellToRow().ToTable()
// add the fourth row
                                   .AddRow()
                                       .AddCellToRow()
                                       .AddCellToRow()
                                       .AddCellToRow()
                                       .AddCellToRow()
// generate the PDF document
                           .ToDocument().Build("Result.pdf");
The result should be similar to this:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u03mcgii88ow3foq00cr.png)

When to use colspan
When you want to place components in a single table cell horizontally spanning several columns.
How to create a layout with colspan
Using colspan is pretty much the same as using rowspan, you first need to use the AddColumnToTable() method to define how many columns you need, and the AddRow() method to define how many rows you need to create in your table. Here we are creating a table with 4 rows and 4 columns with the first cell spanning 4 columns.
To add cells to a row, you need to use the method AddCellToRow().
Now to make one cell span 4 columns, first, you need to use the AddCell() method, then use the SetColSpan(number of columns to span here) method, then the ToTable() method.
Ex: .AddCell("col span").SetColSpan(4).ToTable()

Or you can use the method AddCell and pass its 3 parameters Text, colspan, and rowspan.
Ex:  .AddCell("text here", 1, 3).ToRow()
The following code will create a table with 4 rows and 4 columns, with the first cell spanning 4 columns:

DocumentBuilder.New().AddSection().AddTable()
// create 4 columns
                       .AddColumnToTable().AddColumnToTable()
                       .AddColumnToTable().AddColumnToTable()
// add the first cell to the first row and make it span 4 columns
                       .AddRow()
                           .AddCell("col span").SetColSpan(4).ToTable()
// add the second row
                       .AddRow()
// create 4 cells in the second row
                           .AddCellToRow()
                           .AddCellToRow()
                           .AddCellToRow()
                           .AddCellToRow().ToTable()
// add the third row
                       .AddRow()
                           .AddCellToRow()
                           .AddCellToRow()
                           .AddCellToRow()
                           .AddCellToRow().ToTable()
// add the fourth row
                       .AddRow()
                           .AddCellToRow()
                           .AddCellToRow()
                           .AddCellToRow()
                           .AddCellToRow()
//  generate the PDF document
               .ToDocument().Build("Result.pdf");
The result should be similar to this:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cnq05d5fp5wbs159s117.png)
	
Using rowspan and colspan together
If you need to create a layout where cells span both several rows and several columns, you just need to use both methods SetRowSpan(#) and SetColSpan(#).
 For example:
                     .AddRow()
                            .AddCell("row span").SetRowSpan(4).ToRow()
                            .AddCell("col span").SetColSpan(3).ToTable()
Notice that we set the number of columns to span to 3 because the first cell already spans 4 rows and only 3 columns are left to span.
The following code will create a table with 4 rows and 4 columns, with the first cell spanning 4 rows and the second cell spanning 3 columns:
             DocumentBuilder.New().AddSection().AddTable()
// add 4 columns to the table
                        .AddColumnToTable().AddColumnToTable()
                        .AddColumnToTable().AddColumnToTable()
// add the first row
                        .AddRow()
// make the first cell in the first row span 4 rows
                            .AddCell("row span").SetRowSpan(4).ToRow()
// make the second cell in the first row span 3 columns
                            .AddCell("col span").SetColSpan(3).ToTable()
// add the second row
                        .AddRow()
                            .AddCellToRow()
                            .AddCellToRow()
                            .AddCellToRow()
                            .AddCellToRow().ToTable()
// add the third row
                        .AddRow()
                            .AddCellToRow()
                            .AddCellToRow()
                            .AddCellToRow()
                            .AddCellToRow().ToTable()
// add the fourth row
                        .AddRow()
                            .AddCellToRow()
                            .AddCellToRow()
                            .AddCellToRow()
                            .AddCellToRow()
// generate the PDF document
                .ToDocument().Build("Result.pdf");
The result should be similar to this:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p33mlv24dbsggpon7kg1.png)

When to use nested tables
You should use a nested table when you need to design a more complicated layout, for example, if you need to organize components in a tabular format within a single table cell.
Here's an example of a complex real document created using the PDFFlow library.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ftpjfcqzse44g72hzk1l.png)

The area marked by a green rectangle is a table with a complex structure - it contains two nested tables - marked in red and dark-yellow. These tables are nested inside the cells of the main table that contains two columns (75% and 25% width respectively).
But it is important to note that all elements in any cell are placed after one another in any case by using the break command “\n”. 
A clear example of this behavior is the placement of the texts: "Passenger name", "PAVEL REMPEL".
How to create a layout with nested tables
1- Decomposing the code into separate procedures
To create several nested tables we should decompose the code into separate procedures. Create methods to generate each nested table, then call it when creating the main table, and pass the cell where we need to insert the nested table in the cell parameter.
For example:
           var row2 = table.AddRow().AddCellToRow();
            AddTablePartToCell(row2.AddCell());
// basically generate and insert a table inside a table cell
        private static void AddTablePartToCell(TableCellBuilder cell)
        {
//  create a nested table with 2 rows and 2 columns
            cell.AddTable().AddColumnToTable().AddColumnToTable()                    
                    .AddRow()
                        .AddCellToRow("Row 1 Col 1").AddCellToRow("Row 1 Col 2").ToTable()
                    .AddRow().AddCellToRow("Row 2 Col 1").AddCellToRow("Row 2 Col 2");

        }
In this example, the nested table is highlighted in yellow.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dc23oqyzvcudl1nxcir5.png)

2- Using fluent style to create nested tables
When you need to create a document using a table with nested tables, as an alternative to decomposing the code into separate procedures, you can get the same result using the fluent style to code the entire complex table. You can change the current fluent context to parent objects using the following To... methods: ToTable, ToRow, ToCell, ToSection. To avoid errors when creating nested tables, it is important to correctly specify changes of the current fluent context.
Example of creating a simple table with a nested table using the fluent style:
            DocumentBuilder.New()
            .AddSection()
            .AddTable()
            .AddColumnToTable()
            .AddRow()
            .AddCell()
                .AddTable()
                    .AddColumnToTable()
                    .AddRow()
                    .AddCell("Nested table")
                .ToTable()
            .ToCell()
                .ToTable()
            .AddRow()
                .AddCell("Parent table")
                .ToDocument().Build("Result.pdf");

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0j3p7cxn210eurjf0ksx.png)

Also, you can set the width of each column in percent using the AddColumnPercent("", %) method. In our case, we will set the first column to 25% and the second column to 75%.
For example:
                        .AddColumnPercent("", 25).ToTable()
                        .AddColumnPercent("", 75).ToTable()
Create the first row and add 2 cells to it using the AddCell() method as follows:
.AddRow()
                        .AddCell("column 1,\nrow span", 1, 3).ToRow()
                        .AddCell("column 2")
Notice that the AddCell method here takes 3 parameters (text, colspan, and rowspan), also remember that using “\n” within the text will make a line break.
To create the second row, we need to declare a new var and fill it with a new table cell, then call our method AddTablePartToCell() and pass the newly created cell in it, as shown in the following code:
            var row2 = table.AddRow()
                            .AddCellToRow();
            AddTablePartToCell(row2.AddCell());



The following code will create a table (main table) of 2 columns and 3 rows, span the first cell to 3 rows and insert another table (nested table) in the second column and the second row:
        {
//  create the main table
            var table = DocumentBuilder.New()
                .AddSection()
                    .AddTable()
// add 2 columns to the table with 25% and 75% width
                        .AddColumnPercent("", 25).ToTable()
                        .AddColumnPercent("", 75).ToTable()
                        .AddRow()
// \n will create a line-break inside the cell
                        .AddCell("column 1,\nrow span", 1, 3).ToRow()
                        .AddCell("column 2")
                .ToTable();
//  create the second row
            var row2 = table.AddRow()
                            .AddCellToRow();
// here we call the method that generates the nested table and inserts it into 
// the cell of the main table
            AddTablePartToCell(row2.AddCell());
//  add the last row to the main table 
            table.AddRow()
                            .AddCellToRow()
                            .AddCellToRow()
            .ToDocument().Build("Result.pdf");
        }
// create a method that generates the nested table and inserts it into the main table
        private static void AddTablePartToCell(TableCellBuilder cell)
        {
// create the nested table
            cell.AddTable()
// create 4 columns
                    .AddColumnToTable().AddColumnToTable()
                    .AddColumnToTable().AddColumnToTable()
                    .AddRow()
// using \n to make a line-break 
// add the first cell and make it span 4 rows
                        .AddCell("column 1,\nrow span", 1, 4).ToRow()
                        .AddCellToRow("column 2")
                        .AddCellToRow("column 3")
                        .AddCell("column 4").ToTable()
// add the second row
                    .AddRow()
                        .AddCellToRow().AddCellToRow()
                        .AddCellToRow().AddCellToRow().ToTable()
// add the third row
                    .AddRow()
                        .AddCellToRow().AddCellToRow()
                        .AddCellToRow().AddCellToRow().ToTable()
// add the fourth row
                    .AddRow()
                        .AddCellToRow().AddCellToRow()
                        .AddCellToRow().AddCellToRow();
        }
The result should be similar to this:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9qxpha75ma2ic63f9y48.png)

The nested table is highlighted in yellow and the main table is highlighted in grey.


Create a complex table layout using nested tables, rowspan, and colspan
Now let's try to create an even more complex layout containing 2 nested tables with spanned rows and columns.
It’s very simple, all we have to do is to create a method for each nested table that generates and fills the nested table inside the main table’s cells.
First, we need to create 2 methods that generate the 2 nested tables:
//  notice that this method expects a TableCellBuilder parameter        
private static void AddInnerTable1(TableCellBuilder cell)
        {
// let’s set the background of the first nested table to green
            cell.AddTable().SetBackColor(Gehtsoft.PDFFlow.Models.Shared.Color.Green)
// add two columns 
                    .AddColumnToTable().AddColumnToTable()
// add the first row and the first cell with the text “Name”
                    .AddRow()
                        .AddCellToRow("Name")
// add the second cell and make it span 4 rows
                        .AddCell("photo", 1, 4)
                        .SetHorizontalAlignment(HorizontalAlignment.Center)
                        .ToTable()
//  add the other 3 rows and fill their cells with texts
                    .AddRow()
                        .AddCellToRow("Surname")
                        .AddCell().ToTable()
                    .AddRow()
                        .AddCellToRow("State")
                        .AddCell().ToTable()
                    .AddRow()
                        .AddCellToRow("City")
                        .AddCell().ToTable();
        }        
// now we create the second method that generates the second nested table
private static void AddInnerTable2(TableCellBuilder cell)
        {
// let’s set the background of the second nested table to yellow
            cell.AddTable().SetBackColor(Gehtsoft.PDFFlow.Models.Shared.Color.Yellow)
// add two columns 
                    .AddColumnToTable().AddColumnToTable()
// add the first row and the first cell with the text “Department”
                    .AddRow()
                        .AddCellToRow("Department")
// add the second cell to the first row and make it span 2 rows
                        .AddCell("image", 1, 2)
                        .SetHorizontalAlignment(HorizontalAlignment.Center)
                        .ToTable()
// add the second row
                    .AddRow()
                        .AddCellToRow("Structure")
                        .AddCell().ToTable()
// add the third row
                    .AddRow()
                        .AddCellToRow("Floor")
// add the second cell to the third row and make it span 2 rows
                        .AddCell("qrcode", 1, 2)
                        .SetHorizontalAlignment(HorizontalAlignment.Center)
                        .ToTable()
// add the fourth row
                    .AddRow()
                        .AddCellToRow("Room")
                        .AddCell().ToTable();
        }



// now what is left is to create the main table, with 2 columns and 3 rows,
// in the main class and call our 2 methods
// that will insert the two nested tables in the main table
{
            var table = DocumentBuilder.New()
                .AddSection().AddTable().AddColumnToTable().AddColumnToTable()
// here we create the first row with 2 cells with the  center alignment 
                        .AddRow().AddCellToRow("Personal info").SetHorizontalAlignment(HorizontalAlignment.Center)
                        .AddCellToRow("Department info").SetHorizontalAlignment(HorizontalAlignment.Center).ToTable();
// now the magic happens,
// here we create the second row of the main table
// and call our 2 methods to insert the two nested tables in the 
// first and second cells of the second row
            var row2 = table.AddRow();
            AddInnerTable1(row2.AddCell());
            AddInnerTable2(row2.AddCell());
//  add the third row to the main table and make it span 2 columns
            table.AddRow().AddCellToRow("Signature",2,1)
            .ToDocument().Build("Result.pdf");
}
The result should be similar to this:


![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rw53oqczuhutm5lt26k9.png)

We’ve covered the most important tips on how to layout documents using rowspans, colspans, and nested tables on simple and complex examples. 
Now you know when to use colspan, rowspan, and nested tables and can create PDF documents with complex layouts using the instructions of this tutorial.

You can find more useful examples on generating PDF docs on GitHub here: https://go.pdfflow.io/lib_example

For more information about the PDFFlow library, check out the GS PDFFlow website: https://go.pdfflow.io/library_home