PDFLib: Tables

In our previous examples we were introduced to the PDFLib toolkit, discussed how to place blocks of text, and learned how to place images.  Now we will discuss arguably the most powerful feature of the PDFLib toolkit; tables.  With the ability to place text, images, and tables will have everything we need to make professional PDFs for a variety of purposes. 

We will start with the base set of code needed to initiate the document and load our fonts.  Here I am loading and Arial and an Arial Bold font.  I am also initiating the document and creating a letter sized page. 

 

Here we can begin the process of making a simple table and placing some text in it.  It should be noted that while there is a way to place text using textlines, we will only be discussing how to place text using textflows.  The textline method is much less intuitive and the textflow option is much more flexible.  

 

What we are doing here is creating a textflow with the text “The Centered Title” with a font size of 12 in the Arial Bold font.  We then create an optlist for the table specifying a margin of one.  We also specify that we will be placing the textflow with the reference to the textflow we just created.  With the fittextflow option we can specify an optlist within this optlist that contains any of the options from the fittextflow method that we want.  Note that I am using a double brace to specify the optlist for fittextflow.  This is because we are in the String.Format method and a double brace is the escape character for a brace in that string. 

Once we have done this we then add the table cell.  We specify -1 as the first parameter in order to initiate a new table.  Any new cells added to this same table would be added by calling the return from this function (in this case “table”).  We will see this shortly.  The second and third parameters are specify we are adding this text to column 1 and row 1.  The empty string for the fourth parameter is where we would normally put text if we were going to call fittextline.  Finally we apply the optlist for the table which in this case also contains our reference to the textflow we created earlier. 

We now need to place the table and save and close the document.  

 

We first specify an optlist for fitting the table.  At the moment we are only using the stroke option.  Stroke specifies which lines of the table should be drawn.  We can use it to specify specific horizontal and vertical lines as well as specify the width, color, and pattern of those lines. In this case we are using the frame option which means we want the outer lines of the table drawn.  In the call to fit_table, the first parameter is the reference to the table we want to place.  The next four are the lower left x and y coordinates and the upper right x and y coordinates.  The final option is the optlist which here is only specifying that we want to draw the frame of the table.  The output is below. 

  

We see that we get a 1 by 1 table that takes up the entirety of the page.  There is now row height specified so the fit_table method takes up the entire allowable space.  If we specify a rowheight the table will adjust to only take up that much space.

 

 

 Now that we have the basic idea, let’s try to do something a little more complex.  We will make an invoice that has a product number, a name, a unit count, a unit price and a total.  The footer row will have an absolute total.  We will also apply some formatting to the table to make the lines look nice. 

First let’s create some classes that will represent the data we want to work with;

  

Each attribute of this InvoiceItem class will represent a column in the table.  The items that are ints or doubles are converted to strings here with the display attributes in order create textflows out of them.  The “C2” part of the ToString method is to format the unit costs and totals as currency with 2 decimal places.

  

Now we create a parent object that will allow us to add new line items very easily and as well as access the total.  Again we are creating a display version of the total so that we can create a textflow with it. 

We now want to initialize our data. 

 

This gives us a nice simple set of data to work with. Now we want to set up our headers. 

 This gives us 1 title row and 1 row with the column headers.  Not that in the title row I am using the option colspan=5 to indicate that this entry should span the entire row.  Now we will place the body rows. 

 We start with a “row” variable so that we can increment it after each line item.  This “row” variable is passed as the row parameter to the add_table_cell method.  The last cells we need to add are the footer cells. 

 

We first place a cell that spans 4 columns with the text “Total” that is right aligned.  We span 4 columns with the colspan=4 option.  Note that the cell will span 4 columns starting with the cell you specify.  Since we start at column 1 we will span from 1 to 4.  We then place the total of the entire invoice in the 5th column. 

The last thing we need to do is fit the table on the page. 

 

The default line width is 1.  When we supply the option of line=frame we are saying that the top, bottom, far left, and far right lines should be drawn with a width of 1.  The vertother and horother lines are used to specify any lines we have not specified up until now.  Note that the nice thing about being able to span columns is that vertical lines will not cross cells that span multiple columns.  The same holds true for horizontal lines crossings cells that span multiple rows.  

The final result looks like the following. 

 We now have the ability to create useful, functional tables.  In the next post we will work through a more sophisticated example that will combine everything we have learned up until now.