Home / Articles / Tools of the Trade, Part 1: Creating PDF documents with iText

Tools of the Trade, Part 1: Creating PDF documents with iText

Article Description

Have you ever wanted to create your own PDF documents without having to first shell out money for PDF-creation software? Good news: You can create those documents with nothing more than Java and iText. This freely available Java library provides the classes for easily constructing PDF documents and adding various kinds of content (such as paragraphs, lists, tables, and images) to those documents. This article by Jeff Friesen, the first in a three-part series that explores useful open-source tools, introduces you to iText and shows you how to create many interesting PDF documents without having to first spend money on PDF-creation software.

Planetary PDF

This article has covered lots of material. Your head is probably spinning from exploring many of the capabilities offered by iText. Perhaps you are asking yourself how to combine these capabilities to create useful PDF documents. If so, I have an answer: a more extensive PDF project that brings together many of the capabilities that were presented earlier.

The project I have in mind is to write an application that creates a PDF document called planets.pdf, which tours the planets in our solar system. It contains a title page, an introduction, one chapter per planet, and an appendix that compares each planet's orbit, diameter, and mass. Figure 17 shows what I have in mind.

Figure 17

Figure 17 The planetary PDF document.

Don't worry. You do not have to create the application that generates Figure 17's PDF document. I have done all of that work for you. You can download the code here, and the application's source code appears in Listing 15. As you examine that source code, you will discover that there is nothing you have not seen before.

Listing 15 Planets.java

// Planets.java

import java.awt.Color;
import java.io.*;

import com.lowagie.text.*;
import com.lowagie.text.pdf.*;

class Planets
{
  public static void main (String [] args) throws Exception
  {
   Document doc = new Document ();

   PdfWriter writer;
   writer = PdfWriter.getInstance (doc,
                   new FileOutputStream ("planets.pdf"));
   writer.setViewerPreferences (PdfWriter.PageModeUseOutlines);

   doc.open ();

   // Establish a footer that shows the page number between a pair dashes.

   HeaderFooter footer = new HeaderFooter (new Phrase ("- "),
                       new Phrase (" -"));
   footer.setAlignment (Element.ALIGN_CENTER);

   doc.setFooter (footer);

   // Create the title page.

   PdfContentByte cb = writer.getDirectContent ();

   cb.rectangle (doc.left (), doc.bottom (), doc.right () - doc.left (),
          doc.top ()-doc.bottom ());

   cb.stroke ();

   cb.beginText ();

   BaseFont bf = BaseFont.createFont (BaseFont.HELVETICA,
                     BaseFont.CP1252,
                     BaseFont.NOT_EMBEDDED);
   cb.setFontAndSize (bf, 36);

   cb.showTextAligned (PdfContentByte.ALIGN_CENTER, "The Planets",
             (doc.right ()-doc.left ()) / 2 + doc.leftMargin (),
             (doc.top ()-doc.bottom ()) / 2 + doc.topMargin (),
             0);

   cb.endText ();

   // Establish a title font for all chapter titles.

   Font titleFont = new Font (Font.HELVETICA, 18, Font.BOLD, 
                 new Color (0, 0, 128));

   // Create the Introduction chapter.

   Paragraph title = new Paragraph ("Introduction", titleFont);
   title.setAlignment (Element.ALIGN_CENTER);
   title.setSpacingAfter (18.0f);

   Chapter chapter = new Chapter (title, 0);
   chapter.setNumberDepth (0);

   Paragraph p = new Paragraph ("The solar system is an amazing place. " +
                  "We are learning so much about the " +
                  "planets and their moons, thanks to the " +
                  "efforts of spacecraft and their human " +
                  "controllers. This document provides a " +
                  "brief introduction to our solar " +
                  "system's nine planets.");
   p.setAlignment (Element.ALIGN_JUSTIFIED);
   chapter.add (p);

   doc.add (chapter);

   // Create the Mercury chapter.

   title = new Paragraph ("Mercury", titleFont);

   title.setAlignment (Element.ALIGN_CENTER);
   title.setSpacingAfter (18.0f);

   chapter = new Chapter (title, 1);
   chapter.setNumberDepth (0);
   chapter.setBookmarkOpen (false);
   chapter.setBookmarkTitle ("Chapter 1: Mercury");

   p = new Paragraph ("Mercury, the closest planet to the sun and the " +
             "eighth largest planet, is named after the Roman " +
             "god of commerce, travel, and thievery.");
   p.setAlignment (Element.ALIGN_JUSTIFIED);
   chapter.add (p);

   Image image = Image.getInstance ("mercury.gif");
   image.setAlignment (Image.ALIGN_MIDDLE);
   chapter.add (image);

   chapter.add (new Paragraph ("Vital statistics:"));

   List list = new List (false, 30);
   list.add (new ListItem ("Orbit: 57,910,000 kilometers"));
   list.add (new ListItem ("Diameter: 4,880 kilometers"));
   list.add (new ListItem ("Mass: 3.3e23 kilograms"));
   chapter.add (list);

   doc.add (chapter);

   // Create the Venus chapter.

   title = new Paragraph ("Venus", titleFont);
   title.setAlignment (Element.ALIGN_CENTER);
   title.setSpacingAfter (18.0f);

   chapter = new Chapter (title, 2);
   chapter.setNumberDepth (0);
   chapter.setBookmarkTitle ("Chapter 2: Venus");

   p = new Paragraph ("Venus, the second planet from the sun and the " +
             "sixth largest planet, is named after the Roman " +
             "goddess of love and beauty.");
   p.setAlignment (Element.ALIGN_JUSTIFIED);
   chapter.add (p);

   image = Image.getInstance ("venus.gif");
   image.setAlignment (Image.ALIGN_MIDDLE);
   chapter.add (image);

   chapter.add (new Paragraph ("Vital statistics:"));

   list = new List (false, 30);
   list.add (new ListItem ("Orbit: 108,200,000 kilometers"));
   list.add (new ListItem ("Diameter: 12,103.6 kilometers"));
   list.add (new ListItem ("Mass: 4.869e24 kilograms"));
   chapter.add (list);

   doc.add (chapter);

   // Create the Earth chapter.

   title = new Paragraph ("Earth", titleFont);
   title.setAlignment (Element.ALIGN_CENTER);
   title.setSpacingAfter (18.0f);

   chapter = new Chapter (title, 3);
   chapter.setNumberDepth (0);
   chapter.setBookmarkTitle ("Chapter 3: Earth");

   p = new Paragraph ("Earth, the third planet from the sun and the " +
             "third largest planet, has a name not derived " +
             "from mythology.");
   p.setAlignment (Element.ALIGN_JUSTIFIED);
   chapter.add (p);

   image = Image.getInstance ("earth.gif");
   image.setAlignment (Image.ALIGN_MIDDLE);
   chapter.add (image);

   chapter.add (new Paragraph ("Vital statistics:"));

   list = new List (false, 30);
   list.add (new ListItem ("Orbit: 149,600,000 kilometers"));
   list.add (new ListItem ("Diameter: 12,756.3 kilometers"));
   list.add (new ListItem ("Mass: 5.972e24 kilograms"));
   chapter.add (list);

   doc.add (chapter);

   // Create the Mars chapter.

   title = new Paragraph ("Mars", titleFont);
   title.setAlignment (Element.ALIGN_CENTER);
   title.setSpacingAfter (18.0f);

   chapter = new Chapter (title, 4);
   chapter.setNumberDepth (0);
   chapter.setBookmarkTitle ("Chapter 4: Mars");

   p = new Paragraph ("Mars, the fourth planet from the sun and the " +
             "seventh largest planet, is named after the Roman " +
             "god of war.");
   p.setAlignment (Element.ALIGN_JUSTIFIED);
   chapter.add (p);

   image = Image.getInstance ("mars.gif");
   image.setAlignment (Image.ALIGN_MIDDLE);
   chapter.add (image);

   chapter.add (new Paragraph ("Vital statistics:"));

   list = new List (false, 30);
   list.add (new ListItem ("Orbit: 227,940,000 kilometers"));
   list.add (new ListItem ("Diameter: 6,794 kilometers"));
   list.add (new ListItem ("Mass: 6.4219e23 kilograms"));
   chapter.add (list);

   doc.add (chapter);

   // Create the Jupiter chapter.

   title = new Paragraph ("Jupiter", titleFont);
   title.setAlignment (Element.ALIGN_CENTER);
   title.setSpacingAfter (18.0f);

   chapter = new Chapter (title, 5);
   chapter.setNumberDepth (0);
   chapter.setBookmarkTitle ("Chapter 5: Jupiter");

   p = new Paragraph ("Jupiter, the fifth planet from the sun and the " +
             "largest planet, is named after the Roman king of " +
             "the gods.");
   p.setAlignment (Element.ALIGN_JUSTIFIED);
   chapter.add (p);

   image = Image.getInstance ("jupiter.gif");
   image.setAlignment (Image.ALIGN_MIDDLE);
   chapter.add (image);

   chapter.add (new Paragraph ("Vital statistics:"));

   list = new List (false, 30);
   list.add (new ListItem ("Orbit: 778,330,000 kilometers"));
   list.add (new ListItem ("Diameter: 142,984 kilometers (equatorial)"));
   list.add (new ListItem ("Mass: 1.9e27 kilograms"));
   chapter.add (list);

   doc.add (chapter);

   // Create the Saturn chapter.

   title = new Paragraph ("Saturn", titleFont);
   title.setAlignment (Element.ALIGN_CENTER);
   title.setSpacingAfter (18.0f);

   chapter = new Chapter (title, 6);
   chapter.setNumberDepth (0);
   chapter.setBookmarkTitle ("Chapter 6: Saturn");

   p = new Paragraph ("Saturn, the sixth planet from the sun and the " +
             "second-largest planet, is named after the Roman " +
             "god of agriculture.");
   p.setAlignment (Element.ALIGN_JUSTIFIED);
   chapter.add (p);

   image = Image.getInstance ("saturn.gif");
   image.setAlignment (Image.ALIGN_MIDDLE);
   chapter.add (image);

   chapter.add (new Paragraph ("Vital statistics:"));

   list = new List (false, 30);
   list.add (new ListItem ("Orbit: 1,429,400,000 kilometers"));
   list.add (new ListItem ("Diameter: 120,536 kilometers (equatorial)"));
   list.add (new ListItem ("Mass: 5.68e26 kilograms"));
   chapter.add (list);

   doc.add (chapter);

   // Create the Uranus chapter.

   title = new Paragraph ("Uranus", titleFont);
   title.setAlignment (Element.ALIGN_CENTER);
   title.setSpacingAfter (18.0f);

   chapter = new Chapter (title, 7);
   chapter.setNumberDepth (0);
   chapter.setBookmarkTitle ("Chapter 7: Uranus");

   p = new Paragraph ("Uranus, the seventh planet from the sun and the " +
             "third largest planet (by diameter), is named " +
             "after the Greek deity of the Heavens.");
   p.setAlignment (Element.ALIGN_JUSTIFIED);
   chapter.add (p);

   image = Image.getInstance ("uranus.gif");
   image.setAlignment (Image.ALIGN_MIDDLE);
   chapter.add (image);

   chapter.add (new Paragraph ("Vital statistics:"));

   list = new List (false, 30);
   list.add (new ListItem ("Orbit: 2,870,990,000 kilometers"));
   list.add (new ListItem ("Diameter: 51,118 kilometers (equatorial)"));
   list.add (new ListItem ("Mass: 8.683e25 kilograms"));
   chapter.add (list);

   doc.add (chapter);

   // Create the Neptune chapter.

   title = new Paragraph ("Neptune", titleFont);
   title.setAlignment (Element.ALIGN_CENTER);
   title.setSpacingAfter (18.0f);

   chapter = new Chapter (title, 8);
   chapter.setNumberDepth (0);
   chapter.setBookmarkTitle ("Chapter 8: Neptune");

   p = new Paragraph ("Neptune, the eighth planet from the sun and the " +
             "fourth largest planet, is named after the Roman " +
             "god of the sea.");
   p.setAlignment (Element.ALIGN_JUSTIFIED);
   chapter.add (p);

   image = Image.getInstance ("neptune.gif");
   image.setAlignment (Image.ALIGN_MIDDLE);
   chapter.add (image);

   chapter.add (new Paragraph ("Vital statistics:"));

   list = new List (false, 30);
   list.add (new ListItem ("Orbit: 4,504,000,000 kilometers"));
   list.add (new ListItem ("Diameter: 49,532 kilometers (equatorial)"));
   list.add (new ListItem ("Mass: 1.0247e26 kilograms"));
   chapter.add (list);

   doc.add (chapter);

   // Create the Pluto chapter.

   title = new Paragraph ("Pluto", titleFont);
   title.setAlignment (Element.ALIGN_CENTER);
   title.setSpacingAfter (18.0f);

   chapter = new Chapter (title, 9);
   chapter.setNumberDepth (0);
   chapter.setBookmarkTitle ("Chapter 9: Pluto");

   p = new Paragraph ("Pluto, usually the farthest planet from the sun " +
             "and the smallest planet, is named after the " +
             "Roman god of the underworld.");
   p.setAlignment (Element.ALIGN_JUSTIFIED);
   chapter.add (p);

   image = Image.getInstance ("pluto.gif");
   image.setAlignment (Image.ALIGN_MIDDLE);
   chapter.add (image);

   chapter.add (new Paragraph ("Vital statistics:"));

   list = new List (false, 30);
   list.add (new ListItem ("Orbit: 5,913,520,000 kilometers (average)"));
   list.add (new ListItem ("Diameter: 2274 kilometers"));
   list.add (new ListItem ("Mass: 1.27e22 kilograms"));
   chapter.add (list);

   doc.add (chapter);

   // Create the Appendix chapter.

   title = new Paragraph ("Planetary Comparison", titleFont);
   title.setAlignment (Element.ALIGN_CENTER);
   title.setSpacingAfter (18.0f);

   chapter = new Chapter (title, 0);
   chapter.setNumberDepth (0);
   chapter.setBookmarkTitle ("Appendix A: Planetary Comparison");

   p = new Paragraph ("The following table compares the nine solar " +
             "system planets in terms of orbit, diameter, and " +
             "mass. It only shows two planet entries because " +
             "I want you to add the remaining planet entries " +
             "to this table (as an exercise). Also, feel free " +
             "to expand this table with additional columns " +
             "that present other statistics, if desired.");
   p.setAlignment (Element.ALIGN_JUSTIFIED);
   p.setSpacingAfter (24.0f);
   chapter.add (p);

   PdfPTable table = new PdfPTable (4);

   table.addCell ("Planet");
   table.addCell ("Orbit (km)");
   table.addCell ("Diameter (km)");
   table.addCell ("Mass (kg)");

   table.addCell ("Mercury");
   table.addCell ("57,910,000");
   table.addCell ("4,880");
   table.addCell ("3.3e23");

   table.addCell ("Venus");
   table.addCell ("108,200,000");
   table.addCell ("12,103.6");
   table.addCell ("4.869e24");

   chapter.add (table);

   doc.add (chapter);

   doc.close ();
  }
}

After reviewing the source code, you might be wondering why chapter.setBookmarkOpen (false);—part of the code that creates the first chapter—is present. This method call exists to suppress the display of a chapter's sections on the Bookmarks pane. But Listing 15 adds no sections to any chapter. What gives?

The method call is a hint that the source code is unfinished. I believe the best way for you to understand this iText tool is to continue developing Listing 15. For example, after adding the remaining seven rows to the table in the final chapter (the appendix), add some color to that table. Also, add a section to each of the planet chapters that presents information on (and images of) the various moons that orbit the planet. You might even want to discuss the various spacecraft that have visited the planet. Only your imagination limits what you can do to this document with iText.

5. Conclusion | Next Section Previous Section