ASP: Create pdf files with FPDF

One interesting thing you can do in a web site or application is to present reports directly in pdf format. If you have a database from which you pull data, you can manipulate the information and create a pdf file on the fly. FPDF is a PHP class created by Olivier PLATHEY, but a wise guy named Lorenzo Abbati translated it for asp. The class is completely free for commercial and non commercial use, and has almost everything you need to build up your pdf document. The problem is that Lorenzo has his web page and all the related documentation in Italian. You can always refer to the original PHP version of the class in order to understand in depth how it works. Here I will only scratch the surface and explain the basics.
*** Important Note: it seems that as of the end of November 2011, the site hosting the FPDF library is gone dead. That's quite sad, because of the lost files and related documentation on how to use it. For now, I will leave the links on this page, hoping that they will get back somehow, for reference. If someone would like to host the files or already is distributing the library, please let me know so that I can insert the working link. In the meantime, if you need help, contact me directly, sending me an email. ***
*** Second important note: while the FPDF asp site is waiting to be republished (in January 2012 the site is under construction) one great user named bcsite decided to host the files on www.inforemax.com/fpdf.zip. Many thanks for his/her valuable help! ***

First of all download the class and extract the files in a folder of your web site. The folder (we call it "public") must have read and write permissions: that is because the pdf file will be saved (temporarily) on the server.
Create a new .asp page and insert all the code needed to retrieve eventual data from your database. Then, include the class:
At this point we need to initialize the pdf file, setting some parameters:
<%
Set pdf=CreateJsObject("FPDF")
pdf.CreatePDF "P","mm","A4"
pdf.SetPath("fpdf/")
pdf.SetFont "Arial","",12
pdf.Open()
The main difference between the use of the class in VBScript and JavaScript is in the CreateJsObject command, which is used in VBScript. For JavaScript you need to use var pdf = new FPDF();
In our examples we will consider VBScript as our preferred language.
CreatePDF initializes the class with 3 parameters: orientation, measure unit, format. Orientation might be "P" for portrait or "L" for landscape. Measure unit accepts pt (for points), mm (for millimeters), cm (for centimeters) and in (for inches). Format might be A3, A4, A5, Letter, Legal or an bidimensional array containing width and height (expressed in the aforementioned measure unit).
SetPath sets the relative or virtual path of the fpdf folder (where all the includes, extends, fonts and models folders are located).
We use SetFont for setting the font of the document and its size - SetFont(string family [, string style [, float size]]).
Open starts the generation of the document, but at this point nothing is actually produced. We need to start inserting stuff:
pdf.AddPage()
pdf.Image "head.jpg",5,5,201,0
The AddPage() command inserts a new page. It accepts a string orientation in the form of "P" or "L", otherwise it will take the default orientation given by the CreatePDF command.
In the example above, we insert an image called "head.jpg". The command syntax is: Image(stringfile, float x, float y, float w [, float h [, string type [, mixed link]]])
The image types supported are JPG and PNG.
Now we go on and insert new elements:
pdf.SetXY 95,13
pdf.setfillcolor 255,255,255
pdf.Cell 55,5,"HELLO!",1,0,,1
First of all, we set the inserting position to a specific point on the page, with SetXY(float x, float y). Then we set the fill colour with SetFillColor(int r [, int g, int b]) because we want to determine the fill colour of any cell or box created afterwards. Infact we insert a cell with the command Cell(float w [, float h [, string txt [, mixed border [, int ln [, string align [, int fill [, mixed link]]]]]]]). In the given example the cell is 55 in width, 5 in height, it contains the text "HELLO!", the cell has a border ("1"), it is alligned to the right ("0" right, "1" at the beginning of a new line and "2" at the bottom), default as string aligment (possible values are "L", "C" and "R") and finally the fill must be drawned ("0" would be transparent).
The string can be replaced with anything you like, from a variable to a value of your recordset. You can also use a simple repeated region to display records from a database.

Wow! That was hard! Now let's go on...
pdf.SetXY 8,156
pdf.setfillcolor 197,198,200
pdf.MultiCell 40,4,"Hello!",0,0,1
After changing position and fill colour, we create a MultiCell. A MultiCell has the same parameters as Cell, but it can contain text with line breaks. Those line breaks could be automatic (when the text reaches the cell width) or explicit (with /n). MultiCell(float w, float h, string txt [, mixed border [, string align [, int fill]]]).
As you can see all the objects can be placed whereever you need them to be, and if you use the SetXY command, you don't really need to follow the document natural flow. Infact you can add objects at the end of a page, and afterwards, get back adding an image at the top of it.
After inserting all the needed elements, we can add new pages and elements, but eventually we finish our work. So we close the document and create it:
pdf.Close()
filewrite=Server.MapPath("/public/mypdf.pdf")
pdf.Output filewrite
The close command closes the document (ah!). Then we set the filewrite variable to be used with the Output command. This is the tricky part and I remember I played a lot with it. The Output command is Output([string file [, boolean download]]) where file is the name of the file. If it is left blank the file will be opened by the browser, otherwise saved. If the file is specified, download could be "false" (the file is saved locally) or "true" (a "Save as" dialog will be opened). That gave me a lot of troubles, and so I decided to use the command as in the example. The file is actually saved in the public directory, and that might be a problem if you generate different files with dynamic names: infact your folder might be soon filled up with files you don't really need. So we just use a little trick to open the file in browser and then delete it from the server:
Response.ContentType = "application/x-unknown"
FPath = filewrite
fn = "mypdf.pdf"
Response.AddHeader "Content-Disposition","attachment; filename=" & fn

Set adoStream = CreateObject("ADODB.Stream")
adoStream.Open()
adoStream.Type = 1
adoStream.LoadFromFile(FPath)
Response.BinaryWrite adoStream.Read()
adoStream.Close
Set adoStream = Nothing
dim fs
Set fs=Server.CreateObject("Scripting.FileSystemObject")
    if fs.FileExists(server.mappath("/public/"&fn)) then
      fs.DeleteFile(server.mappath("/public/"&fn))
    end if
set fs=nothing

Response.End
%>
Basically with the above code, we open the pdf file in the browser (obviously a pdf plug-in or reader must be installed in the target computer) and then using the Scripting.FileSystemObject (which I explained in different older posts) we delete it.

I understand that I only explained the basic use of the FPDF class, but I believe that this starting point could make some of you more curious. Please visit the online documentation for further information (but remember it is in Italian).
Let me know what you think about it.