Hi there, been a while since my last post..
Today i will show how to create "on the fly" PDF files. I used this for an web application where users have a "personal" PDF file in their mailbox.
There are many library's available for creating PDF files. This site will show a list of open source library's: csharp-source.net/open-source/pdf-libraries
Some of them i have tried:
Report.NET
SharpPDF
PDFsharp
but i think the easiest to use is iTextSharp.
The homepage of iTextSharp is: http://sourceforge.net/projects/itextsharp/ Here you can download the library, source code and examples.
Short description from the iTextSharp homepage:
"iText# (iTextSharp) is a port of the iText open source java library written entirely in C# for the .NET platform. iText# is a library that allows you to generate PDF files on the fly. It is implemented as an assembly."
The example project creates a large amount of PDF files to show what can be done with iTextSharp. You will have to comment a lot in order to get it working but after that it can come handy. This is because the examples project was build on an earlier version of iTextSharp.
Here are some tutorials for iTextSharp:
itextsharp.sourceforge.net/tutorial/index.html
www.aspfree.com/c/a/BrainDump/Working-with-iTextSharp/ ( found this while writing this article )
OK lets start Visual studio!
First we need to add a reference to the iTextSharp library:
references -> add reference -> browse -> select itextsharp.dll
Then we can include the following to our class:
using iTextSharp.text.pdf;
using iTextSharp.text;
and for file access:
using System.IO;
First we write the hello world with an image and some texts:
protected void Page_Load(object sender, EventArgs e)
{
//Create document A4
Document document = new Document(PageSize.A4);
//Start the writer
PdfWriter writer = PdfWriter.GetInstance(document, new FileStream("c:\\test.pdf", FileMode.Create));
//Open the document
document.Open();
//Set some document attributes
document.AddTitle("Hello world");
document.AddAuthor("Sjoerd Perfors");
document.AddSubject("This is my first PDF created on: " + DateTime.Now.ToShortDateString());
//Add an image
iTextSharp.text.Image image = iTextSharp.text.Image.GetInstance("c:\\caesar_coin.jpg");
document.Add(image);
//Add a normal text
document.Add(new Chunk("HELLO WORLD", FontFactory.GetFont(FontFactory.HELVETICA, 18, Color.RED)));
//Add text to a specific position
PdfContentByte cb = writer.DirectContent;
BaseFont bf = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
cb.BeginText();
cb.SetFontAndSize(bf, 12);
cb.ShowTextAligned(Element.ALIGN_RIGHT, "Another text placed on 100,400", 100, 400, 0);
cb.EndText();
//Close the document
document.Close();
}
See how easy it is?
Remember that the X and Y positions are calculated from the bottomleft and not from the topleft.
The following example shows how to create an table with 2 columns
TABLE IS DEPRECATED SEE MY NEW POST WITH A EXAMPLE USING PdfPTable
#region Example2
//Start table with 2 columns
iTextSharp.text.Table table = new iTextSharp.text.Table(2);
table.BorderWidth = 0;
table.Padding = 2;
//Set the withs for the columns to 10% and 90%
float[] headerwidths = { 10, 90 };
table.Widths = headerwidths;
table.Width = 100;
//Add first cell with colspan2
Cell firstCell = new Cell(new Chunk("Colspan Cell", FontFactory.GetFont(FontFactory.HELVETICA, 14, Color.BLACK)));
firstCell.Colspan = 2;
firstCell.VerticalAlignment = Element.ALIGN_TOP;
firstCell.BorderWidthBottom = 0.5f;
table.AddCell(firstCell);
//Add more cells
for (int i = 0; i < 10; i++)
{
Cell moreCells = new Cell(new Chunk("Cell "+ i.ToString() , FontFactory.GetFont(FontFactory.HELVETICA_OBLIQUE,12)));
moreCells.VerticalAlignment = Element.ALIGN_TOP;
moreCells.Colspan = 1;
moreCells.BorderWidth = 0.5f;
table.AddCell(moreCells);
}
//Add table to document
document.Add(table);
#endregion
To add some nice functions like page numbering or footers we have to create a new class which extends the class PdfPageEventHelper. This class has the following handy functions:
public virtual void OnChapter(PdfWriter writer, Document document, float paragraphPosition, Paragraph title);
public virtual void OnChapterEnd(PdfWriter writer, Document document, float position);
public virtual void OnCloseDocument(PdfWriter writer, Document document);
public virtual void OnEndPage(PdfWriter writer, Document document);
public virtual void OnGenericTag(PdfWriter writer, Document document, Rectangle rect, string text);
public virtual void OnOpenDocument(PdfWriter writer, Document document);
public virtual void OnParagraph(PdfWriter writer, Document document, float paragraphPosition);
public virtual void OnParagraphEnd(PdfWriter writer, Document document, float paragraphPosition);
public virtual void OnSection(PdfWriter writer, Document document, float paragraphPosition, int depth, Paragraph title);
public virtual void OnSectionEnd(PdfWriter writer, Document document, float position);
public virtual void OnStartPage(PdfWriter writer, Document document);
To use the functions we create a new class and overides above functions with out own code to create a nice footer:
public class PDFPageEvents: PdfPageEventHelper
{
PdfPTable table;
PdfTemplate tpl;
BaseFont helv;
public override void OnOpenDocument(PdfWriter writer, Document document)
{
table = new PdfPTable(2);
// initialization of the template
tpl = writer.DirectContent.CreateTemplate(100, 100);
tpl.BoundingBox = new Rectangle(-20, -20, 100, 100);
// initialization of the font
helv = BaseFont.CreateFont("Helvetica", BaseFont.WINANSI, false);
}
public override void OnEndPage(PdfWriter writer, Document document)
{
if (document.PageNumber == 1)
return;
PdfContentByte cb = writer.DirectContent;
cb.SaveState();
// write the headertable
float[] floatwidth = { (document.Right - document.Left) };
table.TotalWidth = 100;
//table.SetTotalWidth(floatwidth);
table.WriteSelectedRows(0, -1, document.Left, document.PageSize.Height - 50, cb);
// compose the footer
String text = "Page " + writer.PageNumber + " of ";
float textSize = helv.GetWidthPoint(text, 12);
float textBase = document.Bottom - 20;
cb.BeginText();
cb.SetFontAndSize(helv, 12);
float adjust = helv.GetWidthPoint("0", 12);
cb.SetTextMatrix(document.Right - textSize - adjust, textBase);
cb.ShowText(text);
cb.EndText();
cb.AddTemplate(tpl, document.Right - adjust, textBase);
cb.SaveState();
}
public override void OnCloseDocument(PdfWriter writer, Document document)
{
tpl.BeginText();
tpl.SetFontAndSize(helv, 12);
tpl.SetTextMatrix(0, 0);
tpl.ShowText("" + (writer.PageNumber - 1));
tpl.EndText();
}
}
Now in our previous example we add the following:
//Create document A4
Document document = new Document(PageSize.A4);
//Start the writer
PdfWriter writer = PdfWriter.GetInstance(document, new FileStream("c:\\test.pdf", FileMode.Create));
PDFPageEvents pageEvent = new PDFPageEvents();
writer.PageEvent = pageEvent;
//Open the document
document.Open();
document.Add(new Chunk("This is a new page WITHOUT page numbering."));
document.NewPage();
for (int i = 0; i < 5; i++)
{
document.Add(new Chunk("This is a new page WITH page numbering."));
document.NewPage();
}
//Close the document
document.Close();
In the next article i will descripe how to create an PDF in memory and mail this as an attachment.
Goodluck and big thanks for iTextSharp!