16 April 2015

SSRS: Direct Printing to Printer

Sometimes we don't need print preview. How to allow user print directly to a printer without viewing it first on screen. ReportViewer control is needed on this example, but I don't want to modify the existing UI. So we'll also added ReportViewer runtime and make it hidden.
This is report that we want to print:

Arrange control as below:
Then type this code behind:
Imports System.Drawing.Printing 
Imports System.Drawing.Imaging 
Imports System.IO 
Imports Microsoft.Reporting.WinForms

Public Class frmPrintReport
    Dim pages As New List(Of Metafile)
Dim pageIndex As Integer = 0
Dim doc As New Printing.PrintDocument()
Dim ReportViewer1 As New ReportViewer

    Private Sub frmPrintReport_Load(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles MyBase.Load

        Button1.Text = "Print"
        With ReportViewer1
            .Visible = False
            .ProcessingMode = ProcessingMode.Remote
            .ServerReport.ReportPath = "/HRD/Attendance Report"
            .ServerReport.ReportServerUrl = New _
        End With

    End Sub

    Private Sub PrintPageHandler(ByVal sender As Object, _
        ByVal e As PrintPageEventArgs)
        Dim page As Metafile = pages(pageIndex)
        pageIndex += 1
        Dim pWidth As Integer = 827
        Dim pHeight As Integer = 1100
        e.Graphics.DrawImage(page, 0, 0, pWidth, pHeight)
        e.HasMorePages = pageIndex < pages.Count
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles Button1.Click
        Dim doc As New Printing.PrintDocument()
        doc = 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

        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>" & _

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

        'Input parameter report
        Dim DateFrom As Date = CDate("4/15/2015")
        Dim DateTo As Date = CDate("4/15/2015")

        Dim parmDateFrom As New ReportParameter("DateFrom", DateFrom)
        Dim parmDateTo As New ReportParameter("DateTo", DateTo)
Dim parmSO1(1) As ReportParameter
        parmSO1(0) = parmDateFrom
        parmSO1(1) = parmDateTo

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

        For Each pageName As String In streamids
            data = ReportViewer1.ServerReport.RenderStream("Image", _
                   pageName, deviceInfo, mimeType, encoding)
            pages.Add(New Metafile(New MemoryStream(data)))
    End Sub
End Class

Then lets try, I'm using pdf printer to print.


Click here if you like this article.

Related Article:
  1. Installing Business Intelligence SQL Server 2005
  2. Creating Report with SQL Server Reporting (Wizard)
  3. Creating Report with SQL Server Reporting (without wizard) | Part 1
  4. Creating Report with SQL Server Reporting (without wizard) | Part 2
  5. Design Layout Report
  6. Creating Parameter for Filtering
  7. Stored Procedure as Report Data Source
  8. Parameter Data List from Database Query
  9. Creating Report Group
  10. Create Sequence Number Using RowNumber Function
  11. Uploading Report FIle (.rdl) to Report Server
  12. Remove Report Page Break/Page Break 
  13. Query to Generate Subscription List 
  14. Direct Printing to Printer
Click here if you like this article.


Thomas Minniear said...

Is there a way to clarify whether the image is in portrait or landscape? right now i have a report that is in landscape, but it prints in portrait.

rani irsan said...

@Thomas: Try to add this code:
doc.DefaultPageSettings.Landscape = True
before this

Max Bucht said...

Hi Rani,

Nice code! Any idea how you could avoid the dialog for selecting a printer to come up? I would like to print directly to the Default Printer.

Thanks and best regards,


rani irsan said...

@Max: Please try to remove this part:

Dim dialog As New PrintDialog()
dialog.Document = doc
Dim print As DialogResult
print = dialog.ShowDialog()

doc.PrinterSettings = dialog.PrinterSettings

Ian Piddington said...

Hi Rani

I am trying to generate picking reports, so when I click the 'Print' button I have to first create a pick run and allocate it to some data for picking then print the Pick Report.

The report prints just fine the first time I click the Print button, but the second time I get this error

This report requires a default or user-defined value for the report parameter 'Picking_Number'. To run or subscribe to this report, you must provide a parameter value. (rsReportParameterValueNotSet)

If I close and reopen the Winform it prints the first one fine again then throws the same error.

What might be wrong?



rani irsan said...

Hi Ian,

From error message, it seems that parameter named "Picking_Number" is not provide. Does it have default value? And how did you provide the parameter value? Maybe it should be provided every time clicking the print button.

Ian Piddington said...

Hi Rani

it's passed as a parameter

Dim parmPickNumber As New ReportParameter("Picking_Number", PickNo)
Dim parmSO1(0) As ReportParameter
parmSO1(0) = parmPickNumber

If I debug I can see it getting a value. As I commented the first time you click print the routine works fine, it is just the second and subsequent times.

The main difference from your code would be, instead of having 'print' code directly on the button I have it in its own Private Sub that is called from within the code that generates teh picking number itself. That code is called when the button is pressed.