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();
}
}
}
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
As an example, you can easily use it this way:
this.reportViewer1.LocalReport.Print();
calling the print method wrong
Is it possible to have in VBA please?
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
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?
localreport does not conatain print() method
It works great, thank you!
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
same problem with me have you found any solution
i want your code and sample i use list i use c#
at design time the rdlc is one page, but print two pages. why???
the same problem any solution
It works great, thank you!
End of a terrific searching…
Thank you brother..
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);
Thank you very much for the example, please take care. Greetings from Maracay Venezuela
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
Does not work when i copy to IIS