Baby Steps
The first thing you need to do is download iTextSharp, from here
Alternatively, you can NuGet them by right-clicking your project, selecting "Manage NuGet Packages" and then searching for and installing (may as well install all four, listed below).
At the time of updating this article (March 2016) the latest release was 5.5.8.0
You then need to add the following DLLs to your Visual Studio project (via References > Add References...):
- itextsharp
- itextsharp.pdfa
- itextsharp.xmlworker
- itextsharp.xtra
You may not need all of these assemblies for simple usage, but those are what I have and, even if you don't need them all right away, you probably will eventually.
Toddler Wobblings
Now here's the basis for a method that will generate a PDF file:
try
{
using (var ms = new MemoryStream())
{
using (var doc = new Document(PageSize.A4, 25, 25, 25, 25))
{
using (var writer = PdfWriter.GetInstance(doc, ms))
{
doc.Open();
doc.Close();
}
var bytes = ms.ToArray();
String PDFFileName = String.Format("AlwaysTheTwainShallMeet_{0}.pdf",
DateTime.Now.ToShortTimeString());
PDFFileName = PDFFileName.Replace(":", "_");
var testFile = Path.Combine(Environment.GetFolderPath
(Environment.SpecialFolder.Desktop), PDFFileName);
File.WriteAllBytes(testFile, bytes);
MessageBox.Show(String.Format("{0} written", PDFFileName));
}
}
}
catch (DocumentException dex)
{
MessageBox.Show(String.Format("DocumentException: {0}", dex.Message));
throw (dex);
}
catch (IOException ioex)
created (just try it again if that happens, or change the name of the file to include seconds also)
{
MessageBox.Show(String.Format("IOException: {0}", ioex.Message));
throw (ioex);
}
catch (Exception ex)
{
String exMsg = ex.Message;
MessageBox.Show(String.Format("General Exception: {0}", ex.Message));
}
Twainiacs of the Galaxy Unite!
This will compile, but won't do anything (good), as we've added no code to generate anything on the PDF file yet. We will now build up the file, step-by-step, until we have one that looks like this:
First, we want to declare some fonts that we will use. Add these, for instance:
Font times16BoldCyan = FontFactory.GetFont(FontFactory.TIMES_BOLD, 16, BaseColor.BLUE);
Font courier11BoldYellow = FontFactory.GetFont(FontFactory.COURIER_BOLD, 11, BaseColor.YELLOW);
Font helvetica9 = FontFactory.GetFont(FontFactory.HELVETICA, 9, BaseColor.BLACK);
Font LinkFont = FontFactory.GetFont(FontFactory.HELVETICA, 9,
iTextSharp.text.Font.UNDERLINE, BaseColor.BLUE);
Now, we can add the title line by creating a Paragraph, passing it the text and the font we want to use, and then adding it to the doc:
Paragraph twainBibText = new Paragraph("Mark Twain - Concise Book Bibliography", times16BoldCyan);
doc.Add(twainBibText);
Go ahead and run it, if you want; you should see that text on the PDF file.
Next, we'll add the verbiage about reading Twain books online. This requires combining two elements (a "Chunk" and an "Anchor") in a Paragraph. That can be done this way:
Chunk chunkTwainCentral = new Chunk("Read selected Twain works online - annotated,
with color-coded dialog, ", helvetica9);
Anchor anchorTwainCentral = new Anchor("hyar", LinkFont);
anchorTwainCentral.Reference = "http://twaincentral.azurewebsites.net/";
Paragraph parTwainCentral = new Paragraph();
parTwainCentral.Add(chunkTwainCentral);
parTwainCentral.Add(anchorTwainCentral);
doc.Add(parTwainCentral);
And now for another, similar, line that combines a Chunk and an Anchor:
Chunk chunkTwainRes = new Chunk("Download a free novel about Samuel Clemens (Mark Twain) ", helvetica9);
Anchor anchorTwainRes = new Anchor("rot cheer", LinkFont);
anchorTwainRes.Reference =
"http://www.lulu.com/shop/blackbird-crow-raven/the-resurrection-of-samuel-clemens/ebook/product-17541930.html";
Paragraph parTwainRes = new Paragraph();
parTwainRes.Add(chunkTwainRes);
parTwainRes.Add(anchorTwainRes);
doc.Add(parTwainRes);
Now let's add some heading text for the Twain bibliography. A good way to do that is to create a table, and then add cells to that table, like so:
PdfPTable tblHeadings = new PdfPTable(3);
tblHeadings.WidthPercentage = 80;
tblHeadings.SpacingBefore = 10f;
float[] headingRowWidths = new float[] { 300f, 100f, 600f };
tblHeadings.SetWidths(headingRowWidths);
tblHeadings.HorizontalAlignment = Element.ALIGN_LEFT;
Phrase phraseYear = new Phrase("Year of Publication", courier11BoldYellow);
PdfPCell cellYear = GetCellForBorderedTable(phraseYear, Element.ALIGN_CENTER, BaseColor.BLUE);
tblHeadings.AddCell(cellYear);
Phrase phraseblankHeading = new Phrase();
PdfPCell cellBlankSectionHeading = new PdfPCell(phraseblankHeading);
cellBlankSectionHeading.BorderWidth = 0;
tblHeadings.AddCell(cellBlankSectionHeading);
Phrase phraseTitle = new Phrase("Title", courier11BoldYellow);
PdfPCell cellTitle = GetCellForBorderedTable(phraseTitle, Element.ALIGN_CENTER, BaseColor.BLUE);
tblHeadings.AddCell(cellTitle);
doc.Add(tblHeadings);
I won't go into detail about what this code does, because either you're like me, and don't really care as long as it works, or you are a "real programmer" and can figure it out by reading it.
Note, that there is also a helper method, namely GetCellForBorderedTable()
. That is:
private static PdfPCell GetCellForBorderedTable(Phrase phrase, int align, BaseColor color)
{
PdfPCell cell = new PdfPCell(phrase);
cell.HorizontalAlignment = align;
cell.PaddingBottom = 2f;
cell.PaddingTop = 0f;
cell.BackgroundColor = color;
cell.VerticalAlignment = PdfPCell.ALIGN_CENTER;
return cell;
}
Now let's add some more single-row tables, and the values for them. We can do that this way:
PdfPTable tblIARow = new PdfPTable(3);
tblIARow.WidthPercentage = 80;
tblIARow.SpacingBefore = 4f;
float[] IARowWidths = new float[] { 300f, 100f, 600f };
tblIARow.SetWidths(IARowWidths);
tblIARow.HorizontalAlignment = Element.ALIGN_LEFT;
Phrase phrase1869 = new Phrase("1869", helvetica9);
PdfPCell cell1869 = GetCellForBorderedTable(phrase1869, Element.ALIGN_CENTER, BaseColor.GREEN);
tblIARow.AddCell(cell1869);
Phrase phraseblankIARow = new Phrase();
PdfPCell cellBlankIARow = new PdfPCell(phraseblankIARow);
cellBlankIARow.BorderWidth = 0;
tblIARow.AddCell(cellBlankIARow);
Anchor anchorIA = new Anchor("The Innocents Abroad, or The New Pilgrim's Progress", LinkFont);
anchorIA.Reference = "http://www.amazon.com/exec/obidos/ASIN/1619492350/garrphotgall-20";
Paragraph parIA = new Paragraph();
parIA.Add(anchorIA);
tblIARow.AddCell(parIA);
doc.Add(tblIARow);
Keep adding code like this, and you will eventually have created one like the one showed earlier.
Note: I used a Green background for nonfiction books, and Yellow for fiction. Otherwise, the only difference is in the name of the controls, the label displayed (year and title), and the URL.
Exercise Is Good For You (Just ask Mike Daniels if you don't believe me)
The nigh-obligatory exercise left to the dear and gentle reader: Change the "Twain Central" Chunk/Anchor Paragraph to display the word "color-coded" in various colors. Hint: you're not restricted to the handful of colors that iTextSharp declares; you can create custom colors like this: var lightGreen = new BaseColor(204, 255, 204);