In this post, I want to share some of my experience in generating PDF documents using Aspose.PDF for .NET and introduce basic render techniques.
As an example, I chose a frequently used document - an invoice. Our document will consist of 5 sections:
- header section - contains the corporate logo and general info;
- address section - contains the info about the seller and the customer;
- grid section - contains the table of product items and the totals subsection;
- terms section - contains the list of strings for additional;
- footer - optional section with one string that placed at the bottom of the page.
Disclaimer: please note, that Apose.PDF is a paid product, but a trial version is fully appropriate to make some experiments like creating a document up to 4 pages.
Step 0. Creating a model of the document. For convenient work, we will create several classes for describing invoice details.
LogoImage will be used for a render company logo in the upper left corner.
TotalRow will be used for render row in totals subsection.
ProductItem represent one product item in the grid section.
And the last class will be used to represent a PDF document.
Step 1. Writing a simple application for testing. In this console application, we create the invoice with
C:\aspose\company-logo-design.png as logo image, 3 product items, some comments, and demo footer.
Step 2. Rendering the header section. The Aspose.PDF library provides several ways to place elements in the document. The simplest way to place a sequence of elements with minimal settings is by using the Document Object Model. According to this conception, Document object contains a collection of the Page objects. This collection, in turn, contains a collection of BaseParagraph objects. Descendants of BaseParagraph is TextFragment, FloatingBox, Table etc.
We will use TextFragment object to place lines "Invoice", "DATE:" and "DUE DATE". The first line will be centered, and the rest is right-aligned. Logo image breaks the hierarchy of DOM elements and must be placed in the upper left corner, so to place the logo we will apply another technique - adding a resource to the page. The detailed explanation of using resources is not the aim of this post. We will return to this technique in the future posts. In short, we complete the following steps:
- Add image to Images collection of Page Resources
- Save current graphics state
- Define a Matrix object for placing the image in the appropriate location
- Apply matrix to the image
- Restore graphics state
Following snippet contains the full implementation of the
Step 3. Rendering the address section. We apply the two-column layout with mirror alignment: the left column is left-aligned and the right column is right-aligned. Such fragments can be easily rendered with FloatingBox class. To perform this layout we need to complete 4 steps:
- Create an object of the FloatingBox class;
- Add text fragments to the left column;
- Add 1 text fragment to the to the right column with properties
HorizontalAlignment = HorizontalAlignment.Right;
- Add the rest fragments to the right column with the right alignment.
The following snippet shows these steps:
Step 4. Rendering the grid section. We will use the Table object to represent data in tabular format. First, we need to define table columns and default decoration of cells. Please, note that
ColumnWidths property implicit define number of columns by setting their widths. In our grid, we will use an inverse color scheme for header rows. The following algorithm is used to create table rows:
table.Rows.Add()to create the row and get the reference to the new row;
row.Cells.Add()to create each cell and get the reference to the new cell;
- Set cell decoration if needed;
The totals subsection is created similarly, but for the better view, we join up the 4 first cells by using
Step 5. Rendering
Terms and Conditions section.
This section contains only text fragments, and their rendering is the same as described above.
Step 6. Rendering Footer section
According to previously declared layout, the last section is optional and must be placed at the bottom of the page. That is mean we can't use adding the text fragment to the paragraph collection because this adding placed our fragment already after the 'Terms and Conditions' section.
In this case, we need to use a TextBuilder class. This class helps us to place text in any location. Additionally, the following snippet shows how we can add a hyperlink to the text fragment.
In this post, we considered how to create a simple PDF document from scratch. Most of the parameters such as font size, the width of the cell's border, column's width in the table are adjusted manually based on A4 page size.
It's obvious that we are able to tune these parameters in proportion to the size of the page, but this will slightly complicate the example, but will not change the technique of creating the document as a whole.
A fundamentally different approach is working with some template and replacing part of the content.