views:

2086

answers:

6

I have a SQLServer 2005 Reporting Services ServerReport deployed and frequently used by my Winforms app (Framework 2.0) via the ReportViewer control.

What I need is to provide a one-click print button from one of the forms of the app that triggers only the print dialog, without bringing up the ReportViewer.

I've been experimenting with rendering the report to a byte array, but I can't get pass that.

This report has multiple pages, so i don't know if the "Image" rendering that works for local reports it's going to work also for server reports.

I've been looking throw MSDN but there is only reference to local reports:

http://msdn.microsoft.com/en-us/library/ms252091(VS.80).aspx

And the little information that I can get on server side reports are using Web references to the ReportServer web service, and I don't want that.

http://blogs.msdn.com/bryanke/articles/71491.aspx

Is there any way to print a server report, using the print dialog, without showing the report viewer to the user (I don't mind if it's behind the scenes)?

A: 

I see this sample, but don't know if it suits your needs: http://www.gotreportviewer.com/EMFPrint.zip

Sam
Yes, that was pretty much the first hint I got, but note that this example is for local reports, not remote reports.In server reports there is no callback for the creation of pages and that was my problem, sorting out how to send all the pages.
David Lay
+6  A: 

Ok, Finally figured out.

check this link: Printing Reporting Services 2005 Reports

That blog post has almost everything that I needed, but I'm going to post the full answer here for references.

I ended up using the report viewer object behind the scenes, but only for convenience, since it's not required.

The first step is asking the user for the printer settings:

Dim doc As New Printing.PrintDocument()
AddHandler doc.PrintPage, AddressOf PrintPageHandler
Dim dialog As New PrintDialog()
dialog.Document = doc
Dim print As DialogResult
print = dialog.ShowDialog()
doc.PrinterSettings = dialog.PrinterSettings

Having that, we proceed to configure our report call: Modifying this string, you can get to print on any paper size and any orientation (switching height and width for landscape), but the report itself must be configured in the same page layout.

Dim deviceInfo As String = _
"<DeviceInfo>" + _
"<OutputFormat>emf</OutputFormat>" + _
"  <PageWidth>8.5in</PageWidth>" + _
"  <PageHeight>11in</PageHeight>" + _
"  <MarginTop>0.25in</MarginTop>" + _
"  <MarginLeft>0.25in</MarginLeft>" + _
"  <MarginRight>0.25in</MarginRight>" + _
"  <MarginBottom>0.25in</MarginBottom>" + _
"</DeviceInfo>"

Dim warnings() As Warning
Dim streamids() As String
Dim mimeType, encoding, filenameExtension, path As String
mimeType = "" : encoding = "" : filenameExtension = ""

Finally, we render the report with all its pages.

Note that if the report has only one page, the renderStream method is never used.

rpt_control is the report viewer control, previously configured and aiming at a server report.

Note allso that in this code we add pages to a list. This list is a global variable, since it's needed in the PrintPageHandler method.

Dim data() As Byte
rpt_control.ServerReport.SetParameters(_parametros)
data = rpt_control.ServerReport.Render("Image", deviceInfo, mimeType, encoding, filenameExtension, streamids, warnings)
pages.Add(New Metafile(New MemoryStream(data)))

For Each pageName As String In streamids
    data = rpt_control.ServerReport.RenderStream("Image", pageName, deviceInfo, mimeType, encoding)
    pages.Add(New Metafile(New MemoryStream(data)))
Next
doc.Print()

Until now, we haven't done any printing at all, this is actually handled by the PrintPageHandler method that we referenced earlier.

Dim pages As New List(Of Metafile)
Dim pageIndex As Integer = 0
Private Sub PrintPageHandler(ByVal sender As Object, ByVal e As PrintPageEventArgs)
    Dim page As Metafile = pages(pageIndex)
    pageIndex += 1
    e.Graphics.DrawImage(page, 0, 0, page.Width, page.Height)
    e.HasMorePages = pageIndex < pages.Count
End Sub
David Lay
The code here helped me get out of a rut i was in trying to set some batch printing up from SSRS. So kudos to you. Yes i know some time has passed since you posted this!
fortheworld
A: 

Hi, great article... i have small silly question here.. When we use this sample, if we open the webform from a different computer than server, what happens? will the document still be printed on the server or client machine? Please let me know.

My email id is [email protected]

Thanks & Regards, Sravan Kasyap Karanam.

Sravan Kasyap Karanam
The report is rendered on the server, but displayed and printed on the client.This approach is used to mantain an modify reports appart of the application, or for consume reports from many clients without duplicate the reports on each one.Server reports also benefit from scheduled notifications, data caching, and other good things of the report server engine on sqlserver.
David Lay
David,Thanks for the response. Well, i got occupied with other issues. Now i am with a question again. I did try this example. This works great on a Windows App. But, when i try the same on ASP.NET Web application, it is not able to find the Printer. If i comment the below step if (!printDoc.PrinterSettings.IsValid) { string msg = String.Format("Can't find printer \"{0}\".", printerName); Console.WriteLine(msg); return; }it enters into an infinte loop. Please help me with this. How to get this to work on a Web app?
Sravan Kasyap Karanam
True, this is spected. ASPNet printing must be handled on the browser, you can't control that from server side. This is why reports server provides a web interface with an activex control, but i don't know if it does printing as well as winforms.
David Lay
+1  A: 

2 caveats to the answer given by David above:-

1) The order in which the streams labels are returned on SQL2005 is usually from the second page to the last, but on a heavily loaded maching (e.g. production environment) it is quite possible for them to be returned in arbitrary order.

The stream ids take the form <reportname>_nn where nn is a number. This makes it a little tricky to sort since the report name will be alphabetic and the numbers are just short form, so page "myreport_2" will sort after page "myreport_10". Leading to my second caveat

2) On SQL 2005 the report suffixes start at 2, on SQL 2008 they start at 1 (for page 2)

oh, thanks for this insight. So far I haven't seen a situation when the streams came in arbitrary order... but I'm going to test this because it could be a problem. Not a big one, since all pages will be rendered at the end, but who knows what implications there could be.
David Lay
A: 

Thank you!!! Is was useful! Thanks

Dennis
this should be a comment
Russ Bradberry
Ya, but without rep he had no other way of saying thanks.
Ryan
+1  A: 

Folks trying to use this code with SQL Server 2008 R2 will find that it only prints only the first page of multi-page reports. There's a new "behavior" wherein the array returned to streamids is empty. Please let Microsoft know you care here:

https://connect.microsoft.com/SQLServer/feedback/details/573997/with-ssrs-2008-r2-microsoft-reporting-winforms-serverreport-render-method-returns-no-stream-identifiers-for-image-format#

BillVo
We just did an upgrade to SQL 2008 R2 last weekend and I hadn't seen this answer until now. I've spent half a day tearing my hair out before reading a little futher. Subsequently, I too have let MS know I care.
fortheworld