| Printable Version
Printing Reports Programmatically Using C# and SQL Server 2000 Reporting Services
By Bryan Keller
Summary: Learn a technique for
printing reports programmatically using the Reporting Services XML Web service
and C#.
Microsoft SQL Server 2000 Reporting Services is
Microsoft's latest entry into the Business Intellegence marketplace and it
joins a host of other BI products for SQL Server 2000. Reporting Services
is a new, server-based reporting platform that you can use to create and manage
tabular, matrix, graphical, and free-form reports that contain data from
relational and multidimensional data sources. The reports that you create can
be viewed and managed over a Web-based connection. As a developer, you have
several programming opportunities available to you through the Reporting
Services API. One of the most appealing aspects of Reporting Services is the
open and flexible Web service API (also known as the SOAP API) which
enables you to integrate existing features and capabilities of Reporting
Services into your own custom reporting and management tools for
Web sites and Windows applications. The SOAP API consists of close to
one-hundred different XML Web service methods that you can use to
integrate anything from report management to report rendering and execution
into your custom applications. In this article, I will focus on one programming
technique in particular: programmatically rendering a report and then
sending that report directly to a local or network printer
using C# and the Reporting Services Web service.
Before reading on, download the source
code.
Creating a Reference to the Web service
The first thing you need to do is add a Web reference
to the Reporting Services Web service that points to your report server. The
source code should already have a Web reference to a local report server
(localhost). If you have a remote report server, simply change the URL of the
Web reference. The end point for any Reporting Services Web service is
"http://servername/reportserver/reportservice.asmx". For you Web service
enthusiasts, you can access the end point through your browser with the
?wsdl directive to see the Web Service Description Language (WSDL) for the
Reporting Services Web service
(http://servername/reportserver/reportservice.asmx?wsdl).
The Render Method
Once you have added the appropriate Web reference, you
will have all of the Web methods at your disposal. The Web methods are methods
of the ReportingService class of the Web service proxy. To
access the Web methods, you need to instantiate a ReportingService
object and set credentials. A sample of this looks like the following:
ReportingService rs;
// Create proxy object and authenticate
Console.WriteLine("Authenticating to the Web service...");
rs = new ReportingService();
rs.Credentials = System.Net.CredentialCache.DefaultCredentials; |
Once you have created a proxy object for the Web
service, you can access the methods as you would any normal C# class. The
method that we are most interested in for the purpose of this article is
the ReportingService.Render method. This is the primary method
for rendering reports that have been published to the report server. The
syntax for the Render method is as follows:
public Byte[] Render(
string Report,
string Format,
string HistoryID,
string DeviceInfo,
[Namespace].ParameterValue[] Parameters,
[Namespace].DataSourceCredentials[] Credentials,
string ShowHideToggle,
out string Encoding,
out string MimeType,
out [Namespace].ParameterValue[] ParametersUsed,
out [Namespace].Warning[] Warnings
out string[] StreamIds);
Member of [Namespace].ReportingService
|
For more details about the various method arguments,
see Reporting Services Books Online.
In code, you need to render to the
Image output format designated by the Format argument. The value
of this parameter is a string, simply "IMAGE". To get Enhanced Meta File (EMF)
output, the kind of output you will need for printing, you also need
to specify device information for the call to Render. That
device information should be passed as an XML string for the DeviceInfo
argument and should look like
"<DeviceInfo><OutputFormat>EMF</OutputFormat></DeviceInfo>".
The Render method returns the report as a base 64-encoded byte array. This
array of bytes can be used to perform a number of functions including saving
the output to a file on the hard drive, or more importantly, sending the bytes
as a stream to a printer.
The sample code renders one of the report samples that
ships with Reporting Services: the Company Sales sample report. Once you have
effectively used the Render method to render a report, you can
begin to think about how to print that report programmatically.
Printing the Report Programmatically
There are a few key challenges here in order to be
able to print a report successfully using C# and Reporting Services. One
challenge is figuring out how to print in the .NET Framework using C#. In the
sample code included with this article, I use the classes of the
System.Drawing.Printing namespace in order to send EMF output to a
printer. The source code can show you how it all comes together. From a
Reporting Services standpoint, the key challenge is determining how many pages
there are in the report. The SOAP API for Reporting Services lacks the ability
to evaluate a report's number of printed pages through any exposed report
properties. So the trick is to determine how many pages there are through some
other means. Fortunately, the SOAP API does return an array of stream IDs
whenever Render is called. What are these stream IDs you ask?
Well, when EMF output is selected, the Render method returns
the results of the rendered report as a byte array, but it only sends back
the first page. Subsequent pages are associated with the report as streams with
accompanying stream IDs. By counting the number of StreamIDs in
the resultant string array, you can determine how many pages are in the report.
The following code should give you the number of pages:
// The total number of pages of
the report is 1 + the streamIDs
int m_numberOfPages = streamIDs.Length + 1;
|
Once you know how many pages you are dealing
with you can call the Render method for each page in the
report and send that page to the printer. You can render specific pages using
device information. The device information for this is StartPage. In
the sample code, the device information for each subsequent call to render
(that is each call after the original one) looks like
"<DeviceInfo><OutputFormat>EMF</OutputFormat><StartPage>current
page </StartPage></DeviceInfo>". After each page is
rendered, you load the page (set of rendered bytes) into an array of
pages, a multi-dimensional array of bytes, and process that array. For each
byte array, you generate a memory stream and load an image
of that memory stream into the print document. From there you
can print each page. Printing using this technique is not for beginners,
so you may want to study the source code and consult you .NET Framework
Developers Guide for more information. See the "References" section at the
end of this article for some recommended reading.
One more thing to remember is that you will need to
replace the printer name placeholder in the source code with a valid printer
name for your system:
static void Main(string[] args)
{
PrintExample pe = new PrintExample();
pe.PrintReport(@"PrinterName");
} |
Conclusion
Okay so get your hands dirty with some code, that
is really the whole point of this article anyway! Seriously, I hope this
provided you with some insight into printing reports programmatically using C#
and Reporting Services. The Web service and its methods expose a rich set
of operations that enable you to draw on the complete functionality of the
report server and allow you to create custom tools for any part of the report
life cycle, from management to execution. I highly encourage you to not only
get involved in programming with XML Web services, but to experiment with tools
that harness the power of the Reporting Services Web service and start
integrating reporting into your current development projects.
Resources
Reporting Services Books Online on MSDN:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/RSPORTAL/HTM/rs_gts_portal_3vqd.asp?frame=true
System.Drawing.Printing namespace on MSDN:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemdrawingprinting.asp?frame=true
Reporting Services official Web site:
http://www.microsoft.com/sql/reporting
XML Web Services documentation on MSDN:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconaspnetbuildingwebservicesaspnetwebserviceclients.asp?frame=true
Download the Eval version of Reporting Services:
http://www.microsoft.com/downloads/details.aspx?FamilyId=BA517C01-2E2F-4BC7-84AF-149B7637F807&displaylang=en
|