Persits Software, Inc. Web Site
 Navigator:  Home |  Manual |  Chapter 7: Tables
Chapter 8: Security Chapter 6: Text and Fonts
  Chapter 7: Tables
7.1 Table Support Overview
7.2 Cell Spanning and Size Adjustment
7.3 Table Rendering

7.1 Table Support Overview

With AspPDF, you can create HTML-style tables and fill them with text data. Once a table is created and filled, it can be rendered onto a canvas.

Tables are represented by the PdfTable object creatable via the CreateTable method of the PdfDocument object.

PdfTable is a free-floating entity. It is not tied to a canvas, page or any other object. Creating or changing a PdfTable object has no effect on the appearance of the document until the table, or any portion thereof, is rendered onto a canvas via the Canvas.DrawTable method. The same table can be drawn on multiple pages, or be part of one or more PdfGraphics objects.

7.1.1 Table Creation Parameters

The Doc.CreateTable method requires two parameters: Width and Height (in default user units). The number of columns and rows in the table is specified via Cols and Rows, respectively. These parameters are both 1 by default. When a table is created, all rows and columns are spaced out evenly within the table.

A generic table has an outer border, and several rows of cells. Each cell has a border of its own. Cells are separated from each other and the outer border by a margin. The following diagram illustrates various table parameters:

A table's origin is located in the upper-left corner of the table. The y axis still extends upwards, so all y-coordinates of the cells are negative.

Border is the width of the table's outer border (0 by default.)

CellBorder is the width of all cell borders (1 by default.) CellSpacing is the width of a margin that separates individual cells from each other and the outer border (0 by default).

CellPadding is the width of a margin within a cell that separates text written in that cell from the cell's borders (0 by default.)

The table colors are specified by the following parameters: BorderColor (the color of the outer border, black by default), CellBorderColor (the color of all cell borders, black by default), BgColor (the color of areas between cells, transparent by default), and CellBgColor (the color of areas within cell borders, transparent by default).

As of Version 2.7, color spaces other than RGB can be used to specify table colors. See Section 15.4 - Using Color Spaces with PdfTable and Other Objects for more information.

7.1.2 Working with Individual Rows and Cells

The PdfTable object provides the Rows property which returns the PdfRows collection of PdfRow objects representing individual table rows. The PdfRow object allows you to change this row's height and move it up and down within the table. It also allows you to change border and background colors of all its cells via the BorderColor and BgColor properties.

The PdfRow object provides the Cells property which returns the PdfCells collection of PdfCell objects representing individual cells in a row. The PdfCell object enables you to change the border width, border color, background color, size, padding, ColSpan and RowSpan of an individual cell.

An individual table cell can also be referenced directly via PdfTable's default property At by specifying 1-based row and cell indices as arguments, as follows:

Set Cell = Table.At(4, 2)

or simply

Set Cell = Table(4, 2)

Rows and Cells are numbered from left to right and from top to bottom. Therefore, the upper-left cell of a table has the indices (1, 1).

The PdfCell object also provides the AddText method for placing text in a cell. This method is almost identical to Canvas.DrawText, except that instead of the X, Y, Width and Height parameters the cell coordinates and sizes are used, and two extra optional parameters, IndentX and IndentY are added for precise positioning of text inside the cell. This method also uses an optional Expand parameter described below. AddText's Font argument is optional but for it to be omitted, you must specify a table-wide default font via the Table.Font property.

The following code sample uses all the properties, methods and collections described above to draw a chessboard. Here, we also use a freeware symbol font Chess Merida residing in the file MERIFONT.TTF.

' Create 8x8 table to depict a chessboard
Set Table = Doc.CreateTable( "width=200; height=200; rows=8; cols=8; border=1; cellborder=0; cellspacing=2")

' Select a Chess font to depict chess pieces
Set Font = Doc.Fonts.LoadFromFile( Server.MapPath("MERIFONT.TTF") )

Table.Font = Font

' initialize Pieces array
Dim Pieces
Pieces = Array(0,_
&HF074, &HF06D, &HF076, &HF077, &HF06C, &HF076, &HF06D, &HF074, _
&HF06F, &HF06F, &HF06F, &HF06F, &HF06F, &HF06F, &HF06F, &HF06F, _
&HF000, &HF000, &HF000, &HF000, &HF000, &HF000, &HF000, &HF000, _
&HF000, &HF000, &HF000, &HF000, &HF000, &HF000, &HF000, &HF000, _
&HF000, &HF000, &HF000, &HF000, &HF000, &HF000, &HF000, &HF000, _
&HF000, &HF000, &HF000, &HF000, &HF000, &HF000, &HF000, &HF000, _
&HF070, &HF070, &HF070, &HF070, &HF070, &HF070, &HF070, &HF070, _
&HF072, &HF06E, &HF062, &HF071, &HF06B, &HF062, &HF06E, &HF072 )

' go over all cells in the table
For Each Row in Table.Rows
   For Each Cell in Row.Cells
      ' set background on cells which sum of indices is odd
      If (Cell.Index + Row.Index) Mod 2 = 1 Then
         Cell.BgColor = "brown"
      End if

      Piece = Pieces( 8 * (Row.Index - 1) + Cell.Index )
      Cell.AddText ChrW(Piece), "size=20; indentx=1; indenty=1"

' Add a new page
Set Page = Doc.Pages.Add

Page.Canvas.DrawTable Table, "x=206, y=498"

... // beginning omitted for brevity

// initialize Pieces array
int [] Pieces = {0,
0xF074, 0xF06D, 0xF076, 0xF077, 0xF06C, 0xF076, 0xF06D, 0xF074,
0xF06F, 0xF06F, 0xF06F, 0xF06F, 0xF06F, 0xF06F, 0xF06F, 0xF06F,
0xF000, 0xF000, 0xF000, 0xF000, 0xF000, 0xF000, 0xF000, 0xF000,
0xF000, 0xF000, 0xF000, 0xF000, 0xF000, 0xF000, 0xF000, 0xF000,
0xF000, 0xF000, 0xF000, 0xF000, 0xF000, 0xF000, 0xF000, 0xF000,
0xF000, 0xF000, 0xF000, 0xF000, 0xF000, 0xF000, 0xF000, 0xF000,
0xF070, 0xF070, 0xF070, 0xF070, 0xF070, 0xF070, 0xF070, 0xF070,
0xF072, 0xF06E, 0xF062, 0xF071, 0xF06B, 0xF062, 0xF06E, 0xF072 };

// go over all cells in the table
foreach( IPdfRow objRow in objTable.Rows )
   foreach( IPdfCell objCell in objRow.Cells )
      // set background on cells which sum of indices is odd
      if( (objCell.Index + objRow.Index) % 2 == 1 )
         objCell.BgColor = "brown";

      int Piece = Pieces[ 8 * (objRow.Index - 1) + objCell.Index ];
      objCell.AddText( ((char)Piece).ToString(), "size=20; indentx=1; indenty=1", Missing.Value );

... // end omitted for brevity

Click the links below to run this code sample:

http://localhost/asppdf/manual_07/07_chess.aspx  Why is this link not working?

7.1.3 Cell Border Management

By default, each cell's border is a rectangle with all four sides drawn in the same color (specified via Cell.BorderColor). It is also possible to hide any, or all, of this rectangle's sides, and also assign individual colors to each side.

Side visibility and coloring is set via PdfCell's SetBorderParams method which accepts a PdfParam object or parameter string as an argument. The following parameters can be used (all optional):

  • Top, Bottom, Right, Left - if set to False, hide the top, bottom, right or left side of the cell border, respectively. True by default.
  • TopColor, BottomColor, RightColor, LeftColor - specify the line color for the top, bottom, right or left side, respectively.

The following code fragment hides the left, top and right sides of a cell and sets the bottom side color to green:

Table.At(1, 2).SetBorderParams "Left=False, Right=False, Top=False, BottomColor=Green"

7.1.4 Drawing in a Cell

The PdfCell object provides a Canvas property which enables you to draw inside an individual cell the same way you would on a page as a whole. The coordinate space origin is located in the lower-left corner of the cell. Cell.Canvas allows you to draw graphics, text and even other tables inside a cell.

When a table is rendered onto a page, its cells' contents is rendered in the following order:

1. Cell background.
2. The contents of Cell.Canvas, if any.
3. Text strings specified via Cell.AddText, if any.
4. Cell borders.

The following code fragment draws a small table inside a large table's cell. The small table, in turn, has the word "Hello" drawn in its upper-left cell.

Set SmallTable = Doc.CreateTable("Height=30; Width=30; cols=2; rows=2")
SmallTable.At(1, 1).Canvas.DrawText "Hello", "x=1, y=15; size=5", font

Table.At(1, 2).Canvas.DrawTable SmallTable, "x=2; y=50"

Note that unlike the Cell.AddText method, Cell.Canvas.DrawText does not affect the size of the cell.

7.2 Cell Spanning and Size Adjustment
As mentioned earlier, all cells are created equal in size when a new table is created. Heights and widths of individual rows and columns can then be adjusted using the Row.Height, Cell.Height and Cell.Width properties. Changing Row.Height changes the heights of all the cells in that row, as well as the overall table height. Changing Cell.Height has the same effect as changing the height of the row this cell belongs to. Changing Cell.Width also changes the widths of cells above and below this cell, as well as the overall table width.

The method Cell.AddText, if called with the parameter Expand set to True, has the side effect of changing the cell's height to accommodate the entire text string passed to it.

Similarly to HTML tables, PdfTable enables you to change the row span and column span of individual cells via the properties Cell.RowSpan and Cell.ColSpan, respectively. A cell whose ColSpan and/or RowSpan is set to a number greater than 1 "swallows" cells to the right and/or below itself. This cell's width and/or height is increased by that of the cells it "swallows" (plus the width of cell spacing, if applicable).

The following code fragment transforms a default 3 x 4 table (shown in the upper half of the diagram below) into a table shown in the lower half of the diagram:

Set param = Pdf.CreateParam("rows=3, cols=4, width=400, height=150")
... (set other parameters)
Set Table = Doc.CreateTable(param)

Table.Rows(1).Cells(1).width = 20
Table(1, 1).RowSpan = 3
Table(1, 3).RowSpan = 2
Table(1, 3).ColSpan = 2
Table.Rows(1).Cells(2).width = 200
Table(3, 2).AddText "Hello World!!!", "size=30; expand=true", Font

Note that the height of row 3 was implicitly increased by calling AddText with the Expand parameter set to True. If that parameter were omitted, only the word "Hello" would be showing and the cell height would remain unchanged.

Rows can be added to a table via the Rows.Add method which takes two arguments: row height and, optionally, the desired position of the new row. By default, rows are added to the end of the table. The second argument is the 1-based index of a row to insert the new one after. The value of 0 means the new row becomes first.

7.3 Table Rendering
Once a table is created, adjusted and filled with data, it can be rendered onto a canvas via the Canvas.DrawTable method. This method expects two requires parameters, X and Y, which specify the coordinates of the table's upper-left corner (origin) on the canvas.

The DrawTable method also accepts an optional MaxHeight parameter which limits the vertical space the table can occupy on a canvas. By default, the limit is the bottom of the canvas. If a row does not fully fit in the space provided, it is not rendered, and neither are the rows that follow.

The DrawTable method is capable of rendering only a certain range of rows, or a set of ranges. This is especially handy when you need to render a large table that spans several pages, and you want the header and/or footer rows of the table to be present on each page. The row ranges are specified via the parameters RowFrom - RowTo, RowFrom1 - RowTo1, RowFrom2- RowTo2, etc.

DrawTable returns the index of the last row it managed to render.

The following code sample renders a multi-page report from data residing in a database table. This sample dynamically appends pages to the PDF document as needed to accommodate the table. The data for this code sample is taken from the MS Access file asppdf.mdb residing in the \Samples\Db subdirectory of the installation.

Set PDF = Server.CreateObject("Persits.Pdf")
Set Param = PDF.CreateParam
Set TextParam = PDF.CreateParam
Set Doc = PDF.CreateDocument

' Create table with one row (header), and 5 columns
Set Table = Doc.CreateTable("width=500; height=20; Rows=1; Cols=5; Border=1; CellSpacing=-1; cellpadding=2 ")
Table.Font = Doc.Fonts("Helvetica")

Set HeaderRow = Table.Rows(1)
With HeaderRow
   .BGColor = &H90F0FE
   .Cells(1).AddText "Category", Param
   .Cells(2).AddText "Description", Param
   .Cells(3).AddText "Billable", Param
   .Cells(4).AddText "Date", Param
   .Cells(5).AddText "Amount", Param
End With

' Set column widths
With Table.Rows(1)
   .Cells(1).Width = 80
   .Cells(2).Width = 160
   .Cells(3).Width = 50
   .Cells(4).Width = 70
   .Cells(5).Width = 60
End With

' Populate table with data
Set Conn = Server.CreateObject("ADODB.Connection")
Connect = "Driver={Microsoft Access Driver (*.mdb)};DBQ=" & Server.MapPath("..\db\asppdf.mdb")
Conn.Open Connect
Set rs = Server.CreateObject("adodb.recordset")
rs.Open "select * from report order by expensedate", Conn

param.Set "expand=true" ' expand cell vertically

Do While Not rs.EOF
   Set Row = Table.Rows.Add(20) ' row height
   param.Add "alignment=left"
   Row.Cells(1).AddText rs("Category"), param
   Row.Cells(2).AddText rs("Description"), param

   param.Add "alignment=center"
   If rs("Billable") Then Billable = "Yes" Else Billable = "No"
   Row.Cells(3).AddText Billable, param
   Row.Cells(4).AddText pdf.FormatDate( rs("ExpenseDate"), "%d %b %Y" ), param

   param.Add "alignment=right"
   Row.Cells(5).AddText pdf.FormatNumber(rs("Amount"), "precision=2, delimiter=true"), param

' Render table on document
Set Page = Doc.Pages.Add(612, 150)
Param("x") = (Page.Width - Table.Width) / 2 ' center table on page
Param("y") = Page.Height - 20
Param("MaxHeight") = 100

FirstRow = 2
Do While True
   LastRow = Page.Canvas.DrawTable( Table, Param )

   ' Print record numbers
   TextParam("x") = (Page.Width - Table.Width) / 2
   TextParam("y") = Page.Height - 5
   TextStr="Records "&FirstRow-1&" to "&LastRow-1&" of "&Table.Rows.Count-1
   Page.Canvas.DrawText TextStr, TextParam, doc.fonts("Courier-Bold")

   if LastRow >= Table.Rows.Count Then Exit Do ' entire table displayed

   ' Display remaining part of table on the next page
   Set Page = Page.NextPage
   Param.Add( "RowTo=1; RowFrom=1" ) ' Row 1 is header.
   Param("RowFrom1") = LastRow + 1 ' RowTo1 is omitted and presumed infinite
   FirstRow = LastRow + 1

IPdfManager objPdf = new PdfManager();
IPdfParam objParam = objPdf.CreateParam(Missing.Value);
IPdfParam objTextParam = objPdf.CreateParam(Missing.Value);
IPdfDocument objDoc = objPdf.CreateDocument(Missing.Value);

// Create table with one row (header), and 5 columns
IPdfTable objTable = objDoc.CreateTable("width=500; height=20; Rows=1; Cols=5; Border=1; CellSpacing=-1; cellpadding=2 ");
objTable.Font = objDoc.Fonts["Helvetica", Missing.Value];

IPdfRow objHeaderRow = objTable.Rows[1];
objHeaderRow.BgColor = 0x90F0FE;
objHeaderRow.Cells[1].AddText( "Category", objParam, Missing.Value );
objHeaderRow.Cells[2].AddText( "Description", objParam, Missing.Value );
objHeaderRow.Cells[3].AddText( "Billable", objParam, Missing.Value );
objHeaderRow.Cells[4].AddText( "Date", objParam, Missing.Value );
objHeaderRow.Cells[5].AddText( "Amount", objParam, Missing.Value );

// Set column widths
objHeaderRow.Cells[1].Width = 80;
objHeaderRow.Cells[2].Width = 160;
objHeaderRow.Cells[3].Width = 50;
objHeaderRow.Cells[4].Width = 70;
objHeaderRow.Cells[5].Width = 60;

objParam.Set( "expand=true" ); // expand cells vertically

// Build OLE DB connection string
String strConnect = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + Server.MapPath("..\\db\\asppdf.mdb");

OleDbConnection myConnection = new OleDbConnection( strConnect );
OleDbDataAdapter myDataAdapter = new OleDbDataAdapter ("select * from report", myConnection);
DataSet myDataSet = new DataSet();
myDataAdapter.Fill( myDataSet, "report" );

// Populate table with data
DataTable tbl = myDataSet.Tables[0];
int nCount = tbl.Rows.Count;
for( int i = 0; i < nCount; i++ )
   IPdfRow objRow = objTable.Rows.Add(20, Missing.Value); // row height

   objParam.Add( "alignment=left" );
   objRow.Cells[1].AddText( tbl.Rows[i]["Category"].ToString(), objParam, Missing.Value );
   objRow.Cells[2].AddText( tbl.Rows[i]["Description"].ToString(), objParam, Missing.Value );

   objParam.Add( "alignment=center" );

   String strBillable;
   if( tbl.Rows[i]["Billable"].ToString() == "True" )
      strBillable = "Yes";
      strBillable = "No";

   DateTime dt = new DateTime();
   dt = (DateTime)tbl.Rows[i]["ExpenseDate"];
   objRow.Cells[3].AddText( strBillable, objParam, Missing.Value );
   objRow.Cells[4].AddText( objPdf.FormatDate( dt, "%d %b %Y" ), objParam, Missing.Value );

   float fAmount = Decimal.ToSingle( (Decimal)tbl.Rows[i]["Amount"] );
   objParam.Add( "alignment=right" );
   objRow.Cells[5].AddText( objPdf.FormatNumber( fAmount, "precision=2, delimiter=true"), objParam, Missing.Value );

// Render table on document, add pages as necessary
IPdfPage objPage = objDoc.Pages.Add(612, 150, Missing.Value);

objParam["x"].Value = (objPage.Width - objTable.Width) / 2; // center table
objParam["y"].Value = objPage.Height - 20;
objParam["MaxHeight"].Value = 100;

int nFirstRow = 2; // use this to print record count on page
while( true )
   // Draw table. This method returns last visible row index
   int nLastRow = objPage.Canvas.DrawTable( objTable, objParam );

   // Print record numbers
   objTextParam["x"].Value = (objPage.Width - objTable.Width) / 2;
   objTextParam["y"].Value = objPage.Height - 5;
   String strTextStr = "Records " + (nFirstRow - 1) + " to " + (nLastRow - 1) + " of " + (objTable.Rows.Count - 1 );

   objPage.Canvas.DrawText( strTextStr, objTextParam, objDoc.Fonts["Courier-Bold", Missing.Value] );

   if( nLastRow >= objTable.Rows.Count )
      break; // entire table displayed

   // Display remaining part of table on the next page
   objPage = objPage.NextPage;
   objParam.Add( "RowTo=1; RowFrom=1" ); // Row 1 is header
   objParam["RowFrom1"].Value = nLastRow + 1; // RowTo1 is omitted

   nFirstRow = nLastRow + 1;

Click the links below to run this code sample:

http://localhost/asppdf/manual_07/07_db.aspx  Why is this link not working?

Chapter 8: Security Chapter 6: Text and Fonts

  This site is owned and maintained by Persits Software, Inc. Copyright © 2003 - 2013. All Rights Reserved.