wpf 直接打印 RDLC 报告而不显示报告查看器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21786103/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Printing RDLC Report directly without displaying reportviewer
提问by Nilesh Barai
I am working on WPF C# 4.0 project in which I am trying to print a RDLC report which is basically an invoice directly without displaying the ReportViewer. I refered code from the following MSDN linkand modified it for my purpose.
我正在研究 WPF C# 4.0 项目,在该项目中我试图打印 RDLC 报告,该报告基本上是直接发票而不显示 ReportViewer。我参考了以下MSDN 链接中的代码并根据我的目的对其进行了修改。
Following is the modified code which I am using.
以下是我正在使用的修改后的代码。
using System;
using System.IO;
using System.Data;
using System.Text;
using System.Drawing.Imaging;
using System.Drawing.Printing;
using System.Collections.Generic;
using System.Windows.Forms;
using Microsoft.Reporting.WinForms;
using System.Xml;
using System.Resources;
using System.Drawing;
using System.Reflection;
namespace POS.Classes
{
public class DirectReportPrint : IDisposable
{
private double[] PageBounds = { 0,0,0,0,0,0};
private int m_currentPageIndex;
private IList<Stream> m_streams;
private DataTable _table = new DataTable();
/// <summary>
/// Must set this to get the report data
/// </summary>
public DataTable ReportTable
{
get { return _table; }
set { _table = value; }
}
// Routine to provide to the report renderer, in order to
// save an image for each page of the report.
private Stream CreateStream(string name,
string fileNameExtension, Encoding encoding,
string mimeType, bool willSeek)
{
//Stream stream = new FileStream(@"..\..\" + name +
// "." + fileNameExtension, FileMode.Create);
Stream stream = new FileStream(Path.GetTempPath() + "\" + name +
"." + fileNameExtension, FileMode.Create);
m_streams.Add(stream);
return stream;
}
private string ReadEmbeddedResource(string ResourceName)
{
var assembly = Assembly.GetExecutingAssembly();
using (Stream stream = assembly.GetManifestResourceStream(ResourceName))
using (StreamReader reader = new StreamReader(stream))
{
string result = reader.ReadToEnd();
string temp = result.Replace('\r',' ');
return temp;
}
}
private string ReadReportXML(string ReportName)
{
try
{
string s = " ", temp = "", t = "";
int x, y, z;
string result = ReadEmbeddedResource(ReportName);
if (result.Contains("<PageHeight>") && result.Contains("</PageHeight>"))
{
x = result.IndexOf("<PageHeight>");
y = result.IndexOf("</PageHeight>");
temp = result.Substring(x, y - x);
s += temp + "</PageHeight> ";
z = temp.IndexOf('>') + 1;
t = temp.Substring(z, temp.Length - z);
PageBounds[0] = Math.Round(Convert.ToDouble(t.Substring(0, t.Length - 2)), 2);
}
if (result.Contains("<PageWidth>") && result.Contains("</PageWidth>"))
{
x = result.IndexOf("<PageWidth>");
y = result.IndexOf("</PageWidth>");
temp = result.Substring(x, y - x);
s += temp + "</PageWidth> ";
z = temp.IndexOf('>') + 1;
t = temp.Substring(z, temp.Length - z);
PageBounds[1] = Math.Round(Convert.ToDouble(t.Substring(0, t.Length - 2)), 2);
}
if (result.Contains("<LeftMargin>") && result.Contains("</LeftMargin>"))
{
x = result.IndexOf("<LeftMargin>");
y = result.IndexOf("</LeftMargin>");
temp = result.Substring(x, y - x);
s += temp + "</LeftMargin> ";
z = temp.IndexOf('>') + 1;
t = temp.Substring(z, temp.Length - z);
PageBounds[2] = Math.Round(Convert.ToDouble(t.Substring(0, t.Length - 2)), 2);
}
if (result.Contains("<RightMargin>") && result.Contains("</RightMargin>"))
{
x = result.IndexOf("<RightMargin>");
y = result.IndexOf("</RightMargin>");
temp = result.Substring(x, y - x);
s += temp + "</RightMargin> ";
z = temp.IndexOf('>') + 1;
t = temp.Substring(z, temp.Length - z);
PageBounds[3] = Math.Round(Convert.ToDouble(t.Substring(0, t.Length - 2)), 2);
}
if (result.Contains("<TopMargin>") && result.Contains("</TopMargin>"))
{
x = result.IndexOf("<TopMargin>");
y = result.IndexOf("</TopMargin>");
temp = result.Substring(x, y - x);
s += temp + "</TopMargin> ";
z = temp.IndexOf('>') + 1;
t = temp.Substring(z, temp.Length - z);
PageBounds[4] = Math.Round(Convert.ToDouble(t.Substring(0, t.Length - 2)), 2);
}
if (result.Contains("<BottomMargin>") && result.Contains("</BottomMargin>"))
{
x = result.IndexOf("<BottomMargin>");
y = result.IndexOf("</BottomMargin>");
temp = result.Substring(x, y - x);
s += temp + "</BottomMargin> ";
z = temp.IndexOf('>') + 1;
t = temp.Substring(z, temp.Length - z);
PageBounds[5] = Math.Round(Convert.ToDouble(t.Substring(0, t.Length - 2)), 2);
}
return s;
}
catch (Exception ex)
{
return null;
}
}
// Export the given report as an EMF (Enhanced Metafile) file.
private void Export(LocalReport report, string ReportName)
{
try
{
string temp = ReadReportXML(ReportName);
if (temp != null)
{
string deviceInfo =
"<DeviceInfo>" +
" <OutputFormat>EMF</OutputFormat>"
+ temp +
"</DeviceInfo>";
Warning[] warnings;
m_streams = new List<Stream>();
report.Render("Image", deviceInfo, CreateStream,
out warnings);
foreach (Stream stream in m_streams)
stream.Position = 0;
}
else
{
throw new Exception("Something went wrong. Unable to Print Report");
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
MessageBox.Show(ex.InnerException.Message);
}
}
// 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()
{
PrinterSettings settings = new PrinterSettings();
if (m_streams == null || m_streams.Count == 0)
return;
PrintDocument printDoc = new PrintDocument();
printDoc.PrinterSettings.PrinterName = settings.PrinterName;
PaperSize CustomSize = new PaperSize("Custom", (int)PageBounds[1]*100, (int)PageBounds[0]*100);
CustomSize.RawKind = (int)PaperKind.Custom;
printDoc.DefaultPageSettings.PaperSize = CustomSize;
if (!printDoc.PrinterSettings.IsValid)
{
string msg = String.Format(
"Can't find printer \"{0}\".", settings.PrinterName);
MessageBox.Show(msg, "Print Error");
return;
}
printDoc.PrintPage += new PrintPageEventHandler(PrintPage);
printDoc.Print();
}
/// <summary>
/// Create a local report for Report.rdlc, load the data,
/// export the report to an .emf file, and print it.
/// Prints the report directly
/// </summary>
/// <param name="ReportName">Name of the report</param>
/// <param name="DS_Name">Dataset name for the report. Provide the name which was used during RDLC file creation</param>
public void Run(string ReportName, string DS_Name)
{
LocalReport report = new LocalReport();
report.ReportEmbeddedResource = ReportName;
report.DataSources.Add(new ReportDataSource(DS_Name, ReportTable));
Export(report, ReportName);
m_currentPageIndex = 0;
Print();
Dispose();
}
public void Dispose()
{
if (m_streams != null)
{
foreach (Stream stream in m_streams)
stream.Close();
m_streams = null;
}
}
}
}
Code which Invokes Run Method
调用 Run 方法的代码
Classes.DirectReportPrint drp = new Classes.DirectReportPrint();
drp.ReportTable = Classes.Class_Sales_Bill.GetBillDetails(this.saleObj.Row_ID);
drp.Run("POS.Reports.Rpt_Anil_Sale_Bill.rdlc", "DataSet1");
This code works well when I am using Visual Studio debugger to execute it. However, it fails if I publish my project, install its setup and then try to run its exe (Weird Behaviour).
当我使用 Visual Studio 调试器执行它时,此代码运行良好。但是,如果我发布我的项目,安装它的设置然后尝试运行它的 exe ,它就会失败(Weird Behaviour)。
If I run exe it works for the first invoice which I try to print. For the subsequent invoices I get the following error.
如果我运行 exe,它适用于我尝试打印的第一张发票。对于后续发票,我收到以下错误。
An error occurred during local report processing. Access to the Path 'c:\Users\Rpt_Anil_Sale_Bill_0.EMF' is denied.
Here Rpt_Anil_Sale_Billis the name of my RDLC file.
这Rpt_Anil_Sale_Bill是我的 RDLC 文件的名称。
On further digging I identified that the exe code creates an intermediate EMF file in this path C:\Users\Nilesh\AppData\Local\Apps\2.0\BWQ6XD5A.DB0
在进一步挖掘时,我发现 exe 代码在此路径中创建了一个中间 EMF 文件 C:\Users\Nilesh\AppData\Local\Apps\2.0\BWQ6XD5A.DB0


If I try to open this file I get the following error:
如果我尝试打开此文件,则会出现以下错误:


Need help in identifying what's going wrong with the code.
需要帮助确定代码出了什么问题。
Any help is appreciated. Thanks!!
任何帮助表示赞赏。谢谢!!
回答by 0_0
I used this code and it works very well for me.
我使用了这段代码,它对我来说效果很好。
First add this class into your project enter link description here
首先将此类添加到您的项目中,在此处输入链接描述
Then use the following code to print directly to the default printer:
然后使用以下代码直接打印到默认打印机:
LocalReport report = new LocalReport();
report.ReportEmbeddedResource = ReportSource;
report.DataSources.Add(myDataSource);
report.PrintToPrinter();

