Tables Tutorial
In this tutorial you'll learn how to create simple tables for your
reports.
Each table must be declared inside document's body
(a table isn't allowed inner footers or headers), and is defined
by a
beginTable - endTable block. The number of columns of
the table is
a priori value, passed to the
beginTable
call. Optionally, at this call, you can define each column's width.
If not defined, for most ReportGenerators, the table will have full
page width (the exception to this is TeXReportGenerator, where the
table will be with the needed width to have its content, even if
greater than the page's width).
Let's declare a 4 column's table:
reportGenerator.beginTable(4);
reportGenerator.endTable();
A table is created with the definition of its
rows. Rows can be of two row types: one for headers, defined by
beginTableHeaderRow() - endTableHeaderRow() blocks, and the
other for normal table rows (usually colored with even/odd row
colors), defined by
beginTableRow() - endTableRow blocks.
As said above, a header row is declared with a
beginTableHeaderRow - endTableHeaderRow. There's no limit of
how many header rows a table can have, and you can declare a table
header row at any desired table line, not only at the first ones
(it's useful, for example, to generate subtitle separators between
table rows).
A header column could be optionally expanded
within multiple columns. Obviously, when colspan is used, the next
column will be the one relative to the previous plus its colspan
value, if any. Let's create our table header lines:
reportGenerator.beginTable(4);
reportGenerator.beginTableHeaderRow();
reportGenerator.addTableHeaderCell("Solar system", 4);
reportGenerator.endTableHeaderRow();
reportGenerator.beginTableHeaderRow();
reportGenerator.addTableHeaderCell("Type");
reportGenerator.addTableHeaderCell("Name");
reportGenerator.addTableHeaderCell("Temperature (K)");
reportGenerator.addTableHeaderCell("Orbital Period (~days)");
reportGenerator.endTableHeaderRow();
reportGenerator.endTable();
As can be seen in the above code, we created two
header lines, the first one with the table title, and the second one
with each column title. If you think the columns title declaration is
too much verbose (and it really is), you can use the function
addTableHeaderRow which receives the list of columns as
parameters (and, of course, do the same code as above internally).
The main disadvantage of
addTableHeaderRow is the memory and
processor to create and use the list passed as parameter. I usually
prefer the verbose way used above, but it's to you consider the
tradeoffs that bother you must.
Let's go back to our table, we must create its
content lines. For simplicity, the values used at the current
tutorial are hardcoded in the bellow variable, but in real world
cases they'll be, of course, got from files or databases. You should
add them to the report at the time you read them from its source
(file or result set, for example).
private static final String[][] solarSystem = {{"Star", "Sun", "5778", "-"},
{"Planet", "Mercury", "100-700", "88"},
{"Planet", "Venus", "737", "225"},
{"Planet", "Earth", "184-330", "365"},
{"Planet", "Mars", "130-308", "687"},
{"Planet", "Jupiter", "165", "4333"},
{"Planet", "Saturn", "134", "10759"},
{"Planet", "Uranus", "76", "30687"},
{"Planet", "Neptune", "72", "60190"},
{"Dwarf Planet", "Ceres", "168-235", "1681"},
{"Dwarf Planet", "Pluto", "~33-55", "90570"},
{"Dwarf Planet", "Haumea", "lesser 50", "103774"},
{"Dwarf Planet", "MakeMake", "~32-44", "112897"},
{"Dwarf Planet", "Eris", "~30-55", "203830"}};
Let's iterate through it and create the row lines:
for (String[] corpse : solarSystem) {
reportGenerator.beginTableRow();
reportGenerator.addTableCell(corpse[0]);
reportGenerator.addTableCell(corpse[1]);
reportGenerator.addTableCell(corpse[2]);
reportGenerator.addTableCell(corpse[3]);
reportGenerator.endTableRow();
}
as you can see, we added the each column element with
addTableCell. You can also add table elements by defining a
beginTableCell - endTableCell block. But, as in our
current case it's just a single string, it's easer to just use a
addTableCell call.
With it we have the full table created. But the
repetition of types maybe aren't gently for some purposes, so we
should group them using row spans. You can span a column through
as many rows as you need, the only limitation is that the greater
spanned column must be the left most one. When a spanned through
row column is declared, the respective column on the next row should
not be declared (ie: for the present case, the next row first
beginTableCell() call will be relative to the second
column, not to the first one).
Let's change the generation code a bit:
String lastType = null;
for (String[] corpse : solarSystem) {
reportGenerator.beginTableRow();
/* Let's check if it's a new type */
if (!corpse[0].equals(lastType)) {
/* New type, must group its elements with a rowspan */
lastType = corpse[0];
int rowspan = 1;
if (useRowSpan) {
if (corpse[0].equals("Star")) {
rowspan = totalStars;
} else if (corpse[0].equals("Planet")) {
rowspan = totalPlanets;
} else if (corpse[0].equals("Dwarf Planet")) {
rowspan = totalDwarfPlanets;
}
}
reportGenerator.addTableCell(corpse[0]);
}
reportGenerator.addTableCell(corpse[1]);
reportGenerator.addTableCell(corpse[2]);
reportGenerator.addTableCell(corpse[3]);
reportGenerator.endTableRow();
}
There are yet some things your need to known
about tables. You can define the table's border width and color by a
reportGenerator.setTableBorderStyle(2.0f, ReportColors.BLACK);
call before the
beginTable - endTable block (remember that the
ReportGenerator is a state machine, so, once defined, the table
style will affect all tables defined after that, until redefined
again with a new
setTableBorderStyle call).
The same apply to table colors. Usually row colors
are alternated between even and odd row colors, which can be defined
by
setEvenRowColor and
setOddRowColor. You can
change this behaviour by either setting both to the same color or
by setting
setRowColor which, if defined, will make to ignore
even and odd colors. You can also use
setRowColor to highlight
a single row line. Let's, for example, highlight the line relative to
Earth:
(...)
for (String[] corpse : solarSystem) {
if (corpse[1].equals("Earth")) {
/* Highlight earth line color. */
reportGenerator.setRowColor(ReportColors.ORANGE);
} else {
/* Use Even/Odd colors */
reportGenerator.setRowColor(null);
}
reportGenerator.beginTableRow();
(...)
}
That's it for now.
Here's the pdf generated by NervalReports' PDFReportGenerator:
And
here you can download the full code of this tutorial.