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

Chunks

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));

doc.Open();

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

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

{

    doc.Add(c1);

}

 

[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);

 

""

Phrases

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++)

{

      phrase.Add(c1);

}

 

""

Paragraphs

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);

 

try

{

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

    doc.Open();

 

    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();

    p2.Add(c1);

    p2.Add(c2);

    p2.Add(c3);

    p2.Add(c4);

    p2.Add(c5);

    p2.Add(c6);

    p2.Add(c7);

    p2.Add(c8);

    p2.Add(c9);

    Paragraph p = new Paragraph();

    p.Add(p1);

    p.Add(p2);

    doc.Add(p);

}

catch (DocumentException dex)

{

    throw (dex);

}

catch (IOException ioex)

{

    throw (ioex);

}

finally

{

    doc.Close();

}

 

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: 270974

13 Comments

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

Excelente short but concise tutorial!

Thanks!

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.

Thanks,
Vijay

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

@Vijay

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.

YOU ROCK!!!!!

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

Gautam 11/20/2014 8:01 AM
In response to I'm Writing A Book On WebMatrix
Hello Mike, I read your book, loved it! However, I have a few request/suggestions: 1) an example...

Bret Dev 11/19/2014 8:39 PM
In response to The Difference Between @Helpers and @Functions In WebMatrix
Excellent post! One concern - where can you place global @Functions code within an MVC project to Is...

Rob Farquharson 11/19/2014 4:28 PM
In response to iTextSharp - Links and Bookmarks
How can I place text at an absolute position on the page? Also, how can I rotate text?...

Andy 11/17/2014 8:08 PM
In response to MVC 5 with EF 6 in Visual Basic - Sorting, Filtering and Paging
Hello I'm testing your sorting instructions above. This is great and I was able to get it to work...

Gautam 11/17/2014 5:51 PM
In response to WebMatrix - Database Helpers for IN Clauses
Hi Mike, I am very new to programming: In the above example if I want to use a delete button the...

donramon 11/17/2014 3:22 PM
In response to Entity Framework 6 Recipe - Alphabetical Paging In ASP.NET MVC
Congratulations on your new website look and the excellent articles. Thank you!...

Gautam 11/17/2014 11:26 AM
In response to Looking At The WebMatrix WebGrid
Hi Mike, I add the jquery script at the end of my html file.. when ajax attribute is added to the be...

Chet Ripley 11/15/2014 6:57 PM
In response to Adding A New Field
It appears the command is case sensitive. I had the same issue as Cameron. When I changed the to it...

Alvin 11/14/2014 12:49 PM
In response to Razor Web Pages E-Commerce - Adding A Shopping Cart To The Bakery Template Site
Great article Mike! When do you plan to extend the bakery shopping cart beyond this point?...

Gautam 11/14/2014 10:16 AM
In response to Web Pages - Efficient Paging Without The WebGrid
to get the count can we use only the below sql, why to join category and author table var sql =...