本文转自:https://www.codeproject.com/Articles/686994/Create-Read-Advance-PDF-Report-using-iTextSharp-in
Contents
- Introduction
- Requirements
- Installation
- Creating PDF Document in 6 Steps
- Working with Page Size of PDF Document
- Setting Background Color of PDF Document
- Setting Page Margins of PDF Document
- Setting Text Alignment in PDF Document
- Setting Meta Information or Properties of a PDF Document
- Creating a Multipage Document
- Creating a New PDF Document from an existing PDF Document
- Adding Watermark to PDF Document using Layer
- Removing Watermark from the just created Watermarked Document by Removing Layer
- Adding Watermark to each Page during Creation
- Export/Print/Output the PDF File directly to the Client without saving it to the Disk
The following two contents are added in this updated version:
Introduction
Recently I was looking for an Advance Tool to create complex PDF Report in C#.Net and I found iTextSharp
. The main problem is that lacks of Documentation. Yes, there are a few examples in C#, but that is not sufficient to the Beginners and the examples are in older version of iTextSharp
, there are lots of change in the latest version. So, it will be difficult for beginners to convert older version to latest version. Besides, I think that if I write an Article on this, then it will help me also as a future reference as I'll describe each functionality of this library with example. Frankly speaking, in this Article, you find all the examples from Chapter 1 of the book iText in Action, Second Edition which is written for Java Developers. I'll explain all the examples of the rest Chapters in my next release of this Article. So if any one is interested in using this library, he/she will get a good kick start.
To know the history or any other details of iTextSharp, please go through the Official Website
Requirements
- To compile this library, you need a C# 2008 compiler or better, Visual Studio 2008 or Visual C# 2008 Express Edition
- This library code will run in:
- .NET 2.0
- .NET 3.0
- .NET 3.5
- .NET 4.0
- .NET 4.0 Client Profile
- .NET 4.5
- .NET 4.5 Client Profile
Installation
- Simply install the NuGet package
Or you can download the library DLL from the above link or from the SourceForge. Then do the following:
- Add the following library into your project by adding reference to that library DLL. Just see the image below:
- The necessary namespace that you have to add into your C# file to do what are in this Article are::
iTextSharp.text
iTextSharp.text.pdf
Quick Start
Creating PDF Document in 6 Steps:
- Step 1: Create a
System.IO.FileStream
object:
FileStream fs = new FileStream("Chapter1_Example1.pdf", FileMode.Create, FileAccess.Write, FileShare.None);
- Step 2: Create a
iTextSharp.text.Document
object:
Document doc = new Document();
- Step 3: Create a
iTextSharp.text.pdf.PdfWriter
object. It helps to write the Document to the Specified FileStream:
PdfWriter writer = PdfWriter.GetInstance(doc, fs);
- Step 4: Openning the Document:
doc.Open();
- Step 5: Adding a Paragraph by creating a iTextSharp.text.Paragraph object:
doc.Add(new Paragraph("Hello World"));
- Step 6: Closing the Document:
doc.Close();
Working with Page Size of PDF Document:
Creating a Page of specified size, we must have to create a iTextSharp.text.Rectangle
object and Passing the size as argument to its constructor. There are a few way to define Page Size:
- First Way to define Page Size:
Creating Page Size by Pixels or Inch. NOTE: In iTextSharp library, unit is 'point'. 72 points = 1 inch. Suppose we want to create a PDF File of width = 2 inch & height = 10 inch, then we need 144pt for 2 inch & 72pt for 10 inch. Lets see, how to do this:
Rectangle rec = new Rectangle(144, 720);
- Second Way to define Page Size:
Taking Page Size from in-builtiTextSharp.text.PageSize
class:
Rectangle rec2 = new Rectangle(PageSize.A4);
The following are the Supported in-built Page Size. Read the full Documentation of Page Size:_11X17
A0
A1
A10
A2
A3
A4
A4_LANDSCAPE
A5
A6
A7
A8
A9
ARCH_A
ARCH_B
ARCH_C
ARCH_D
ARCH_E
B0
B1
B10
B2
B3
B4
B5
B6
B7
B8
B9
CROWN_OCTAVO
CROWN_QUARTO
DEMY_OCTAVO
DEMY_QUARTO
EXECUTIVE
FLSA
FLSE
HALFLETTER
ID_1
ID_2
ID_3
LARGE_CROWN_OCTAVO
LARGE_CROWN_QUARTO
LEDGER
LEGAL
LEGAL_LANDSCAPE
LETTER
LETTER_LANDSCAPE
NOTE
PENGUIN_LARGE_PAPERBACK
PENGUIN_SMALL_PAPERBACK
POSTCARD
ROYAL_OCTAVO
ROYAL_QUARTO
SMALL_PAPERBACK
TABLOID
- Third Way to define Page Size:
Rotating Document i.e. height becomes width & vice-versa:
Rectangle rec3 = new Rectangle(PageSize.A4.Rotate());
Now, just pass this iTextSharp.text.Rectangle
object (any one) i.e. either 'rec', or 'rec2' or 'rec3' to the iTextSharp.text.Document
's constructor during object creation like below:
Document doc = new Document(rec);
Setting Background Color of PDF Document:
There are a few ways to set background color:
- First Way to Set Background Color:
It takes the object ofiTextSharp.text.BaseColor
. BaseColor constructor takes in-built System.Drawing.Color object Or you can pass RGB values to the constructor in different forms:
rec.BackgroundColor = new BaseColor(System.Drawing.Color.WhiteSmoke);
- Second Way to Set Background Color:
It takes the object ofiTextSharp.text.pdf.CMYKColor
. CMYKColor constructor takes only CMYK values in different forms:
rec2.BackgroundColor = new CMYKColor(25, 90, 25, 0);
Setting Page Margins of PDF Document:
Margins can be set during Document
object creation like Page Size
Suppose we set the margins as below:
- Left Margin: 0.5 inch
- Right Margin: 1 inch
- Top Margin: 1.5 inch
- Bottom Margin: 2.5 inch
So, we need to do set the following points for the Left, Right, Top, Bottom Margins respectively as we already know that iTextSharp
library only understand points where 72 points = 1 inch.
- Left Margin: 36pt => 0.5 inch
- Right Margin: 72pt => 1 inch
- Top Margin: 108pt => 1.5 inch
- Bottom Margini: 180pt => 2.5 inch
Lets implement:
Document doc = new Document(PageSize.A4, 36, 72, 108, 180);
Setting Text Alignment in PDF Document:
Alignment
is one of the property of iTextSharp.text.Paragraph
's object. iTextSharp
Library provides various types of Alignments. These Alignments can be access through iTextSharp.text.Element
class. The following are Alignment types provides iTextSharp:
-
<a href="http://api.itextpdf.com/itext/com/itextpdf/text/Element.html#ALIGN_BASELINE"> ALIGN_BASELINE</a>
[^] -
<a href="http://api.itextpdf.com/itext/com/itextpdf/text/Element.html#ALIGN_BOTTOM"> ALIGN_BOTTOM</a>
[^] -
<a href="http://api.itextpdf.com/itext/com/itextpdf/text/Element.html#ALIGN_CENTER"> ALIGN_CENTER</a>
[^] -
<a href="http://api.itextpdf.com/itext/com/itextpdf/text/Element.html#ALIGN_JUSTIFIED"> ALIGN_JUSTIFIED</a>
[^] -
<a href="http://api.itextpdf.com/itext/com/itextpdf/text/Element.html#ALIGN_JUSTIFIED_ALL"> ALIGN_JUSTIFIED_ALL</a>
[^] -
<a href="http://api.itextpdf.com/itext/com/itextpdf/text/Element.html#ALIGN_LEFT"> ALIGN_LEFT</a>
[^] -
<a href="http://api.itextpdf.com/itext/com/itextpdf/text/Element.html#ALIGN_MIDDLE"> ALIGN_MIDDLE</a>
[^] -
<a href="http://api.itextpdf.com/itext/com/itextpdf/text/Element.html#ALIGN_RIGHT"> ALIGN_RIGHT</a>
[^] -
<a href="http://api.itextpdf.com/itext/com/itextpdf/text/Element.html#ALIGN_TOP"> ALIGN_TOP</a>
[^] -
<a href="http://api.itextpdf.com/itext/com/itextpdf/text/Element.html#ALIGN_UNDEFINED"> ALIGN_UNDEFINED</a>
[^]
As we already see the iTextSharp.text.Document
's constructor takes iTextSharp.text.Paragraph
's object during Document creation. So, after creating the Paragraph object and setting Alignment property, we can pass this object to iTextSharp.text.Document
's constructor during Document ceration. Lets implement:
Paragraph para = new Paragraph("Hello World Hello World Hello World Hello World Hello World Hello World Hello World Hello World Hello World Hello World Hello World");
// Setting paragraph's text alignment using iTextSharp.text.Element class
para.Alignment = Element.ALIGN_JUSTIFIED;
// Adding this 'para' to the Document object
doc.Add(para);
Setting Meta Information or Properties of a PDF Document:
The following Meta information of PDF Document, you can set through iTextSharp.text.Document
's methods by creating its object i.e. doc
here:
- Author Name[^]
- Creation Date[^]
- Creator Name[^]
- Header Name & Content[^]
- Keywords[^]
- Langugae[^]
- Producer[^]
- Subject[^]
- Title[^]
Lets implement a few of them:
// Setting Document properties e.g.
// 1. Title
// 2. Subject
// 3. Keywords
// 4. Creator
// 5. Author
// 6. Header
doc.AddTitle("Hello World example");
doc.AddSubject("This is an Example 4 of Chapter 1 of Book 'iText in Action'");
doc.AddKeywords("Metadata, iTextSharp 5.4.4, Chapter 1, Tutorial");
doc.AddCreator("iTextSharp 5.4.4");
doc.AddAuthor("Debopam Pal");
doc.AddHeader("Nothing", "No Header");
Now after openning this PDF file, right click over it and click Properties, then you'll see the following:
Creating a Multipage Document:
We can create a new page through iTextSharp.text.Document
's NewPage()
method by creating its object. Lets add five pages in PDF Document:
for (int i = 1; i <= 5; i++)
{
doc.NewPage();
doc.Add(new Paragraph(string.Format("This is a page {0}", i)));
}
Creating a New PDF Document from an existing PDF Document:
We can read from a PDF Document using iTextSharp.text.pdf.PdfReader
's object and write it to another PDF Document using iTextSharp.text.pdf.PdfStamper
's object. Lets implement:
string originalFile = "Original.pdf";
string copyOfOriginal = "Copy.pdf";
using (FileStream fs = new FileStream(originalFile, FileMode.Create, FileAccess.Write, FileShare.None))
using (Document doc = new Document(PageSize.LETTER))
using (PdfWriter writer = PdfWriter.GetInstance(doc, fs))
{
doc.Open();
doc.Add(new Paragraph("Hi! I'm Original"));
doc.Close();
}
PdfReader reader = new PdfReader(originalFile);
using (FileStream fs = new FileStream(copyOfOriginal, FileMode.Create, FileAccess.Write, FileShare.None))
// Creating iTextSharp.text.pdf.PdfStamper object to write
// Data from iTextSharp.text.pdf.PdfReader object to FileStream object
using (PdfStamper stamper = new PdfStamper(reader, fs)) { }
Adding Watermark to PDF Document using Layer:
Watermark can be add after creating the PDF Dodument in iTextSharp
Library. Here I'll add Watermark to existing PDF Document i.e. Original.pdf
, through creating a iTextSharp.text.pdf.PdfLayer
object. Lets implement:
string watermarkedFile = "Watermarked.pdf";
// Creating watermark on a separate layer
// Creating iTextSharp.text.pdf.PdfReader object to read the Existing PDF Document
PdfReader reader1 = new PdfReader(originalFile);
using (FileStream fs = new FileStream(watermarkedFile, FileMode.Create, FileAccess.Write, FileShare.None))
// Creating iTextSharp.text.pdf.PdfStamper object to write Data from iTextSharp.text.pdf.PdfReader object to FileStream object
using (PdfStamper stamper = new PdfStamper(reader1, fs))
{
// Getting total number of pages of the Existing Document
int pageCount = reader1.NumberOfPages;
// Create New Layer for Watermark
PdfLayer layer = new PdfLayer("WatermarkLayer", stamper.Writer);
// Loop through each Page
for (int i = 1; i <= pageCount; i++)
{
// Getting the Page Size
Rectangle rect = reader1.GetPageSize(i);
// Get the ContentByte object
PdfContentByte cb = stamper.GetUnderContent(i);
// Tell the cb that the next commands should be "bound" to this new layer
cb.BeginLayer(layer);
cb.SetFontAndSize(BaseFont.CreateFont(
BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED), 50);
PdfGState gState = new PdfGState();
gState.FillOpacity = 0.25f;
cb.SetGState(gState);
cb.SetColorFill(BaseColor.BLACK);
cb.BeginText();
cb.ShowTextAligned(PdfContentByte.ALIGN_CENTER, watermarkText, rect.Width / 2, rect.Height / 2, 45f);
cb.EndText();
// Close the layer
cb.EndLayer();
}
}
The created PDF Document is below:
Removing Watermark from the just created Watermarked Document by Removing Layer:
Whenever we add Layer in PDF Document, then the content of the Layer resides under OCG
Group. So if I remove this Layer we can remove the content of the Layer also e.g. here it is Watermark Text. To remove all the Layers from PDF Document, you have to remove OCG Group completely from the Document using reader.Catalog.Remove(PdfName.OCPROPERTIES)
. Now follow the Steps below to remove the Watermark Text from Layer:
- Read the existing watermarked document using
iTextSharp.text.pdf.PdfReader
's object - Taking each Page in the
iTextSharp.text.pdf.PdfDictionary
's object usingGetPageN(int pageNumber)
method ofiTextSharp.text.pdf.PdfReader
's object. - Taking the Content of the Page in the
iTextSharp.text.pdf.PdfArray
's object usingGetAsArray(PdfName.CONTENTS)
method ofiTextSharp.text.pdf.PdfDictionary
's object - Loop through this array and Get each element as
iTextSharp.text.pdf.PRStream
's object usingGetAsStream(int arrayIndex)
method ofiTextSharp.text.pdf.PdfArray
's object - Convert each stream into Bytes using Static method
GetStreamBytes(PRStream stream)
ofiTextSharp.text.pdf.PdfReader
class - Convert these Bytes into String using
System.Text.Encoding.ASCII.GetString(byte[] bytes)
method - Search for the String "/OC" and also the
Watermarked Text
. If found then remove it by giving it zero length and zero data using two methods:Put()
&SetData()
ofiTextSharp.text.pdf.PRStream
class - Write this modified document exists in the
reader
to a new document usingiTextSharp.text.pdf.PdfStamper
's object
Lets Implement it:
// Removing the layer created above
// 1. First we bind a reader to the watermarked file
// 2. Then strip out a branch of things
// 3. Finally use a simple stamper to write out the edited reader
PdfReader reader2 = new PdfReader(watermarkedFile);
// NOTE: This will destroy all layers in the Document, only use if you don't have any addtional layers
// Remove the OCG group completely from the Document: reader2.Catalog.Remove(PdfName.OCPROPERTIES);
// Clean up the reader, optional
reader2.RemoveUnusedObjects();
// Placeholder variables
PRStream stream;
string content;
PdfDictionary page;
PdfArray contentArray;
// Get the number of pages
int pageCount2 = reader2.NumberOfPages;
// Loop through each page
for (int i = 1; i <= pageCount2; i++)
{
// Get the page
page = reader2.GetPageN(i);
// Get the raw content
contentArray = page.GetAsArray(PdfName.CONTENTS);
if (contentArray != null)
{
// Loop through content
for (int j = 0; j < contentArray.Size; j++)
{
stream = (PRStream)contentArray.GetAsStream(j);
// Convert to a String, NOTE: you might need a different encoding here
content = System.Text.Encoding.ASCII.GetString(PdfReader.GetStreamBytes(stream));
//Look for the OCG token in the stream as well as our watermarked text
if (content.IndexOf("/OC") >= 0 && content.IndexOf(watermarkText) >= 0)
{
//Remove it by giving it zero length and zero data
stream.Put(PdfName.LENGTH, new PdfNumber(0));
stream.SetData(new byte[0]);
}
}
}
}
// Write the content out
using (FileStream fs = new FileStream(unwatermarkedFile,
FileMode.Create, FileAccess.Write, FileShare.None))
using (PdfStamper stamper = new PdfStamper(reader2, fs)) { }
Adding Watermark to each Page during Creation:
Now, we already know that, watermark cannot be add during Page creation, it have to add after document creation. So, I've created a class PDFWriterEvents
which implements the interface iTextSharp.text.pdf.IPdfPageEvent
and modify the event OnStartPage
. This interface contains a set of events from the Openning & to Closing the PDF Document. The events are following:
public void OnOpenDocument(PdfWriter writer, Document document)
public void OnCloseDocument(PdfWriter writer, Document document)
public void OnStartPage(PdfWriter writer, Document document)
public void OnEndPage(PdfWriter writer, Document document)
public void OnParagraph(PdfWriter writer, Document document, float paragraphPosition)
public void OnParagraphEnd(PdfWriter writer, Document document, float paragraphPosition)
-
public void OnChapter(PdfWriter writer, Document document, float paragraphPosition, Paragraph title)
public void OnChapterEnd(PdfWriter writer, Document document, float paragraphPosition)
-
public void OnSection(PdfWriter writer, Document document, float paragraphPosition, int depth, Paragraph title)
public void OnSectionEnd(PdfWriter writer, Document document, float paragraphPosition)
-
public void OnGenericTag(PdfWriter writer, Document document, Rectangle rect, String text)
You may modify other events accroding to your needs which occured against a particular action. Let see the which I've created:
// Creating Watermark inside OnStartPage Event by implementing IPdfPageEvent interface
// So that, dusring Page Creation, Watermark will be create
class PDFWriterEvents : IPdfPageEvent
{
string watermarkText;
float fontSize = 80f;
float xPosition = 300f;
float yPosition = 800f;
float angle = 45f;
public PDFWriterEvents(string watermarkText, float fontSize = 80f,
float xPosition = 300f, float yPosition = 400f, float angle = 45f)
{
this.watermarkText = watermarkText;
this.xPosition = xPosition;
this.yPosition = yPosition;
this.angle = angle;
}
public void OnOpenDocument(PdfWriter writer, Document document) { }
public void OnCloseDocument(PdfWriter writer, Document document) { }
public void OnStartPage(PdfWriter writer, Document document)
{
try
{
PdfContentByte cb = writer.DirectContentUnder;
BaseFont baseFont = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.EMBEDDED);
cb.BeginText();
cb.SetColorFill(BaseColor.LIGHT_GRAY);
cb.SetFontAndSize(baseFont, fontSize);
cb.ShowTextAligned(PdfContentByte.ALIGN_CENTER, watermarkText, xPosition, yPosition, angle);
cb.EndText();
}
catch (DocumentException docEx)
{
throw docEx;
}
}
public void OnEndPage(PdfWriter writer, Document document) { }
public void OnParagraph(PdfWriter writer, Document document, float paragraphPosition) { }
public void OnParagraphEnd(PdfWriter writer, Document document, float paragraphPosition) { }
public void OnChapter(PdfWriter writer, Document document, float paragraphPosition, Paragraph title) { }
public void OnChapterEnd(PdfWriter writer, Document document, float paragraphPosition) { }
public void OnSection(PdfWriter writer, Document document, float paragraphPosition, int depth, Paragraph title) { }
public void OnSectionEnd(PdfWriter writer, Document document, float paragraphPosition) { }
public void OnGenericTag(PdfWriter writer, Document document, Rectangle rect, String text) { }
}
Lets see how & when you use the object of this class:
using (FileStream fs = new FileStream(
"Watermark_During_Page_Creation.pdf", FileMode.Create, FileAccess.Write, FileShare.None))
using (Document doc = new Document(PageSize.LETTER))
using (PdfWriter writer = PdfWriter.GetInstance(doc, fs))
{
writer.PageEvent = new PDFWriterEvents("This is a Test");
doc.Open();
doc.Add(new Paragraph("This is a page 1"));
doc.Close();
}
See, OnStartPage
event called during adding a new paragraph. So I don't need to add watermark later:)
Export/Print/Output the PDF File directly to the Client without saving it to the Disk:
We can create PDF File in memory by creatig System.IO.MemorySystem
's object. Lets see:
using (MemoryStream ms = new MemoryStream())
using(Document document = new Document(PageSize.A4, 25, 25, 30, 30))
using(PdfWriter writer = PdfWriter.GetInstance(document, ms))
{
document.Open();
document.Add(new Paragraph("Hello World"));
document.Close();
writer.Close();
ms.Close();
Response.ContentType = "pdf/application";
Response.AddHeader("content-disposition", "attachment;filename=First_PDF_document.pdf");
Response.OutputStream.Write(ms.GetBuffer(), 0, ms.GetBuffer().Length);
}
Setting Viewer Preferences of a PDF Document:
The values of the different ViewerPreferences
were originally stored in iTextSharp.text.pdf.PdfWriter
class as an integer constant. You can set the ViewerPreferences
by following two ways:
- By setting property
ViewerPreferences
ofiTextSharp.text.pdf.PdfWriter
class. To know all theViewerPreferences
and its purpose, please read this first. E.g.-
writer.ViewerPreferences = PdfWriter.HideMenubar;
- By calling method
AddViewerPreference(PdfName key, PdfObject value)
ofiTextSharp.text.pdf.PdfWriter
's object. To know whichvalue
is appropiate for whichkey
, read this first. E.g.-
writer.AddViewerPreference(PdfName.HIDEMENUBAR, new PdfBoolean(true));
Encrypting a PDF Document:
By SetEncryption()
method of iTextSharp.text.pdf.PdfWriter
's object, we can encrypt a PDF document. Read full documentation of this method here. To know all the encryption types, click here. E.g.-
writer.SetEncryption(PdfWriter.STRENGTH40BITS, null, null, PdfWriter.ALLOW_COPY);
Declaration
Please download the source code for detail. I hope you'll understand as the source code is documented. If any doubt, just post your comment below. Thank you.
References
- iText Official Website
- iText in Action, Second Edition
- Core iText API Documentation
- RubyPdf Blog - iText# in Action
- Create PDFs in ASP.NET - getting started with iTextSharp
- Basic PDF Creation Using iTextSharp - Part I