The code of today shows how to add lists, horizontal lines, how to create PDF-document in memory and how to add page numbers! Sounds good? Okay, let's get to it!
protected void btnCreatePdf_Click(object sender, EventArgs e)
{
try
{
// set the file name
string file = "C:/pdf/MyPdf.pdf";
// create a pdf document
Document document = new Document();
// set the page size, set the orientation
document.SetPageSize(PageSize.A4.Rotate());
// create a writer instance - the document will be kept in memory
MemoryStream pdfStream = new MemoryStream();
PdfWriter pdfWriter = PdfWriter.GetInstance(document, pdfStream);
// open the document
document.Open();
// define fonts
Font titleFont = FontFactory.GetFont("Helvetica", 14, Font.BOLD, new iTextSharp.text.BaseColor(0, 179, 212));
Font textFont = FontFactory.GetFont("Helvetica", 9, Font.NORMAL, BaseColor.BLACK);
// create a paragraph and add it to the document
Paragraph title = new Paragraph("This PDF-document was created using iTextSharp!");
title.Font = titleFont;
title.IndentationLeft = 50f;
document.Add(title);
// add line below title
LineSeparator line = new LineSeparator(1f, 100f, BaseColor.BLACK, Element.ALIGN_CENTER, -1);
document.Add(new Chunk(line));
// add list
string[] listItems = new string[] { "item one", "item two", "item three" };
List list = new List(List.UNORDERED, 10f);
list.SetListSymbol("\u2022");
list.IndentationLeft = 15f;
foreach (string listItem in listItems)
{
list.Add(new iTextSharp.text.ListItem(listItem, textFont));
}
document.Add(list);
// close the document
pdfWriter.CloseStream = true;
document.Close();
// add page numbers
Document copyDoc = new Document();
PdfCopy copyPdf = new PdfCopy(copyDoc, new FileStream(file, FileMode.Create));
copyPdf.SetPageSize(PageSize.A4.Rotate());
copyDoc.Open();
// read the initial pdf document
PdfReader reader = new PdfReader(pdfStream.ToArray());
int totalPages = reader.NumberOfPages;
PdfImportedPage copiedPage = null;
iTextSharp.text.pdf.PdfCopy.PageStamp stamper = null;
for (int i = 0; i < totalPages; i++)
{
// get the page and create a stamper for that page
copiedPage = copyPdf.GetImportedPage(reader, (i + 1));
stamper = copyPdf.CreatePageStamp(copiedPage);
// add a page number to the page
ColumnText.ShowTextAligned(stamper.GetUnderContent(), Element.ALIGN_CENTER, new Phrase((i + 1) + "/" + totalPages, textFont), 820f, 15, 0);
stamper.AlterContents();
// add the altered page to the new document
copyPdf.AddPage(copiedPage);
}
copyDoc.Close();
reader.Close();
// flush and clear the document from memory
pdfStream.Flush();
pdfStream.Close();
// open the pdf document
Process.Start(file);
}
catch (Exception)
{
lblError.Text = "An error ocurred, the PDF-document could not be created.";
}
}
To add a horizontal line in your PDF-document, you could use a graph or a table but the easiest way is to use the LineSeparator-object. You can set the width of the line, the size in percentage, the color, the alignment and the offset.
To add a list you can use the List and ListItem objects. You can create an ordered or unordered list and use different symbols for the list or even roman numbering. The font for the list should be set at the list item level.
To create you PDF-document in memory instead of saving it to a file, you need to use MemoryStream instead of FileStream. In this example you can find code for how to use both options. I combined them to create two documents but create only one file. If you create the document in memory, make sure to flush and close the stream afterwards.
And finally, the hardest one, page numbering. iTextSharp makes it possible to add repeated content to your document, such as footers, headers or page numbers. But this can only be done after the current page number and the total number of pages is known. So one of the possibilities to implement page numbering is to create a new document in which you copy the pages of the original document. As you copy the pages the page numbers are calculated and added.
You'll use the PageStamp object to add a ColumnText to the existing page before you copy it. This ColumnText-object will allow you to add text at an absolute position. You can set the x and y postition and also a rotation. The GetUnderContent defines that you want to write under the original content. If you want to write over the original content, you should use GetOverContent. Finally, use AlterContents() to make the change and AddPage to add the page to the new document.
So that was it! Here you can find my code and the resulting PDF-document.
// add line below title
LineSeparator line = new LineSeparator(1f, 100f, BaseColor.BLACK, Element.ALIGN_CENTER, -1);
document.Add(new Chunk(line));
To add a list you can use the List and ListItem objects. You can create an ordered or unordered list and use different symbols for the list or even roman numbering. The font for the list should be set at the list item level.
// add list
string[] listItems = new string[] { "item one", "item two", "item three" };
List list = new List(List.UNORDERED, 10f);
list.SetListSymbol("\u2022");
list.IndentationLeft = 15f;
foreach (string listItem in listItems)
{
list.Add(new iTextSharp.text.ListItem(listItem, textFont));
}
document.Add(list);
To create you PDF-document in memory instead of saving it to a file, you need to use MemoryStream instead of FileStream. In this example you can find code for how to use both options. I combined them to create two documents but create only one file. If you create the document in memory, make sure to flush and close the stream afterwards.
MemoryStream pdfStream = new MemoryStream();
PdfWriter pdfWriter = PdfWriter.GetInstance(document, pdfStream);
string file = "C:/pdf/MyPdf.pdf";
PdfCopy copyPdf = new PdfCopy(copyDoc, new FileStream(file, FileMode.Create));
And finally, the hardest one, page numbering. iTextSharp makes it possible to add repeated content to your document, such as footers, headers or page numbers. But this can only be done after the current page number and the total number of pages is known. So one of the possibilities to implement page numbering is to create a new document in which you copy the pages of the original document. As you copy the pages the page numbers are calculated and added.
You'll use the PageStamp object to add a ColumnText to the existing page before you copy it. This ColumnText-object will allow you to add text at an absolute position. You can set the x and y postition and also a rotation. The GetUnderContent defines that you want to write under the original content. If you want to write over the original content, you should use GetOverContent. Finally, use AlterContents() to make the change and AddPage to add the page to the new document.
// add page numbers
Document copyDoc = new Document();
PdfCopy copyPdf = new PdfCopy(copyDoc, new FileStream(file, FileMode.Create));
copyPdf.SetPageSize(PageSize.A4.Rotate());
copyDoc.Open();
// read the initial pdf document
PdfReader reader = new PdfReader(pdfStream.ToArray());
int totalPages = reader.NumberOfPages;
PdfImportedPage copiedPage = null;
iTextSharp.text.pdf.PdfCopy.PageStamp stamper = null;
for (int i = 0; i < totalPages; i++)
{
// get the page and create a stamper for that page
copiedPage = copyPdf.GetImportedPage(reader, (i + 1));
stamper = copyPdf.CreatePageStamp(copiedPage);
// add a page number to the page
ColumnText.ShowTextAligned(stamper.GetUnderContent(), Element.ALIGN_CENTER, new Phrase((i + 1) + "/" + totalPages, textFont), 820f, 15, 0);
ColumnText.ShowTextAligned(stamper.GetUnderContent(), Element.ALIGN_CENTER, new Phrase("test"), 1f, 1f, 1f);
stamper.AlterContents();
// add the altered page to the new document
copyPdf.AddPage(copiedPage);
}
copyDoc.Close();
reader.Close();
So that was it! Here you can find my code and the resulting PDF-document.
To be continued!
At copyDoc.Close() I got a NullReference error. Turns out I made a typo and so I was opening the PdfWriter instead of the PdfDocument, the reason why you should give two objects such a similar name... So my document remained closed as I added content to it, when I tried to close it, there was nothing to close so it threw an error. Stupid but honest mistake since the PdfWriter has an Open()-method as well. So, hopefully this can be useful to someone making the same mistake :)
Could be useful, right?
Thank you so much! this is an absolute awesome example! i wanted to use memory streams and first create the whole document, then read it into a temp stream and then add the page numbers and close it...this example helped me a lot in achieving exactly that:) thanx
ReplyDeleteAwesome post!!! Two thumbs up
ReplyDelete