Hi Wendy et al,
It's the weekend now and I've had a chance to work on this a bit...
Here's the deal: Chris' hack gave you the group page numbers, Wendy, but not the group totals, right Well, by adapting his function, and using it to preprocess the report in a silent run, you can get total number of pages for the group.
This is why I said it would take some surrounding code (you couldn't do this straight from reportserver, you'd want an app that could run the report once without showing it and then again for the "real" run.
In this sample (which is all I've had time to do) I'm just shooting a log of the group page numbers to a text file. Generally I'd want to send the results to an xml file, and the name of the file would be a hidden parameter to the report.
On my first run, I would erase the file if it existed (we'd generate a temp file name anyway, but it doesn't hurt to check) and then give this filename to the report as a parameter. I'd write to the file using a really simple xml syntax. The function you see below is my adaptation of Chris' for this purpose.
On the second run, I would still want that parameter so I could load up this file as a document and grab the values, matching them to the group values, with some equally simple XPATH. The groupNo var you see would make the xpath bizarrely simple, actually, because you could just use it for the index into the nodes collection -- you wouldn't really even need to store the group name value for name identification purposes even though I'm doing it in my text file here.
I would keep the two functions separate. They would "know" which run we were on (whether preprocess or real) with a second, boolean, parameter.
Both functions could send values back on both runs, the adapted version of function #1 sending back group page number as you see here and function #2 sending the group page total.. The page values coming back from function #2 would be spurious on the preprocess run, but that wouldn't affect anything.
The reason I'm not writing the second function here is that I'm not sure that my method of writing to an xml temp file is going to be the way that other people want to do this -- maybe there's another approach writing to a table or something, it's just the way I tend to do things. Also some other method would work better for a server report. IAC you can write code that runs during a report, therefore something like this has to be possible. I think the main idea (preprocess to get the values, then do your real run) should be adaptable.
(FWIW I would get around the shared issue that Chris talks about, at least for these values, if I were writing to a table, by adding a key representing this run to "my" rows in the table. But where possible a private little XML file is sure handy <s>. )
I *don't* think it would be a good idea to do a preprocess using a custom renderer unless you could guarantee that pagination would be the same. So, in the case of printing, to make sure that pagination was exactly like what you would get when you printed, I'd have a second printer setup with the same attributes that went out to an empty port or printed to file or something for run #1.
(It would be nice if there was a hook to run the report in a no-output mode like this, for just this purpose, with correct pagination, in the default renderers. As far as I know RS doesn't provide this feature, so we're just inventing it until they get around to it <s>.)
So, okay, to review, Chris' instructions and function look like this:
Code Snippet
(http://blogs.msdn.com/chrishays/archive/2006/01/05/ResetPageNumberOnGroup.aspx)
Step 1: Make sure there's a textbox in the report which contains the group expression
Step 2:
Add shared variables to track the current group and page offset
Shared offset as Integer
Shared currentgroup as Object
Step 3: Add a custom function to set the shared variables and retrieve the group page number
Public Function GetGroupPageNumber(group as Object, pagenumber as Integer) as Object
If Not (group = currentgroup)
offset = pagenumber - 1
currentgroup = group
End If
Return pagenumber - offset
End Function
Step 4: Use the function in the page header or footer
=Code.GetGroupPageNumber(ReportItems!Category.Value,Globals!PageNumber)
In my Step 4, the function you put in the page header or footer looks like this (new last arg):
Code Snippet
Code.GetGroupPageNumber(ReportItems!txtGroupHeaderItem.Value ,Globals!PageNumber,Globals!TotalPages )
I'll highlight my code additions below:
Code Snippet
Shared offset as Integer
Shared currentgroup as Object
Shared groupNo As Integer = 0
Dim sw As System.IO.StreamWriter
Public Function GetGroupPageNumber(group as Object, _
pagenumber as Integer, total As Integer) as Object
If Not (group = currentgroup)
If groupNo = 0 Then
sw = New System.IO.StreamWriter("c:\temp\TestFile.txt")
Else
sw.WriteLine("Group " & currentgroup & " last page: " & CSTR(pagenumber-1))
End If
groupNo += 1
offset = pagenumber - 1
currentgroup = group
End If
If (pagenumber = total) Then
sw.WriteLine("Group " & currentgroup & " last page: " & CSTR(total))
sw.Close()
sw = Nothing
End If
Return pagenumber - offset
End Function
You can see there isn't anything tricky here; the sample output gives you a set of "last pages" which you can then use, with subtraction, to figure out how many pages were in each group. For example, my output looks like this:
Group A last page: 1
Group B last page: 2
Group C last page: 3
Group D last page: 4
Group E last page: 30
Group F last page: 44
Group G last page: 45
Group H last page: 50
Group I last page: 51
Group J last page: 52
Group L last page: 55
Group M last page: 56
Group N last page: 61
Group O last page: 66
... so you can see that A, B, C, and D had 1 page each, E had 26 pages, etc.
>L<