iTextSharp version 5

Why iText?

Updated 2012-02-08 - Added a bullet regarding using iTextSharp with a medium trust shared web hosting provider in the notes section.
How many times have you been asked to generate a report in an open file format such as PDF? iTextSharp, a free C# PDF library ported from the Java-PDF Library iText, gives you a nice option.

Important / Breaking Changes

Getting Started

In general creating a PDF with iText[Sharp] is a five-step process:
  1. Instantiate a Document object.
  2. Get an instance of the PdfWriter object.
  3. Open the Document instance.
  4. Add content to the Document instance.
  5. Close the document. As explained above you can omit step 5 from iTextSharp 5.0.6.
The following example shows how to:
  1. Create a centered, single-page document header. If you need to add page headers to all pages of your document see Adding PDF Page Headers, which shows the recommended method to add page headers using the PdfPageEventHelper class.
  2. Add a center-aligned image to the document.
  3. Add a center-aligned paragraph to the document.
  4. Add tabular formatted data to the document.

iTextSharp Versions 5 and Above

Creating our PDF going from step 1 through 4. Uncomment where specified (Document using statement) if using anything less than 5.0.6:
/* 
 * step 1
 * 
 * __ONLY__ if using version >= 5.0.6
 * see commented section directly below
 * 
 */
    using (Document doc = new Document()) {
    
/*
 * uncomment this line __AND__ comment out line above if you're
 * using version < 5.0.6
 * 
 * Document doc = new Document();
 * 
 */
    
// step 2
    PdfWriter writer = PdfWriter.GetInstance(doc, Response.OutputStream);

// step 3
    doc.Open();

// step 4
/*
 * create document header; shows GMT time when PDF created.
 * HeaderFooter class removed in iText 5.0.0, so we instead write 
 * content to an **absolute** position on the document
 */
    Rectangle page = doc.PageSize;
    PdfPTable head = new PdfPTable(1);
    head.TotalWidth = page.Width;
    Phrase phrase = new Phrase(
      DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss") + " GMT",
      new Font(Font.FontFamily.COURIER, 8)
    );    
    PdfPCell c = new PdfPCell(phrase);
    c.Border = Rectangle.NO_BORDER;
    c.VerticalAlignment = Element.ALIGN_TOP;
    c.HorizontalAlignment = Element.ALIGN_CENTER;
    head.AddCell(c);
    head.WriteSelectedRows(
      // first/last row; -1 writes all rows
      0, -1,
      // left offset
      0,
      // ** bottom** yPos of the table
      page.Height - doc.TopMargin + head.TotalHeight + 20,
      writer.DirectContent 
    );

/* 
 * add image to document
 */
    Image gif = Image.GetInstance(
      Request.MapPath("~/kyouyuu/image/kuujinbo2.gif")
    );
    gif.Alignment = Image.MIDDLE_ALIGN;
// downsize the image by specified percentage        
    gif.ScalePercent(50f);
    doc.Add(gif);

/*
 * add tabular data
 */
// table heading
    Paragraph p = new Paragraph("US Presidents Born in " + _state);
    p.Alignment = 1;
    doc.Add(p);
// table data, see code snippet following this one
    doc.Add( _stateTable() );

/*
 * step 5 is __REQUIRED__ if using version < 5.0.6; uncomment Close()
 * below and comment out the bracket below!
 * 
 * doc.Close();
 * 
 */
    }
Creating a simple table is easy; query the database (data access code omitted) and add each rowset to the table in the PDF:
// add a table to the PDF document
private PdfPTable _stateTable() {
  string[] col = { "No.", "Name", "City" };
  PdfPTable table = new PdfPTable(3);
/*
* default table width => 80%
*/  
  table.WidthPercentage = 100;
// then set the column's __relative__ widths
  table.SetWidths(new Single[] {1, 5, 4});
/*
* by default tables 'collapse' on surrounding elements,
* so you need to explicitly add spacing
*/
  table.SpacingBefore = 10;

  for (int i = 0; i < col.Length; ++i) {
    PdfPCell cell = new PdfPCell(new Phrase(col[i]));
    cell.BackgroundColor = new BaseColor(204, 204, 204);
    table.AddCell(cell);
  }

// !! database code omitted !!
// r.Read is the DbDataReader for whatever flavor 
// of database you're connecting to; we're iterating
// over the results returned from the database and 
// adding rows to the table in the PDF 
      while (r.Read()) {
        table.AddCell(r["id"].ToString());
        table.AddCell(r["name"].ToString());
        table.AddCell(r["city"].ToString());
      }
  }
  return table;
}  

Example for iTextSharp Versions Less Than 5.XX

Here's a stand-alone working HTTP handler that works with 4.1.6.
<%@ WebHandler Language='C#' Class='itext' %>
/*
 * example ONLY WORKS for iTextSharp < 5.0.0;
 * as of 2011-03-28 source code for older versions __NOT__ available
 */
using System;
using System.Web;
using iTextSharp.text;
using iTextSharp.text.pdf;

public class itext : IHttpHandler {
// ===========================================================================  
  public void ProcessRequest (HttpContext context) {
    HttpResponse Response = context.Response;
    Response.ContentType = "application/pdf";
    Response.AppendHeader(
      "Content-Disposition",
      "attachment; filename=itext.pdf"
    );
// step 1    
    Document doc = new Document();
    
// step 2    
    PdfWriter writer = PdfWriter.GetInstance(doc, Response.OutputStream);
       
/*
 * create document header; shows GMT time when PDF created.
 * set header [1] text [2] font style
 */        
    Phrase phrase = new Phrase(
      DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss") + " GMT",
      new Font(Font.COURIER, 8)
    ); 
    HeaderFooter header = new HeaderFooter (phrase, false);
// top & bottom borders on by default 
    header.Border = Rectangle.NO_BORDER;
// center header
    header.Alignment = 1;
/*
 * HeaderFooter => add header __before__ opening document
 */
    doc.Header = header;  
// step 3
    doc.Open(); 
      
// step 4
/* 
 * add image to document
 */
    Image gif = Image.GetInstance(
      "http://kuujinbo.info/kyouyuu/image/kuujinbo2.gif"
    );
    gif.Alignment = Image.MIDDLE_ALIGN;
// downsize the image by specified percentage    
    gif.ScalePercent(50f);
    doc.Add(gif);

/*
 * add tabular data
 */
// table heading
    Paragraph p = new Paragraph("Table Heading");
    p.Alignment = 1;
    doc.Add(p);
    
// table 'data'   
    Table table = new Table(3);
    table.BorderWidth = 1;
    table.BorderColor = new Color(0, 0, 255);
    table.Padding = 4;
    table.Width = 100;

    // set *column* widths
    float[] widths = {.3f, .5f, .4f};
    table.Widths = widths;

    string[] col = {"COL 1", "COL 2", "COL 3"};
    for (int i = 0; i < col.Length; ++i) {
      Cell cell = new Cell(col[i]);
      cell.Header = true;
      cell.BackgroundColor = new Color(204, 204, 204);
      table.AddCell(cell);
    }
    table.EndHeaders();
    
    for (int i = 1; i < 5; ++i) {
      for (int j = 0; j < col.Length; ++j) {
        table.AddCell(string.Format(
          "Row {0}, Cell {1}",
          i, j + 1
        ));
      }
    }
    doc.Add(table);
    
// step 5
    doc.Close();    
  }

  public bool IsReusable {
    get { return false; }
  }
// ===========================================================================
}

Notes

Don't forget to set the correct Content-Type before you send the PDF stream if you're running a web application:

Response.ContentType = "application/pdf";
// [optional]
Response.AddHeader(
  "Content-Disposition",
  "attachment; filename=itext.pdf"
);