I was wondering if is possible to send/print data from DataGridView directly to rdlc report without binding it to ReportViewercontrol.
There are many threads about binding dgv data to report viewer control.
I don't want to create another form with report viewer control, but use existing form with data on DataGridView and on print button to send the data to RDLC report and print it.
Is it possible?
Thanks
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
Related
I am using the below code to print RDCL Report directly ,
but the problem in the printed page , it is not same to what i choose in the report properties (A4), i tried to change page width and height in device info but same issue the printed paper huge and printed on 4 papers. please any idea?
private Stream CreateStream(string name,
string fileNameExtension, Encoding encoding,
string mimeType, bool willSeek)
{
Stream stream = new MemoryStream();
m_streams.Add(stream);
return stream;
}
// Export the given report as an EMF (Enhanced Metafile) file.
private void Export(LocalReport report)
{
string deviceInfo =
#"<DeviceInfo>
<OutputFormat>EMF</OutputFormat>
<PageWidth>8.27in</PageWidth>
<PageHeight>11.69in</PageHeight>
<MarginTop>0.25in</MarginTop>
<MarginLeft>0.25in</MarginLeft>
<MarginRight>0.25in</MarginRight>
<MarginBottom>0.25in</MarginBottom>
</DeviceInfo>";
Warning[] warnings;
m_streams = new List<Stream>();
report.Render("Image", deviceInfo, CreateStream,
out warnings);
foreach (Stream stream in m_streams)
stream.Position = 0;
}
// Handler for PrintPageEvents
private void PrintPage(object sender, PrintPageEventArgs ev)
{
Metafile pageImage = new
Metafile(m_streams[m_currentPageIndex]);
// Adjust rectangular area with printer margins.
Rectangle adjustedRect = new Rectangle(
ev.PageBounds.Left - (int)ev.PageSettings.HardMarginX,
ev.PageBounds.Top - (int)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++;
ev.HasMorePages = (m_currentPageIndex < m_streams.Count);
}
private void Print()
{
if (m_streams == null || m_streams.Count == 0)
throw new Exception("Error: no stream to print.");
PrintDocument printDoc = new PrintDocument();
if (!printDoc.PrinterSettings.IsValid)
{
throw new Exception("Error: cannot find the default printer.");
}
else
{
printDoc.PrintPage += new PrintPageEventHandler(PrintPage);
m_currentPageIndex = 0;
printDoc.Print();
}
}
// Create a local report for Report.rdlc, load the data,
// export the report to an .emf file, and print it.
private void Run()
{
LocalReport report = new LocalReport();
report.ReportPath = #"Doctor_form.rdlc";
Export(report);
Print();
}
protected void print_Click1(object sender, EventArgs e)
{
LocalReport report = new LocalReport();
report.ReportPath = #"Doctor_form.rdlc";
report.SetParameters(parameters);
Export(report);
Print();}
Here is my code i work with:
set Dataset and parameter to RDLC report
private static int m_currentPageIndex;
report.DataSources.Add(new ReportDataSource("dsReceiptInfor", ReceiptInfor));
ReportParameter[] param = new ReportParameter[2];
param[0] = new ReportParameter("imgPath", FilePath);
param[1] = new ReportParameter("BaseCurrencyFormat", BaseCurrencyFormat);
report.SetParameters(param);
Export(report);
Print();
Functions
--Export
private static void Export(LocalReport report)
{
string deviceInfo =
#"<DeviceInfo>
<OutputFormat>EMF</OutputFormat>
<PageWidth>8.5in</PageWidth>
<PageHeight>11in</PageHeight>
<MarginTop>0in</MarginTop>
<MarginLeft>0in</MarginLeft>
<MarginRight>0in</MarginRight>
<MarginBottom>0in</MarginBottom>
</DeviceInfo>";
Warning[] warnings;
m_streams = new List<Stream>();
report.Render("Image", deviceInfo, CreateStream, out warnings);
foreach (Stream stream in m_streams)
stream.Position = 0;
}
--Print
private static void Print()
{
if (m_streams == null || m_streams.Count == 0)
throw new Exception("Error: no stream to print.");
PrintDocument PrintBill = new PrintDocument();
PrintBill.PrintPage += new PrintPageEventHandler(PrintPage);
PrintBill.PrinterSettings.PrinterName = PrinterName;
PrintBill.PrintController = new StandardPrintController();
m_currentPageIndex = 0;
PrintBill.Print();
}
--PrintPage
private static void PrintPage(object sender, PrintPageEventArgs ev)
{
try
{
Metafile pageImage = new Metafile(m_streams[m_currentPageIndex]);
//Adjust rectangular area with printer margins.
Rectangle adjustedRect = new Rectangle(
0,
0,
765,
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++;
ev.HasMorePages = (m_currentPageIndex < m_streams.Count);
}
catch (Exception ex)
{
}
}
When the data print (PageHeight > 11 inch) it will cut. Could you tell me how to print long as the paper.
thanks for your attention :)
after long time i have searching the answer but still not found. So i have found one solution without coding.
in Printer setting we can change printer preference :
Paper source --> Document (cut). Done
I am new to C# and reports. What am I doing wrong or missing?
I have searched and searched and for the life of me can't figure this out.
I am using C# Windows Forms Application. I have report2.rdlc and everything works great in the report viewer, the text boxes and data in the tablix print as expected. When I print directly to the printer without using the report viewer, the text boxes print, but the data in the tablix does not print. Provided below is a screenshot of the Report Data window along with the coding and explanation.
Report Data Image
StatusCodes.cs form: Contains print button that has DialogResult. If "Yes" is clicked, StatusCodePreview.cs form opens. This has the report viewer (no problems here). If "No" is clicked, this triggers PrintWithoutReportViewer.cs and the report is printed directly to the default printer (problem: only text boxes and column headers are printing, data is not).
private void btn_CodePrint_Click(object sender, EventArgs e)
{
var message = "Do you wish to preview the report before printing?";
var title = "Preview Report";
DialogResult dg = MessageBox.Show(message, title, MessageBoxButtons.YesNo);
if (dg == DialogResult.Yes)
{
StatusCodePreview scp = new StatusCodePreview();
scp.Show();
}
else if (dg == DialogResult.No)
{
DataTable dt = new StatusCodesPrintDataSet.DataTable1DataTable();
LocalReport report = new LocalReport {ReportEmbeddedResource = "Toolbar.Report2.rdlc"};
report.DataSources.Add(new ReportDataSource("StatCodePrintDataSet1", dt));
report.PrintToPrinter();
}
}
Code for PrintWithoutReportViewer.cs
public static class PrintWithoutReportViewer
{
private static int m_CurrentPageIndex;
private static IList<Stream> m_Streams;
private static PageSettings m_PageSettings;
public static Stream CreateStream(string name, string fileNameExtension, Encoding encoding, string mimeType, bool willSeek)
{
Stream stream = new MemoryStream();
m_Streams.Add(stream);
return stream;
}
public static void Export(LocalReport report, bool print = true)
{
PaperSize paperSize = m_PageSettings.PaperSize;
Margins margins = m_PageSettings.Margins;
string deviceInfo = string.Format(
CultureInfo.InvariantCulture,
"<DeviceInfo>" +
"<OutputFormat>EMF</OutputFormat>" +
"<PageWidth>{5}</PageWidth>" +
"<PageHeight>{4}</PageHeight>" +
"<MarginTop>{0}</MarginTop>" +
"<MarginLeft>{1}</MarginLeft>" +
"<MarginRight>{2}</MarginRight>" +
"<MarginBottom>{3}</MarginBottom>" +
"</DeviceInfo>",
ToInches(margins.Top),
ToInches(margins.Left),
ToInches(margins.Right),
ToInches(margins.Bottom),
ToInches(paperSize.Height),
ToInches(paperSize.Width));
Warning[] warnings;
m_Streams = new List<Stream>();
report.Render("Image", deviceInfo, CreateStream,
out warnings);
foreach (Stream stream in m_Streams)
stream.Position = 0;
if (print)
{
Print();
//PrintDialog startPrint = new PrintDialog();
//startPrint.ShowDialog();
}
}
public static void PrintPage(object sender, PrintPageEventArgs e)
{
Stream pageToPrint = m_Streams[m_CurrentPageIndex];
pageToPrint.Position = 0;
using (Metafile pageMetaFile = new Metafile(pageToPrint))
{
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(pageMetaFile, adjustedRect);
m_CurrentPageIndex++;
e.HasMorePages = m_CurrentPageIndex < m_Streams.Count;
}
}
public static void Print()
{
if (m_Streams == null || m_Streams.Count == 0)
throw new Exception("Error: no stream to print.");
PrintDocument printDoc = new PrintDocument();
if (!printDoc.PrinterSettings.IsValid)
{
throw new Exception("Error: cannot find the default printer.");
}
else
{
printDoc.PrintPage += new PrintPageEventHandler(PrintPage);
m_CurrentPageIndex = 0;
printDoc.Print();
}
}
public static void PrintToPrinter(this LocalReport report)
{
m_PageSettings = new PageSettings();
ReportPageSettings reportPageSettings = report.GetDefaultPageSettings();
m_PageSettings.PaperSize = reportPageSettings.PaperSize;
m_PageSettings.Margins = reportPageSettings.Margins;
Export(report);
}
public static void DisposePrint()
{
if (m_Streams != null)
{
foreach (Stream stream in m_Streams)
stream.Close();
m_Streams = null;
}
}
private static string ToInches(int hundrethsOfInch)
{
double inches = hundrethsOfInch / 100.0;
return inches.ToString(CultureInfo.InvariantCulture) + "in";
}
}
I was originally trying to print using PrintDialog (I was wanting this option to allow user to still be able to select a printer), but that doesn't work at all and just led me to getting so frustrated. I am now just trying to use Print();
Like I said at the beginning, I am new at this and I'm lost. It would be greatly appreciated if anyone can help me with this.
I want to render a "Document"-object twice, but on the second generation the PDF-File shows an error:
Error on this page. Maybe this page couldn't appear correctly. Please talk to the document-creator.
Sorry, it is german...
This is my example-code:
using System;
using System.Windows.Forms;
using MigraDoc.Rendering;
using MigraDoc.DocumentObjectModel;
using PdfSharp.Pdf;
using System.Diagnostics;
namespace Temp
{
public partial class Form1 : Form
{
Document document; //using the same document- and renderer-object ..
PdfDocumentRenderer renderer; //..creates the error
public Form1()
{
InitializeComponent();
document = new Document();
renderer = new PdfDocumentRenderer(false, PdfFontEmbedding.Always);
}
private void button1_Click(object sender, EventArgs e)
{
Section section = document.AddSection();
Paragraph paragraph = section.AddParagraph();
paragraph.AddFormattedText("Hello World", TextFormat.Bold);
SaveFile(renderer);
}
private void SaveFile(PdfDocumentRenderer renderer)
{
renderer.Document = document;
renderer.RenderDocument();
string pdfFilename = string.Format("Rekla-{0:dd.MM.yyyy_hh-mm-ss}.pdf", DateTime.Now);
renderer.PdfDocument.Save(pdfFilename);
Process.Start(pdfFilename);
}
}
}
Of course i could always create a new "Document"-object:
private void button1_Click(object sender, EventArgs e)
{
Document document = new Document(); //Creating a new document-object solves the problem..
PdfDocumentRenderer renderer = new PdfDocumentRenderer(false, PdfFontEmbedding.Always);
Section section = document.AddSection();
Paragraph paragraph = section.AddParagraph();
paragraph.AddFormattedText("Hi", TextFormat.Bold);
SaveFile(renderer, document);
}
This works. But i need to change the current document while performing other button-click-events. The second code-snippet doesn't solve this task.
Does someone know how to fix the first code-snippet?
Do not re-use the Renderer. Create a new Renderer in the SaveFile method and everything should be fine.
If a new Renderer is not enough, call document.Clone() and assign that to the Renderer.
A method I have found very useful for repeatedly saving a Migradoc pdf to a file is to save the document to a MemoryStream/byte array when I render it. Then when I need to save the pdf file, I just save the byte array.
Put this part in your constructor where you want to render the document:
// First we render our document and save it to a byte array
bytes[] documentBytes;
Document doc;
using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
{
PdfDocumentRenderer pdfRender = new PdfDocumentRenderer();
pdfRender.Document = doc;
pdfRender.RenderDocument();
pdfRender.Save(ms, false);
documentBytes = ms.ToArray();
}
Put this part in your button event where you want to save to a file:
// Then we save the byte array to a file when needed
string filename;
using (System.IO.FileStream fs = new System.IO.FileStream(filename, System.IO.FileMode.Create))
{
fs.Write(documentBytes, 0, documentBytes.Length);
}
I'm using a PrintDocument to set a network printer and paper source. I have a Stream to print.
In this case, only a blank page is printed (on good printer and tray), so how bind the StreamReader to the PrintDocument in MVC4 ? Stream is well populated.
public ActionResult ImprimerEtiquettes(int patientId, int venueId, string uf)
{
//do some business logic to have a Stream with parameters
using (StreamReader sr = new StreamReader(fStream))
{
var doc = new PrintDocument();
doc.PrinterSettings.PrinterName = "\\\\imp-dsii\\PI91063";
PaperSource ps = doc.PrinterSettings.PaperSources[2];
doc.DefaultPageSettings.PaperSource = ps;
doc.PrintPage += doc_PrintPage;
doc.Print();
}
return Json(new { success = true }, JsonRequestBehavior.AllowGet);
}
void doc_PrintPage(object sender, PrintPageEventArgs e)
{
}