Modify Page Numbering behavior
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 has 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, putting page totals in page headers, etc. 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 me forcing a specific function signature for everyone to follow.
--
SooGuan - 27 Dec 2005