How To Customize Page Information

Not happy with ${#} and ${##}? Then do it yourself with scripts…

In order to know the total page count you need to wait until all pages have been rendered. You then need to go back and insert the values. Here’s a general technique for doing that by building a list of callback functions and then executing it at the end of rendering.

Report:On Render Begin
pageCount = 0;
pageFooters = new java.util.ArrayList();

Field():On Render End // this is the page count literal field
function fn(t,pageNo,pageTotal)
{
t.setText("Page “+pageNo+” of "+pageTotal);
}
fn.target = result.getLogicalElement(0);
pageFooters.add(fn);
++pageCount;

Report:On Render End
i = 1;
it = pageFooters.iterator();
while (it.hasNext())
{
fn = it.next();
fn(fn.target,i,pageCount);
++i;
}

At the beginning (Report onRenderBegin) we initialize the pageCount to 0 and create an empty list for holding the functions.

Each time we hit the field (in the page footer in this case) that should show the page info, we define a function to do the job and store it in the list. We then increment the pageCount (this would be in a different script if the field were not in the page footer).

Finally, when we get to the end (Report onRenderEnd) we iterate through the list getting each function, and call it with the appropriate parameters. Of course the text fields must be wide enough to hold the text (I suggest putting a literal like “Page 999 of 999” as the default value, because if you leave it empty there’s nothing to render and you won’t get a text element in the result to write over) because the wrapping and pagination have already been done before this substitution.

Note that fn.target is not a special name, you can add attributes on the fly to any JavaScript object, including functions.

Now you can do any kind of formatting of the numbers because the whole thing is in JavaScript.

Of course you can generalize this mechanism to any sort of post-processing - “reverse hide duplicates” which hides all but the last value, puts page totals in page headers, etc.

I’m naming this concept “temporal scripts” - scripts whose execution can be delayed to arbitrary points - eg. OnGroupEnd?, OnPageEnd?, OnSectionEnd?, OnReportEnd?. I was originally planning to add explicit support for temporal scripts, but it is simple enough in plain JavaScript and much more extensible than forcing a specific function signature for everyone to follow.

– SooGuan - 27 Dec 2005

To download necessary files for this recipe, refer to the attached ZIP package.
CustomizingPageInformation.zip (5.2 KB)