Saturday, November 26, 2011

Getting Started with iTextSharp


For the ASP.NET developers out there, if you need to generate PDF reports from your code, there is an open source library called iText# (iTextSharp) that is worth checking out. iTextSharp is a port of the Java iText library written entirely in C#. Source and binaries are available at http://sourceforge.net/projects/itextsharp/.

From what I’ve seen, it works well and only requires one .dll to be copied to your bin directory. Unfortunately, there is no documentation with the product, so I’ll share some of the code I used for a proof of concept that should hopefully get you started.

Using Visual Studio 2005 or greater, or your favorite text editor, create a page with a label called Label1 and a button called Button1. You can skip the label if you want, as I just used it to dump exception output, but I do have it referenced in code. The example will work with any of the Express (free) versions of Visual Studio as well.

First of all, ensure your page has references to ITextSharp.text, ITextSharp.text.PDF, System.IO, and System.Text.

In Button1’s Click event handler, add the following code. My comments appear within square brackets inside the code:

Dim doc As New iTextSharp.text.Document(PageSize.LETTER, 10, 10, 10, 10)

[Here is where you declare the page size and margins.]

Dim output As New MemoryStream()

[You can generate the output directly to a file, but, for demonstration purposes, I just used a MemoryStream object. Note that if you generate your output to a file, you will require write permission on the server in the directory where you want to place your PDF files, otherwise you will get a SecurityException.]

Dim logo As iTextSharp.text.Image
Dim bTest As Boolean
Dim par As Paragraph
Dim tbl As PdfPTable
Dim widths As Single() = {1.3, 1.3}
Dim bfHelvetica As BaseFont = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, False)

[I found the choices of fonts quite limiting, in contrast to the FPDF library I’ve used in PHP at www.whahof.com.]

Dim cb As PdfContentByte
Dim titleFont As iTextSharp.text.Font = New Font(bfHelvetica, 14, Font.BOLD, iTextSharp.text.BaseColor.BLACK)
Dim bodyFont As iTextSharp.text.Font = New Font(bfHelvetica, 10, Font.NORMAL, iTextSharp.text.BaseColor.BLACK)
Dim smallFont As iTextSharp.text.Font = New Font(bfHelvetica, 8, Font.NORMAL, iTextSharp.text.BaseColor.BLACK)

Try
    Label1.Text = String.Empty
    Dim instance As PdfWriter = PdfWriter.GetInstance(doc, output)
    Dim ev As New itsEvents
    instance.PageEvent = ev
    doc.Open()
    cb = instance.DirectContent

    doc.AddAuthor("Curtis Walker")
    doc.AddTitle("This is a test PDF")

[In your PDF, these values will appear under Document Properties. It’s optional, but if you want to add a professional touch, it’s a good idea.]

     par = New Paragraph("Test paragraph", titleFont)
     par.Alignment = 1 ' 1 is center, 0 is left, 2 is right
     doc.Add(par)

     par = New Paragraph(" ", smallFont)
     doc.Add(par)

      tbl = New PdfPTable(2) ' number of columns
      tbl.WidthPercentage = 30
      tbl.HorizontalAlignment = 1
      tbl.DefaultCell.BorderWidthTop = 1
      tbl.DefaultCell.BorderWidthLeft = 1
      tbl.DefaultCell.BorderWidthRight = 1
      tbl.DefaultCell.BorderWidthBottom = 0

[There is a “border” attribute, but I found that it just sets the top value, not all four values above.]

       tbl.SpacingAfter = 0
       tbl.SpacingBefore = 0
       tbl.SetWidths(widths)
       tbl.AddCell(New Phrase("test", bodyFont))
       tbl.AddCell(New Phrase("test2", bodyFont))
       tbl.AddCell(New Phrase("test3", bodyFont))
       tbl.AddCell(New Phrase("test4", bodyFont))
       tbl.AddCell(New Phrase("test5", bodyFont))
       tbl.AddCell(New Phrase("test6", bodyFont))
       tbl.AddCell(New Phrase("test7", bodyFont))
       tbl.AddCell(New Phrase("test8", bodyFont))

       doc.Add(tbl)

       logo = iTextSharp.text.Image.GetInstance(Server.MapPath("~/images/thrashers.jpg"))

[You can pick any image on your server.]

       logo.SetAbsolutePosition(100, doc.PageSize.Height - 100)

[Strangely, the second value is distance from the bottom of the page, not the top. Setting the value to “0” puts it at the bottom.]

        logo.ScaleAbsolute(100, 100)
        bTest = doc.Add(logo)

        doc.NewPage()

        par = New Paragraph("test item on second page", titleFont)
        doc.Add(par)

        doc.Close()

         Response.ContentType = "application/pdf"
         Response.AddHeader("Content-Disposition", "Output.pdf")
         Response.BinaryWrite(output.ToArray())

  Catch ex As Exception
     Label1.Text = ex.Message
  End Try

After the page class, insert the following class that handles the page header and footer events.

Public Class itsEvents
        Inherits PdfPageEventHelper

        Private bfHelvetica As BaseFont = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, False)
        Private smallFont As iTextSharp.text.Font = New Font(bfHelvetica, 8, Font.NORMAL, iTextSharp.text.BaseColor.BLACK)

        Public Overrides Sub OnStartPage(ByVal writer As iTextSharp.text.pdf.PdfWriter, ByVal document As iTextSharp.text.Document)
            Dim cb As PdfContentByte

            cb = writer.DirectContent

            cb.BeginText()
            cb.SetFontAndSize(bfHelvetica, 8)
            cb.SetTextMatrix(30, document.PageSize.Height - 30)
            cb.ShowText("Test header on page " + writer.PageNumber.ToString)
            cb.EndText()

            cb.MoveTo(30, document.PageSize.Height - 35)
            cb.LineTo(document.PageSize.Width - 40, document.PageSize.Height - 35)
            CB.Stroke()
        End Sub

        Public Overrides Sub OnEndPage(ByVal writer As iTextSharp.text.pdf.PdfWriter, ByVal document As iTextSharp.text.Document)
            Dim cb As PdfContentByte

            cb = writer.DirectContent

            cb.BeginText()
            cb.SetFontAndSize(bfHelvetica, 8)
            cb.SetTextMatrix(30, 30)
            cb.ShowText("Test footer on page " + writer.PageNumber.ToString)
            cb.EndText()

            cb.MoveTo(30, 40)
            cb.LineTo(document.PageSize.Width - 40, 40)
            cb.Stroke()
        End Sub
    End Class

You should be set to build your project and run the page. Click the button and you should get a PDF file coming up in your browser. Once I found the code, I found that it went pretty smoothly.

If you want to deploy the isharptext.dll and your code to a host on a shared plan, you may run into trouble. The pre-built .dll is strongly typed and though your code may have worked locally, you may get an error message about not allowing partially trusted callers.

After doing a little research, I found that all you have to do is recompile the source using Visual Studio 2005 and adding the following lines to assembly.cs:

using System.Security;
[assembly:AllowPartiallyTrustedCallers]

Using this rebuilt .dll, everything worked on my hosting provider just as it did locally under both IIS and the lightweight development Web Server provided with the .NET SDK that is most often installed with Visual Studio. For my example, click here.

I’ve just scratched the surface and there’s a lot more to do with this library, but this code should get you started in generating PDF files from your .NET application or Web site.

No comments:

Post a Comment