Dr. iText, Or: How I Learned to Stop Worrying and Love PDF

If you have read iText in Action (more specifically chapters 8 and 9), you know that I’m a filmbuff: I really like to watch movies from all over the world. Every year, my wife and I attend the Flanders International Filmfestival, and we try watching as many movies as possible. That is: we see 60 to 65 movies in less than two weeks time.
On top of this slight mental aberration, I also have some extra nerdy characteristics. For instance: I store all the movies and all the filmfestival screenings in a database. You can find out more about this database on the sample database page.
At JavaPolis I used this database as a resource for a web application demonstrating three different aspects of iText (watch the presentation). This web application allows you to produce some convenient reports (that is: if you intended to go to the 33th International Filmfestival in Ghent).
Let’s have a look at these reports:

Creating a report with basic building blocks

The first part of the web application I demonstrated at JavaPolis produces a tabular list of the complete filmfestival period. I created a simple HTML form where you can select different dates and different options. If you hit Print list, a Servlet will create a PDF document on-the-fly. The resulting PDF very much like this one: list.pdf. By changing (de)selecting some days and changing some options, you can create different variations of this list.
This example uses some of iText’s most interesting basic building blocks: some deep nested PdfPTables, Paragraphs for the movie titles, Lists and ListItems for the directors and screenings. You can learn more about this example on this page.

Creating a report with direct content

The list shown in the previous section gave you a very interesting day by day overview of the filmfestival program, but we can even do better. Let’s create a new PDF with as many pages as there are days, and organize all the screenings so that we can see which screenings overlap. I created another HTML form that calls another servlet, resulting in a PDF that looks like this one: calendar.pdf
In this example we’re writing lines and text to the direct content using low-level PDF functionality. The blocks indicating the time, place, and duration of every movie are added using the basic building block ColumnText. You can find out how it’s done on this page.

Creating an accreditation card with PDF forms

Whereas the first two examples in this web application involve PDF creation only, the third one deals with PDF manipulation. Suppose we have a template for an accreditation card. This PDF document contains an AcroForm; it has some text fields and some buttons. Some of the text fields can be filled out, one of them is read-only (with a gray background). The buttons act as placeholders for a photograph and a barcode.
Using the following HTML form, you can fill the form with a name (for example “Ingeborg Willaert”), a number (for example: “12345”), a type (”Guest” (0), “Student” (1), “Press” (2),...), an accreditation level (”No admittance” (0), “Press screenings only” (1),...), and a photograph. There’s also a checkbox to indicate if you want the form to be flattened, or not.
I made two examples where the accreditation form is filled out: not flattened and flattened. In the former, the form is still there: you can select the “Ingeborg Willaert” and enter a different name. In the latter, the form has been removed. You end up with a traditional PDF file without the AcroForm. In practice, you’ll use the first form example when you want to prefill the fields of a form that has to be completed/updated by the end-user; that’s what forms are about. The second example is convenient when the end-user isn’t supposed to change anything; in this case you use the form as a template.
To know how it’s done: go to this page.

But we mustn’t run before we can walk. Let’s first try some simple examples to get acquainted with the filmfestival database.

My first filmfestival PDFs

The filmfestival database is used to explain how the databases used in the examples on this Wiki work, for instance how to perform a custom query.

Paragraph

The example com.lowagie.filmfestival.test.FilmfestivalDatabaseTest1 wrote the titles of the movies in my database to the System.out:

FilmfestivalDatabase database = new FilmfestivalDatabase();
try {
  database.open();
  ResultSet rs = database.executeQuery("SELECT title FROM film_titles ORDER BY title");
  while (rs.next()) {
    System.out.println(rs.getString("title"));
  }
} catch (SQLException e) {
  e.printStackTrace();
}
database.close();

Let’s now reuse this example, and write the titles to a PDF document as different paragraphs.

FilmfestivalDatabase database = new FilmfestivalDatabase();
Document document = new Document(); // step 1
try {
  database.open();
  PdfWriter.getInstance(document, new FileOutputStream(FILENAME)); // step 2
  document.open(); // step 3
  ResultSet rs = database.executeQuery("SELECT title FROM film_titles ORDER BY title");
  while (rs.next()) {
    document.add(new Paragraph(rs.getString("title"))); // step 4
  }
} catch (SQLException e) {
  e.printStackTrace();
} catch (IOException e) {
  e.printStackTrace();
} catch (DocumentException e) {
  e.printStackTrace();
}
document.close(); // step 5
database.close();

This code snippet can be found in class MovieParagraphs; compiling and executing this code will result in the PDF document simple_paragraphs.pdf.

The 5 steps indicated in the comments are explained in section 2.1 of iText in Action, titled Generating a PDF document in five steps, will return in all the examples that create a PDF document from scratch. We can easily adapt the other test examples; for instance creating a List object with directors:

List

In class DirectorList we reuse the test example that gave us the list of directors of the movie All the Invisible Children. Step 4 now looks like the following code snippet:

ResultSet rs = statement.executeQuery();
List list = new List();
while (rs.next()) {
  list.add(rs.getString("name"));
}
document.add(list);

The result can be found here: simple_list.pdf.

PdfPTable

Finally, we take com.lowagie.filmfestival.test.FilmfestivalDatabaseTest3 and adapt it as follows:

FilmfestivalDatabase database = new FilmfestivalDatabase();
Document document = new Document(PageSize.A4.rotate()); // step 1
try {
  database.open();
  PdfWriter.getInstance(document, new FileOutputStream(FILENAME)); // step 2
  document.open(); // step 3
  FilmfestivalQuery q = new FilmfestivalQuery(
    FilmfestivalDatabase.getDays(),
    false,  // onlyPress
    false,  // noPress
    false,  // comp
    false,  // eXploreZone
    false); // alter
  FilmfestivalMovie movie;
  PdfPTable table;
  PdfPCell cell;
  Chunk imdb;
  for (int i = 0; i < q.getNumberOfDays(); i++) {
    table = new PdfPTable(new float[]{ 7, 7, 1 });
    cell = new PdfPCell(new Phrase(q.getDay(i)));
    cell.setBackgroundColor(new Color(0xC0, 0xC0, 0xC0));
    cell.setColspan(3);
    table.addCell(cell);
    for (Iterator iterator = q.getMovies(i).iterator(); iterator.hasNext(); ) {
      movie = (FilmfestivalMovie)iterator.next();
      table.addCell(movie.getTitle());
      table.addCell(movie.getScreening().toString());
      if (movie.getImdb().startsWith("?")) {
        table.addCell("");
      }
      else {
        imdb = new Chunk("imdb");
        imdb.setAnchor("http://imdb.com/title/tt" + movie.getImdb());
        table.addCell(new Phrase(imdb));
      }
    }
    document.add(table); // step 4
  }
} catch (SQLException e) {
  e.printStackTrace();
} catch (IOException e) {
  e.printStackTrace();
} catch (DocumentException e) {
  e.printStackTrace();
}
document.close(); // step 5
database.close();

You can download the full example here. The result is a PDF document simple_table.pdf with a 3-column table. The cells with a date have colspan 3, the other rows contain the title, the screening information, and if possible, a link to IMDB, the Internet Movie DataBase.
As you can see we have introduced a lot of new basic building blocks in this example: PdfPTable, PdfPCell, Phrase, Chunk. You can find the complete overview of all the available high-level objects in the book.

Conclusion

On this page, I have introduced you to the three parts of the web application that was demonstrated at JavaPolis (2006). Before we discuss these examples in detail, we made some simple PDF documents to get acquainted with the database and some of iText’s basic building blocks. We’ll learn more about these objects on the next page.

 
Back to top
filmfestival.txt · Last modified: 2007/06/05 16:46 by root