Print Rdlc Report Without Showing Reportviewer Control

Print RDLC Report without showing ReportViewer Control

You can print an RDLC report programmatically by using LocalReport object and CreateStreamCallback callback function. Here is a complete Microsoft docs walkthrough which you may find useful:

  • Walkthrough: Printing a Local Report without Preview

To make it easier to use, I've created a Print extension method which you can easily use it this way:

this.reportViewer1.LocalReport.Print();

Here is the extension method:

using Microsoft.Reporting.WinForms;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Printing;
using System.IO;

public static class LocalReportExtensions
{
public static void Print(this LocalReport report)
{
var pageSettings = new PageSettings();
pageSettings.PaperSize = report.GetDefaultPageSettings().PaperSize;
pageSettings.Landscape = report.GetDefaultPageSettings().IsLandscape;
pageSettings.Margins = report.GetDefaultPageSettings().Margins;
Print(report, pageSettings);
}

public static void Print(this LocalReport report, PageSettings pageSettings)
{
string deviceInfo =
$@"<DeviceInfo>
<OutputFormat>EMF</OutputFormat>
<PageWidth>{pageSettings.PaperSize.Width * 100}in</PageWidth>
<PageHeight>{pageSettings.PaperSize.Height * 100}in</PageHeight>
<MarginTop>{pageSettings.Margins.Top * 100}in</MarginTop>
<MarginLeft>{pageSettings.Margins.Left * 100}in</MarginLeft>
<MarginRight>{pageSettings.Margins.Right * 100}in</MarginRight>
<MarginBottom>{pageSettings.Margins.Bottom * 100}in</MarginBottom>
</DeviceInfo>";

Warning[] warnings;
var streams = new List<Stream>();
var currentPageIndex = 0;

report.Render("Image", deviceInfo,
(name, fileNameExtension, encoding, mimeType, willSeek) =>
{
var stream = new MemoryStream();
streams.Add(stream);
return stream;
}, out warnings);

foreach (Stream stream in streams)
stream.Position = 0;

if (streams == null || streams.Count == 0)
throw new Exception("Error: no stream to print.");

var printDocument = new PrintDocument();
printDocument.DefaultPageSettings = pageSettings;
if (!printDocument.PrinterSettings.IsValid)
throw new Exception("Error: cannot find the default printer.");
else
{
printDocument.PrintPage += (sender, e) =>
{
Metafile pageImage = new Metafile(streams[currentPageIndex]);
Rectangle adjustedRect = new Rectangle(
e.PageBounds.Left - (int)e.PageSettings.HardMarginX,
e.PageBounds.Top - (int)e.PageSettings.HardMarginY,
e.PageBounds.Width,
e.PageBounds.Height);
e.Graphics.FillRectangle(Brushes.White, adjustedRect);
e.Graphics.DrawImage(pageImage, adjustedRect);
currentPageIndex++;
e.HasMorePages = (currentPageIndex < streams.Count);
e.Graphics.DrawRectangle(Pens.Red, adjustedRect);
};
printDocument.EndPrint += (Sender, e) =>
{
if (streams != null)
{
foreach (Stream stream in streams)
stream.Close();
streams = null;
}
};
printDocument.Print();
}
}
}

Print with showing Print dialog

Just in case someone wants to print with showing Print dialog, you can put a ReportViewer on form and set the Visible property of the control to false then pass data to the report and when the RenderingComplete event fired, call PrintDialog:

  • ReportViewer.PrintDialog Method

VB.NET - Print RDLC Report without showing ReportViewer control

Note: All the converters that I tried were unable to convert the C# code of the linked post to a correct VB.NET version. You can find the original C# version in the linked post: Print RDLC Report without showing ReportViewer Control.

VB.NET - Print RDLC Report without showing ReportViewer control

Here is the VB version of the Print extension method of LocalReport:

Imports Microsoft.Reporting.WinForms
Imports System.Drawing.Imaging
Imports System.Drawing.Printing
Imports System.IO
Imports System.Runtime.CompilerServices

Public Module LocalReportExtensions
<Extension()>
Sub Print(ByVal report As LocalReport)
Dim pageSettings = New PageSettings()
pageSettings.PaperSize = report.GetDefaultPageSettings().PaperSize
pageSettings.Landscape = report.GetDefaultPageSettings().IsLandscape
pageSettings.Margins = report.GetDefaultPageSettings().Margins
Print(report, pageSettings)
End Sub

<Extension()>
Sub Print(ByVal report As LocalReport, ByVal pageSettings As PageSettings)
Dim deviceInfo As String = $"<DeviceInfo>
<OutputFormat>EMF</OutputFormat>
<PageWidth>{pageSettings.PaperSize.Width * 100}in</PageWidth>
<PageHeight>{pageSettings.PaperSize.Height * 100}in</PageHeight>
<MarginTop>{pageSettings.Margins.Top * 100}in</MarginTop>
<MarginLeft>{pageSettings.Margins.Left * 100}in</MarginLeft>
<MarginRight>{pageSettings.Margins.Right * 100}in</MarginRight>
<MarginBottom>{pageSettings.Margins.Bottom * 100}in</MarginBottom>
</DeviceInfo>"
Dim warnings() As Warning
Dim streams = New List(Of Stream)()
Dim currentPageIndex = 0
report.Render("Image", deviceInfo,
Function(name, fileNameExtension, encoding, mimeType, willSeek)
Dim stream = New MemoryStream()
streams.Add(stream)
Return stream
End Function, warnings)

For Each stream As Stream In streams
stream.Position = 0
Next

If streams Is Nothing OrElse streams.Count = 0 Then
Throw New Exception("Error: no stream to print.")
End If

Dim printDocument = New PrintDocument()
printDocument.DefaultPageSettings = pageSettings

If Not printDocument.PrinterSettings.IsValid Then
Throw New Exception("Error: cannot find the default printer.")
Else
AddHandler printDocument.PrintPage,
Sub(sender, e)
Dim pageImage As Metafile = New Metafile(streams(currentPageIndex))
Dim adjustedRect As Rectangle = New Rectangle(
e.PageBounds.Left - CInt(e.PageSettings.HardMarginX),
e.PageBounds.Top - CInt(e.PageSettings.HardMarginY),
e.PageBounds.Width,
e.PageBounds.Height)
e.Graphics.FillRectangle(Brushes.White, adjustedRect)
e.Graphics.DrawImage(pageImage, adjustedRect)
currentPageIndex += 1
e.HasMorePages = (currentPageIndex < streams.Count)
e.Graphics.DrawRectangle(Pens.Red, adjustedRect)
End Sub

AddHandler printDocument.EndPrint,
Sub(Sender, e)
If streams IsNot Nothing Then
For Each stream As Stream In streams
stream.Close()
Next
streams = Nothing
End If
End Sub

printDocument.Print()
End If
End Sub
End Module

To use above code, it's enough to call Print extension method on a LocalReport. For example if you have a (visible or invisible ReportViewer):

Me.ReportViewer1.LocalReport.Print()

Of if you want to pass printer settings:

Me.ReportViewer1.LocalReport.Print(ReportViewer1.GetPageSettings())

How to directly print rdlc report without showing PrintDialog() in C#?

I just gave a quick look to a class I created to print directly and I think I took some ideas from this walkthrough:
Printing a Local Report without Preview

Print rdlc report without viewing print dialogue box

Here is how you can do it:

Dim m_currentPageIndex As Integer
Private m_streams As IList(Of Stream)

Dim report As New LocalReport()
report.DataSources.Add(New ReportDataSource("testData", reportData.Tables(0)))
report.ReportEmbeddedResource = "ReportsLibrary.rptTestData.rdlc"

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()
m_streams = New List(Of Stream)()
report.Render("Image", deviceInfo, CreateStream, warnings)
For Each stream As Stream In m_streams
stream.Position = 0
Next

Dim printDoc As New PrintDocument()
printDoc.PrinterSettings.PrinterName = "<your default printer name>"
Dim ps As New PrinterSettings()
ps.PrinterName = printDoc.PrinterSettings.PrinterName
printDoc.PrinterSettings = ps

printDoc.PrintPage += New PrintPageEventHandler(PrintPage)
m_currentPageIndex = 0
printDoc.Print()

Where PrintPage defined as follows:

' Handler for PrintPageEvents
Private Sub PrintPage(sender As Object, ev As PrintPageEventArgs)
Dim pageImage As New Metafile(m_streams(m_currentPageIndex))

' Adjust rectangular area with printer margins.
Dim adjustedRect As New Rectangle(ev.PageBounds.Left - CInt(ev.PageSettings.HardMarginX), ev.PageBounds.Top - CInt(ev.PageSettings.HardMarginY), ev.PageBounds.Width, ev.PageBounds.Height)

' Draw a white background for the report
ev.Graphics.FillRectangle(Brushes.White, adjustedRect)

' Draw the report content
ev.Graphics.DrawImage(pageImage, adjustedRect)

' Prepare for the next page. Make sure we haven't hit the end.
m_currentPageIndex += 1
ev.HasMorePages = (m_currentPageIndex < m_streams.Count)
End Sub


Related Topics



Leave a reply



Submit