Print Properties
6 - Table Iterations

Inforama tutorial

You can download the Inforama project files for this example by clicking the attachments link at the bottom of this page.

 

Inforama has the ability to iterate datasets to duplicate document elements such as tables. This can be useful where a list of items relating to a customer or account need to be listed.

 

Simple Table Iterations

In this example we'll create a simple list of films filtered by rating. To begin with, create a new parameter called file_rating and a new dataset called film_by_rating with the following SQL statement...

SELECT title, length, rental_rate, special_features FROM film WHERE rating = '$P{film_rating}'

And now create a new letter template called FilmsByRating. Add an introduction paragraph at the top of the document and follow it will a new 4 column by 1 row table as shown in figure 1.

Figure 1: Simple table iteration command

 

As you can see the table is preceeded by the command $iterateRows{film_by_rating} which tells the Inforama engine to iterate the following table with the dataset between the braces which in this case is film_by_rating. When this document is previewed it will appear as in figure 2.

 

Figure 2: Simple table iteration preview

 

This is a very basic table and it would be nice to add a header row which shows the column names. Create a new row in the table before the existing row and enter the column names in this new row. You can also format this new row in whatever way you want it to appear as shown in figure 3.

 

Figure 3: Simple table command with header

 

The command has now been changed to $iterateRows{film_by_rating, 2}. The second parameter in this command indicates that the second row in the table needs to be iterated when generating the table. We have also changed the length and rental_rate columns to align their data to the right. The length field also includes the text mins after the value and the rental_rate field is preceded by the euro symbol.

Now when previewed the document will appear as shown in figure 4.

 

Figure 4: Simple header table iteration preview

 

Sub Tables

In many cases it's necessary to have tables within tables and this is possible with Inforama. Begin by creating a new parameter called numInCategory in the project. Next create a new dataset called allCategories with the following SQL Statement...

select * from category

Create another new dataset called filmsInCategory with the following SQL Statement...

select film.* from film, film_category where film.film_id=film_category.film_id and film_category.category_id = $F{allCategories.category_id} limit 0, $P{numInCategory}

The second dataset refers to the first in the where clause and limits the output of films in the category to the number specified by the numInCategory parameter.

Now you can create the document template which will include the table as shown in figure 5.

 

Figure 5: Sub table template

 

The first table has a single cell and is preceded by the command

 

$iterateRows{allCategories}

 

Within the cell, the name of the current category is displayed and after this another 3 column by 2 row table is created. The instruction before this table is

 

$iterateRows{filmsInCategory, 2}

 

When the document template is previewed it will appear as shown in figure 6.

 

Figure 6: Preview of the sub table

 

Using Table Templates

If you intend to format several tables using the same styling you might want to consider using a table template. This will allow you to refer to the same table template from any number of documents. You can also use elements of the table templates without having to use all of them.

Begin by clicking the File – New template... to open the new template dialog as shown in figure 7.

 

Figure 7: New template dialog

 

Enter the name you want to give the new template in the Template name field and make sure that the Template type dropdown list has Table selected. Click the Create button and the new template will open as an OpenOffice document in the main editor and the new template will appear in the tree of documents in the documents frame.

In the OpenOffice document create a new 2 column by 1 row table and format the cells as shown in figure 8.

 

Figure 8: The table template

 

The text in the first column has red text and we'll use this to display information in a table in another document. Create a new dataset called customerRentals with the following SQL Statement.

select film.film_id, film.title, rental.rental_date, film.rental_duration, rental.return_date from film, rental, inventory where film.film_id=inventory.film_id and inventory.inventory_id=rental.inventory_id and rental.customer_id = '$P{customerId}' order by rental.rental_date

And create another dataset called customer with the following SQL Statement.

select customer.first_name, customer.last_name, customer.email, city.city, address.address, address.address2, address.phone from customer, address, city where customer.address_id=address.address_id and city.city_id=address.city_id and customer.customer_id = '$P{customerId}'

Next create a new letter fragment called customerDesc as shown in figure 9.

 

Figure 9: Customer paragraph

 

 

 

 

And follow this by creating a new letter template

 

Figure 10: The main letter template

 

The first line in this document tells the Inforama engine to include the customerDesc fragment. The second line outputs the customer id and the third line before the table is the following instruction.

$createTable{ customerRentals, $template{ *.*->customerRentals.value('return_date') == null ? rentalCells.at(0,0) : rentalCells.at(1,0) } }

 

The first parameter to this call is the name of the dataset to be used to create the table. The second parameter checks if the return_date field in the customerRentals dataset is null. If it is then the first cell in the rentalCells template should be used otherwise the second one should be used. The resulting document will appear as shown in figure 11.

 

Figure 11: The table template preview

 

As you can see we've set one of the rental rows to have a null return_date value with the result that the row uses the first column in the table template and the text is displayed in red.

 

Customising Table Output from Java

As you imagine, the code required to be used in-line in the letter templates can get quite verbose if there are a number of checks to be made in order to determine what template to use. In these cases it's useful to create a custom Java class which will take care of the code to apply the formatting.

To begin this example create a new Java class called CustomTableFormatter as listed below.

 

package org.inforama.formatters;

 

import java.util.Enumeration;

import java.util.Properties;

 

import org.in4ama.documentautomator.DocumentRepository;

import org.in4ama.documentautomator.documents.xslfo.templates.XslFoTableTemplate;

import org.in4ama.documentengine.format.table.DataSetTableFormatter;

 

public class CustomTableFormatter extends DataSetTableFormatter {

 

/** Don't include the ID column in the result table */

@Override

public boolean isCurrentIncluded() {

  int currentCol = getCurrDSCol();

  return (!dataSet.getColumnName(currentCol).equalsIgnoreCase("film.film_id"));

}

/** Gets the number of columns that should appear,

* since we don't include the "id" column, subtract "1" from what would be

* returned by default.

*/

@Override

public int getNumCols() {

   return super.getNumCols() - 1;

}

/** Change the column widths of the first and fourth column

* (column indexes start with 0, hence "2" and "0" in the conditions) */

@Override

public Properties getColumnProperties(int colIdx) {

  Properties properties = super.getColumnProperties(colIdx);

  if (colIdx == 2) {

    properties.put("column-width", "3cm");

  } else if (colIdx == 0) {

    properties.put("column-width", "8cm");

  }

  return properties;

}

/** Change the properties of the cell contents in the first column,

* use the "rentalCells" template's first cell.

*/

@Override

public Properties getCurrentContentProperties() {

  Properties properties = super.getCurrentContentProperties();

  DocumentRepository documentRepository = evaluationContext.getProjectContext().getDocumentRepository();

  XslFoTableTemplate template = (XslFoTableTemplate)documentRepository.getDocument("rentalCells",  XslFoTableTemplate.TYPE);

  if (getCurrentColumn() == 0) {

    properties = template.getContentProperties(0, 0);

  }

  return properties;

}

 

/** Change the properties of the cells in the first column,

* use the "rentalCells" template's first cell. For the other

* cells use the properties of the first row's last cell in the

* "myTemplate1" template.

*/

@Override

public Properties getCurrentCellProperties() {

  Properties properties = super.getCurrentCellProperties();

  DocumentRepository documentRepository = evaluationContext.getProjectContext().getDocumentRepository();

  XslFoTableTemplate template = (XslFoTableTemplate)documentRepository.getDocument("rentalCells",  XslFoTableTemplate.TYPE);

  if (getCurrentColumn() == 0) {

    properties = template.getCellProperties(0, 0);

  } else {

    properties = template.getCellProperties(1,0);

  }

  return properties;

}

 

}

 

 

This custom class extends the Inforama DataSetTableFormatter class and which, in turn, implements the TableFormatter interface. If you look at the getNumCols method you'll see that we will display all of the fields less one as we don't want the film_id field to appear in the resulting table. Now take a look at the isCurrentIncluded field and you'll see that if the class is processing the column who's name is film.film_id it will return false indicating that the field shouldn't appear.

The getColumnProperties method shows how the individual cell properties can be set. In this case the cells in columns 0 and 2 are set to non-default values and the others are left as the default values. In the getCurrentCellProperties method it's possible you can see that the table template we created earlier is used to load the properties for the cell.

In order to reference this class from the document templates you will need to use the following command.

 

$createCustomTable{org.inforama.formatters.CustomTableFormatter, customerRentals}

 

This simplifies the template command quite a bit and moves the logic into the Java class where it can be reused if necessary.

 

 

 

 

 

984 Views, 1 Attachments 1 Attachments

  • Comments
Copyright © 2008 - 2010