Print RDLC Report without Preview

Sometimes you have a report which you want to print without showing a preview in ReportViewer. You can print an RDLC report programmatically using LocalReport object and CreateStreamCallback callback function.

There is an article in MSDN which describes how to print an RDLC report programmatically. Based on the idea of that article, I created an extension method for LocalReport class, called Print to make it easier to print the report without showing the report or any dialog:

It has two overloads:

  • Print(): It uses the default page settings of the report.
  • Print(PageSettings): It uses the page settings object which is passed to the method.

As an example, you can easily use it this way:

this.reportViewer1.LocalReport.Print();

LocalReport Print Extension Method

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();
        }
    }
}

You May Also Like

About the Author: Reza Aghaei

I’ve been a .NET developer since 2004. During these years, as a developer, technical lead and architect, I’ve helped organizations and development teams in design and development of different kind of applications including LOB applications, Web and Windows application frameworks and RAD tools. As a teacher and mentor, I’ve trained tens of developers in C#, ASP.NET MVC and Windows Forms. As an interviewer I’ve helped organizations to assess and hire tens of qualified developers. I really enjoy learning new things, problem solving, knowledge sharing and helping other developers. I'm usually active in .NET related tags in stackoverflow to answer community questions. I also share technical blog posts in my blog as well as sharing sample codes in GitHub.

19 Comments

  1. OK thank you

    But how can i use it

    i have created a report And i add data to it from a datatable object

    how can i print using your method

  2. Thank you Reza for your post. This solved my issue, but how about quality, do you think there is an alternative for EMF, images like logo loose quality when printed directly, when using the Preview everything looks fine.
    Thank you in advance

    1. I have the same problem. When using the Preview everything looks fine, but without preview font and report size are changed. Is there any solution for this?

  3. Thank you for your help.
    But in a pos printer its not end printing where data finish.

    it takes height like A4 paper height.
    If i change here
    {pageSettings.PaperSize.Width * 100}in
    {pageSettings.PaperSize.Height * 100}in

    still it problem.

    Any example or help please

  4. im having an error in this part:

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

  5. Hi,

    I used this code and works great. I use it to print labels on a zebra printer. What I have notices is that the size of the label can be slightly different when used on some machines. Did anybody notice this issue before?
    I’m ending up in an “it’s working on my machine” discussion at work. 🙂

    Any help is appreciated.

    Kind Regards

Leave a Reply

Your email address will not be published. Required fields are marked *