"Any ideas?" is the most frequently-asked question in technical forums. My answer is: yes.

A small present for Ludek: RunReports revision

I mentioned that _ReportListener's .RunReports method contained a private array member property holding page information, with the idea that running a collection of reports and all the pagination options, old and new, available in VFP might deserve some customized handling.  It was just stubbed in, originally, in the hopes that somebody, somewhere, would get the idea that this took work of a non-generic (trans: non-shippable) nature, but still worth doing.

In SP2, the contents of the array will be a bit easier for users to customize, and a bit more useful even in the base _ReportListener representation -- so the member is now marked PUBLIC. 

The array is easier to customize because .RunReports calls a hook method, .adjustReportPagesInfo(m.tiReportIndex, m.tcClauses, m.toListener), to adjust the array contents on each report pass during a .RunReports processing action. It's more useful in the base (I hope) because it is adjusted to two-dimensional contents by this method, and filled with a report-specific last page number in the first element and a cumulative report run total in the second element.

As the comments in the new method will indicate, this implementation is still a sketch.  There are lots of other ways you might decide to handle pagination for a multi-report page run, depending on whether you're using NORESET, NOPAGEEJECT, one listener, multiple listeners, mixed runs with some listeners and some non-object-assisted old-style reports... all of which .RunReports allows you to do.

Have at it, with my blessings.

What's it for?

If you have a properly-scoped instance of _ReportListener running your reports (note: I did not say serving as the OBJECT reference for each report, I'm talking about the listener with the .RunReports method!) you can get a look at the contents of this collection afterwards and... do what with it? Well, for one thing, you could do a custom preprocess run, setting listenertype to -1 for your object reference listeners, with great performance and full pagination information at your disposal for a second, displayable run. 

If a report is truly a document section, you can think of each report as a custom page number set ("reset on group", where each report in the run is a group, even though there is no group expression involved).  If (again) your _ReportListener instance is properly scoped, you can reference this collection for custom Page X of Y this section, Page A of B total report behavior.

Ludek was using PDFListener (which, by default, uses old-style reporting); the array will give him some access to per-report page totals that will be more consistent between old- and new- style REPORT FORM commands, even in its sketchy_ReportListener default implementation:

   IF ISNULL(m.toListener)
     THIS.reportPages[m.tiReportIndex,1] = _PAGENO
.reportPages[m.tiReportIndex,1] = m.toListener.PageNo

But wait there's more...

SP2 is also shipping with a new class called fxResetPageTotal, which handles similar chores for the "reset on group" pagination improvements in a single report. But that's another post.

Did you think other people got this in-the-box?

How do you suppose you do this same stuff in Reporting Services reports?  That's definitely another post.