iTextSharp - Adding Text with Chunks, Phrases and Paragraphs

This is the third in a series of articles that looks at using the open source component, iTextSharp from within ASP.NET to generate PDFs. Just as HTML and ASP.NET provide containers for varying ampounts of textual content, iTextSharp offers the Chunk, Phrase and Paragraph classes. Before going on, if you would like to read earlier articles, they are:

Create PDFs in ASP.NET - getting started with iTextSharp
iTextSharp - Working with Fonts


A Chunk is the smallest significant piece of text that you can work with. It's ASP.NET equivalent is the <asp:Label>. As with the Label, you need to be careful how you use Chunks. The following snippet shows how to set the text of a Chunk, then write it to the PDF document 3 times:


string path = Server.MapPath("PDFs");

Rectangle r = new Rectangle(400, 300);

Document doc = new Document(r);

PdfWriter.GetInstance(doc, new FileStream(path + "/Blocks.pdf", FileMode.Create));


Chunk c1 = new Chunk("A chunk represents an isolated string. ");

for (int i = 1; i < 4; i++)





[Keep an eye on the following paragraph - we will come back to it]
The result can be seen below, which shows the text having been written to the document but it looks a mess. Chunks have no concept of how to force a new line when the length exceeds the available width in the document. Really, all they should be used for is to change or set the style of a word or phrase inline. You can of course force a newline using "\n" or Environment.NewLine, or even Chunk.NEWLINE as part of the string you give a chunk.


The chunk has a number of methods to allow you to do this, such as setUnderLine(), setBackGround(), and setTextRise(), as well as a number of constructors that permit you to set the font and its styles.


Chunk chunk = new Chunk("Setting the Font", FontFactory.GetFont("dax-black"));

chunk.SetUnderline(0.5f, -1.5f);




The Phrase is the next container in the hierarchy. A phrase is an array of chunks, and will force a newline when the length of its contents exceed the vertical margins of the document. The space between each line (actually the measurement taken between the baselines of each line, or "leading") is 1.5 times the font size. Since the default font-size was applied by iTextSharp (12pt), the code below will result in a leading of 16pt. You can set the leading or font as part of initiating a new phrase, as well as pass it a string or chunk to set its content through the phrase's various overloaded constructors. The following snippet shows how the earlier chunk is added to a phrase 3 times, and the result.


Phrase phrase = new Phrase();

for (int i = 1; i < 4; i++)







What we have seen so far is the very basic building blocks for text in PDFs. The object that you will use most often is a Paragraph, which is a sequence of Phrases and Chunks held together. Paragraphs derive from Phrase, so they autommatically fit text within the horizontal boundaries of the document, but they also force a new line for each paragraph (just as in any word processing application). The paragraph earlier in the Chunk section of this article is as good as any to experiment with. It has a number of sentences and some formatted inline text, so we can use that to build a paragraph from chunks and phrases:


string path = Server.MapPath("PDFs");

Rectangle r = new Rectangle(400, 300);

Document doc = new Document(r);




    PdfWriter.GetInstance(doc, new FileStream(path + "/Blocks2.pdf", FileMode.Create));



    string text = @"The result can be seen below, which shows the text

                  having been written to the document but it looks a

                  mess. Chunks have no concept of how to force a new

                   line when the length exceeds the available width in

                  the document. Really, all they should be used for is

                  to change or set the style of a word or phrase inline. ";

    text = text.Replace(Environment.NewLine, String.Empty).Replace("  ", String.Empty);

    Font brown = new Font(Font.COURIER, 9f, Font.NORMAL, new Color(163, 21, 21));

    Font lightblue = new Font(Font.COURIER, 9f, Font.NORMAL, new Color(43, 145, 175));

    Font courier = new Font(Font.COURIER, 9f);

    Font georgia = FontFactory.GetFont("georgia", 10f);

    georgia.Color = Color.GRAY;

    Chunk beginning = new Chunk(text, georgia);

    Phrase p1 = new Phrase(beginning);

    Chunk c1 = new Chunk("You can of course force a newline using \"", georgia);

    Chunk c2 = new Chunk(@"\n", brown);

    Chunk c3 = new Chunk("\" or ", georgia);

    Chunk c4 = new Chunk("Environment", lightblue);

    Chunk c5 = new Chunk(".NewLine", courier);

    Chunk c6 = new Chunk(", or even ", georgia);

    Chunk c7 = new Chunk("Chunk", lightblue);

    Chunk c8 = new Chunk(".NEWLINE", courier);

    Chunk c9 = new Chunk(" as part of the string you give a chunk.", georgia);

    Phrase p2 = new Phrase();










    Paragraph p = new Paragraph();





catch (DocumentException dex)


    throw (dex);


catch (IOException ioex)


    throw (ioex);







First, the result, then some notes about the code:


It didn't take long to start adding Exception handling to the code. Of course, you should always use try... catch when performing IO operations, and with iTextSharp Document objects, there is also a DocumentException object to manage. There is another source of exceptions that I found to be rather sneaky. When testing the code to generate the PDF file, I inadvertently transposed two arguments in the constructor for the font I called lightblue, in that I passed in the value Font.NORMAL before the size. This had the effect of setting the font size to 0, which is the value that the constant is set to. An exception is thrown when trying to call doc.Close(), and I have to shut down VS to release its hold on the document object.

So, exception handling starts to make its appearance, so that at least the document object is released. You will also notice that the font size values are now passed in with the f suffix following them. That explicitly tells the compiler that the value is to be treated as a float, and prevents the sort of mistake I experienced happening again.

The first block of text, which is @-quoted, or a verbatim string literal, needs to have all the whitespace and newlines removed from it, otherwise it will appear with them preserved in the resulting PDF. Other than that, each individually styled string is applied to its own Chunk object, and then added to a Phrase to ensure that lines are wrapped in the PDF. Finally both phrases are added to the single Paragraph object. It is also possible to set the alignment of the paragraph text, using the Paragraph.setAlignment() method. This accepts a string, with "Left", "Center", "Justify", and "Right" being valid values. The following shows the earlier example with p.setAlignment("Justify");


The Paragraph class has a number of other useful methods and properties for styling including:

Paragraph.FirstLineIndent  //allows you to apply a float value to indent the first line
Paragraph.IndentationLeft  //allows you to add space to the left hand side
Paragraph.IndentationRight //allows you to add space to the right hand side
Paragraph.setSpacingBefore //adds a specified amount of space above the paragraph
Paragraph.setSpacingAfter  //adds the specified amount of space after the paragraph

The next article will look at more text-based functionality, specifically in the area of lists.


Date Posted: Saturday, October 18, 2008 10:32 PM
Last Updated: Monday, October 20, 2008 8:34 AM
Posted by: Mikesdotnetting
Total Views to date: 285967


Wednesday, March 25, 2009 8:03 PM - Nameless

Excelente short but concise tutorial!


Wednesday, October 28, 2009 2:17 PM - Nameless 2

Hi, thanks for all the effort gone into these tutorials. I need to stamp existing PDFs with some text (and possibly and image), and it's occured to me that I can't use PdfWriter for this, as in all your examples a new PDF is being created.

I'm guessing it's PdfStamper that I need - perhaps you'll add a tutorial on that to your great series. I'm off to see if I can figure that one out now...

Tuesday, June 15, 2010 4:43 PM - Vijay

Hi Mike,

Thanks for such a wonderful site and detailed explanations.

I was wondering how to handle TAB character. I tried to use above chunk code but results is always a space.
Do i have to use columns or there is some other way around.


Tuesday, June 15, 2010 6:49 PM - Mike


As I understand it, Tabs are not supported in iTextSharp. The usual recommendation is to use Paragraph.IndentationLeft

Saturday, July 3, 2010 5:29 PM - sky

Hi Mike, How to Positioning display text ?

Monday, September 13, 2010 9:11 PM - Eva

Thankx a lot for these articles!

Monday, January 10, 2011 3:05 PM - mohit

Good shot!!!!!!!!!!!!!!!

Monday, January 31, 2011 5:18 PM - Mle

Thank you for the tutorial, very clear and understandable

Wednesday, July 20, 2011 10:28 AM - Alex L.

Wow man. I'm a nub at this stuff and it just clicked with the earlier tutorials about adding a reference to the library and calling stuff from iTextsharp once I add the "Using" line. Also you example is clean / simple but effective letting me build on it.


Thursday, April 12, 2012 1:16 AM - Igor

I am introducing myself to Pdf creation with Java and thanks to your tutorials (the one about tables saved me), I have reached nearly all the objectives I had with the document in only 6 hours.

Simply awesome!

Thanks a lot.

Sunday, October 21, 2012 8:20 PM - Mark Wilson

I was wondering what the usual method is to place text at a particular location in a PDF. I have some pre-produced PDFs that will go to a printer and I need to insert some text info and an image.

Is it possible to specify where the text appears and the boundaries? Would you use the PDF form functionality for this?

Awesome series by the way.

Wednesday, December 25, 2013 12:31 PM - nirach

and what about tables ?
if i wanna include tables to the pdf file then how can i do this ?

Wednesday, January 8, 2014 12:25 PM - Mike

Add your comment

If you have any comments to make about this article, please use this form to do so. Make sure that your comment relates specifically to the article above. More general comments can be posted through the form on the Contact page.

Please note, all comments are moderated, and some may not be published. The kind of things that will ensure your comment is deleted without ever seeing the light of day are as follows:

  • Not relevant to the article
  • Gratuitous links to your own site or product
  • Anything abusive or libellous
  • Spam
  • Anything in a language I don't understand including gibberish.

I do not pass email addresses on to spammers, so a valid one will assist me in responding to you personally if required.

Recent Comments

Satyabrata 1/23/2015 6:02 AM
In response to Usage of the @ (at) sign in ASP.NET
Refreshed a lot of things.Thanks...

Vo Thanh Chinh Trung 1/22/2015 4:30 PM
In response to Adding A View
It's very helpful...Thank you so much, Mikes!...

Joop Stringer 1/22/2015 12:00 PM
In response to Inline Editing With The WebGrid
How to add a row for a new record ?...

Gaetan C 1/21/2015 8:49 PM
In response to Looking At The WebMatrix WebGrid
I use the webgrid very often and I Wonder if it's possible to merge to different sql query into on...

Teresa 1/19/2015 3:08 PM
In response to MVC 5 with EF 6 in Visual Basic - Creating an Entity Framework Data Model
At the top, the first thing you write is "Open Visual Studio and create a new C# Web project named I...

Evita 1/19/2015 6:44 AM
In response to Creating a Connection String and Working with SQL Server LocalDB
Hi Mike, Thank you so much for the tutorial. It really help me. However, I am a bit confuse .mdf...

Scott 1/18/2015 2:22 PM
In response to Migrating Classic ASP To ASP.NET Razor Web Pages Part Two- Data Access
Just an FYI: I get an exception when clicking the link for Razor Syntax and Visual Basic. "A was...

F.Manicou 1/15/2015 8:54 PM
In response to Conversion of a datetime2 data type to a datetime data type resulted in an out-of-range value
Thank you so much!!!!...

Satyabrata 1/13/2015 3:24 PM
In response to Entity Framework 6 Recipe - Grouping By Year And Month
Nice article. Learned a lot. Thanks for sharing....

Gjuro 1/13/2015 2:41 AM
In response to MVC 5 with EF 6 in Visual Basic - Creating an Entity Framework Data Model
under subtitle "Create a logging interface and class" remove excess empty lines at the start of the...