How to Render the Subreport
There are two important parts to handling subreports with the ReportViewer
control.The first part deals with the way the ReportViewer control finds the
definition of any subreports referenced by the main report. Essentially, the
ReportViewer control loads the subreport definitions using the same method used
to load the main report. When the ReportViewer control reads the report definition
from the file system based on a path specified in the ReportPath parameter,
the control will read the subreport definitions from the file system as well.
(When the report definition is loaded using the LoadReportDefinition method,
you must use the LoadSubreportDefinition method to load the report definitions
for any subreports.)
When the ReportPath parameter is used, the ReportViewer control looks for the subreports in the same folder in which it found the main report.The ReportViewer control uses the name of the subreport specified in main report definition as the name of the subreport definition file. It assumes a file extension of .rdlc. Even if you specify that the main report file has an .rdl extension, the ReportViewer control will still use an .rdlc extension for the subreport. So, to make the subreport code work properly, you must rename the subreport definition file from EmployeeAssignments.rdl to EmployeeAssignments.rdlc.
The second part of handling subreports deals with creating the data sets for
the subreport. Each time a subreport is rendered, you must use the local report's
Subreport-Processing event to supply code that creates the necessary data sets
for that subreport. When a subreport is rendered, this event fires. It's up
to you to handle this event properly, which brings us to the code between callout
A and callout B in Listing 2.This code assigns
a subroutine to serve as the event handler for the SubreportProcessing event.
In this case, the subroutine is named GalacticSubreportProcessingEvent-Handler.
GalacticSubreportProcessingEventHandler first gets the value for the Employee-Number
parameter passed from the main report to the subreport. The subroutine then
uses the EmployeeNumber parameter's value to create a result set and adds that
result set to the collection of data sources used by the subreport. As with
the main report, the name of the data set must match the name in the subreport's
definition.
With the necessary code in place, the application is now ready to render both
the report and subreport. When a user selects entries in the checked list box
and clicks the Render Report button, the user will get results similar to those
in Figure 2.
Rendering Behind the Scenes
In addition to being added as a visual control on a form, the ReportViewer control
can function as an object instantiated in code without a visual presence. When
used in this manner, you can use the Report-Viewer control to render reports
in any of the supported rendering formats, including spreadsheet (.xls), PDF,
and XML. You can then use these rendered reports within the application or write
them to a file. You can also render reports in Enhanced Meta-File (EMF) format
and send them directly to a printer. You can even render the report as an image
and use that image as the background to a control or form.
Listing 3 shows the code that makes our
sample report a background image in a form. As callout A in Listing
3 shows, the code uses a subroutine to create an instance of the ReportViewer
control, point the viewer at the report definition, and supply the required
data set. Although this code is similar to that used in Listing
1 and Listing 2, the rest of the code
in the subroutine differs from what you've seen so far. As callout B in Listing
3 shows, the subroutine defines an XML structure named deviceInfo. This
structure provides information (e.g., page size, margin size) required by the
various rendering formats. Next, the code prepares for the Render method, which
will place the rendered report's pages in a list of streams (one stream for
each page). The preparations include initializing the list of streams to an
empty list and providing a callback function that will create a new stream for
each new page.The callback function, which is named CreateStream, appears at
the end of Listing 3.
With the necessary preparations made, the subroutine finally calls the Render
method.The method's first parameter specifies the rendering format. As callout
C in Listing 3 shows, the format in this
example is Image. After the method is called, you can use the streams as desired.
In this case, the first and only stream is the first page of the Employee List
report, which is converted to a bitmap and assigned to the form's BackgroundImage
property. Figure 3 shows the result.
Reports Anywhere and Everywhere
The ReportViewer control is an extremely flexible tool. It supplies you with
a convenient way to display reports residing on a Reporting Services report
server. It also provides the means for you to render reports in a completely
self-contained environment, severing your ties to the report server. To borrow
an old advertising slogan, with the ReportViewer control, Reporting Services
reports can truly be everywhere you and your users want to be.
End of Article
Prev. page
1
[2]
next page -->