C# 报表(report)和LocalReport类如何实现打印?
在这里与大家一起来分享下LocalReport类与报表(report)打印的使用。在做项目时候,报表打印是常常会用到的。它们是如何实现 打印的呢?今天根据自己在项目中用到的部分报表打印,再次重温一下它们的原理。(该项目是c版 C#windows forms)
在这里我就不在设计报表格式和其他的的内容了,根据自己的理解来给大家说下原理,若有不对还请见谅!我项目中关于报表打印的设计,还有数据源等都已经具备有的,在以下代码中有部分是省略了的。
//加载报表一个类 (表示不用连接到报表服务器而在本地处理和呈现的报表。) LocalReport report = new LocalReport();/* 这里创建二张表dt1=rdlcbiz.Get_tj_sqdlx_hd(tjbh, tjcs) 和dt2=rdlcbiz.Get_v_tj_tjdjb(tjbh, tjcs) 是根据方法来查询数据得到的两张表。 */ DataTable dt1 = rdlcbiz.Get_tj_sqdlx_hd(tjbh, tjcs);DataTable dt2 = rdlcbiz.Get_v_tj_tjdjb(tjbh, tjcs); //加载报表的路径 report.ReportPath = Application.StartupPath + @"/rdlcreport/Report_tjsqd.rdlc";//以图片显示 report.EnableExternalImages = true; /* 这里要要注意的:根据设计报表时需要传入参数值(ReportParameter) ReportParameter rp1 = new ReportParameter("tjdw", str_tjdw);//第 个参数是变量,第二个参数是值 以下代码:是向报表Report_tjsqd.rdlc中传入参数变量为tjdw,barcode并且把值传进到 */ ReportParameter rp1 = new ReportParameter("tjdw", str_tjdw);ReportParameter rp2 = new ReportParameter("barcode", str_path); //清除之前的报表数据 report.DataSources.Clear(); //设置好的报表参数以数组的形式传入 report.SetParameters(new ReportParameter[] { rp1, rp2 }); //获得报表使用的数据源集合,并且添加一个构造命名的数据源集合“ReportDataSource("PEISDataSet_tj_sqdlx_hd", dt1))” report.DataSources.Add(new ReportDataSource("PEISDataSet_tj_sqdlx_hd", dt1));report.DataSources.Add(new ReportDataSource("PEISDataSet_v_tj_tjdjb", dt2));//RdlcPrintNew这是一个打印的类也调用硬件的类(一会儿会重点讲) RdlcPrintNew rdlcprint = new RdlcPrintNew();rdlcprint.Run(report, "报表打印名称(可以修改)", false, "A4");//第一个参数:是本地报表,第二参数是报表打印名称(可以修改) 第三个参数是否显示打印设置对话框
以上的代码就是当我点击打印某张报表时,调用的一个方法。里面 rdlcprint.Run(report, "报表打印名称(可以修改)", false, "A4");这个方法就可以调硬件打印机啊。原理就是:利用LocalReport类把报表设计好,并且放在本地;再把报表中的参数和数据源,加载在指定的报表中;调用rdlcprint.Run(report, "报表打印名称(可以修改)", false, "A4");实现打印。接下来重点讲解这个方法。
using System; using System.IO; using System.Data; using System.Text; using System.Drawing.Imaging; using System.Drawing.Printing; using System.Collections.Generic; using Microsoft.Reporting.WinForms; using System.Windows.Forms; using System.Drawing;namespace PEIS.xtgg {public class RdlcPrintNew : IDisposable{string PaperName = "";//纸张名字string PageWidth = "";//纸张宽度string PageHeight = "";//纸张高度string MarginTop = "";//上边距string MarginLeft = "";//左边距string MarginRight = "";//右边距string MarginBottom = "";//下边距string PagePrinter = "";//打印机private bool hxdy = false;int m_PageIndex = 0;//需要打印的当前页 2012-08-14/// <summary>/// 获取一个值,指示是否为横向打印,默认为纵向/// </summary>public bool Hxdy{set { hxdy = value; }}/// <summary>/// 用来记录当前打印到第几页了/// </summary>private int m_currentPageIndex;/// <summary>/// //声明一个Stream对象的列表用来保存报表的输出数据 ///LocalReport对象的Render方法会将报表按页输出为多个Stream对象。/// </summary>private IList<Stream> m_streams;//文件流///用来提供Stream对象的函数,用于LocalReport对象的Render方法的第三个参数/// 提供 Stream 对象以进行呈现的 CreateStreamCallback 委托指向的方法 /// 这里为将报表的每一个页面作为一个EMF图片存放,通常用于报表呈现 /// </summary> /// <param name="name">流的名称</param> /// <param name="fileNameExtension">创建文件流时要使用的文件扩展名</param> /// <param name="encoding">指定流的字符编码的 Encoding 枚举器值。如果流不包含字符,则此值可能为 null。</param> /// <param name="mimeType">一个包含流的 MIME 类型的 string</param> /// <param name="willSeek">指示流是否需要支持查找的 Boolean 值。如果值为 false,则流将为只前推,并将按其创建顺序发送到块区中的客户端。如果值为 true,则流可以任何顺序写入。</param> /// <returns>ReportViewer 控件可以写入数据的 Stream 对象</returns> private Stream CreateStream(string name, string fileNameExtension, Encoding encoding, string mimeType, bool willSeek){//如果需要将报表输出的数据保存为文件,请使用FileStream对象。Stream stream = new FileStream(name + XtNumber.Name.ToString() + "." + fileNameExtension, FileMode.Create);m_streams.Add(stream);return stream;}/// <summary>/// 导出报表的每一个页面到一个EMF文件 /// </summary>/// <param name="report">ReportViewer.LocalReport</param>/// <param name="PageName">页面设置</param>private void Export(LocalReport report, string PageName){string deviceInfo = "";if (PageName == "")//单据名称 {deviceInfo ="<DeviceInfo>" +" <OutputFormat>EMF</OutputFormat>" +" <PageWidth>21cm</PageWidth>" +" <PageHeight>29.7cm</PageHeight>" +" <MarginTop>1cm</MarginTop>" +" <MarginLeft>1cm</MarginLeft>" +" <MarginRight>1cm</MarginRight>" +" <MarginBottom>1cm</MarginBottom>" +"</DeviceInfo>";}else{deviceInfo ="<DeviceInfo>" +" <OutputFormat>EMF</OutputFormat>" +" <PageWidth>" + PageWidth + "</PageWidth>" +" <PageHeight>" + PageHeight + "</PageHeight>" +" <MarginTop>" + MarginTop + "</MarginTop>" +" <MarginLeft>" + MarginLeft + "</MarginLeft>" +" <MarginRight>" + MarginRight + "</MarginRight>" +" <MarginBottom>" + MarginBottom + "</MarginBottom>" +"</DeviceInfo>"; }Warning[] warnings;m_streams = new List<Stream>();try{//report.DisplayName = PageName;////将报表的内容按照deviceInfo指定的格式输出到CreateStream函数提供的Stream中。report.Render("Image", deviceInfo, CreateStream, out warnings);report.Dispose();}catch (Exception ex){Exception innerEx = ex.InnerException;//取内异常。因为内异常的信息才有用,才能排除问题。 while (innerEx != null){MessageBox.Show(innerEx.Message);innerEx = innerEx.InnerException;}}foreach (Stream stream in m_streams){stream.Position = 0;}}/// <summary>/// 缩略图形的调用函数/// </summary>/// <returns></returns>public bool DelegateGetThumbnailImageAbort(){return false;}/// <summary> /// 当前页打印的输出 /// </summary> /// <param name="sender"></param> /// <param name="ev"></param> private void PrintPage(object sender, PrintPageEventArgs ev){if (m_PageIndex == 0)//没有指定页码打印所有的 {//把数据流转化把EMF矢量图片 Metafile pageImage = new Metafile(m_streams[m_currentPageIndex]); //设置高质量插值法 ev.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;//设置高质量,低速度呈现平滑程度 ev.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;//在指定位置并且按指定大小绘制原图片的指定部分 ev.Graphics.DrawImage(原始图片, new System.Drawing.Rectangle(0, 0, 缩略图片的宽, 缩略图片的高), new System.Drawing.Rectangle(0, 0, 原始图片的宽, 原始图片的高), System.Drawing.GraphicsUnit.Pixel);ev.Graphics.DrawImage(pageImage, new System.Drawing.Rectangle(0, 0, ev.PageBounds.Width, ev.PageBounds.Height), new System.Drawing.Rectangle(0, 0, pageImage.Width, pageImage.Height), System.Drawing.GraphicsUnit.Pixel);m_currentPageIndex++;ev.HasMorePages = (m_currentPageIndex < m_streams.Count);}else//指定页面后只打印指定页码 {if (m_PageIndex > m_streams.Count){ev.HasMorePages = false;//当终止页数大于总页数ev.Cancel = true;MessageBox.Show("自定义页面填写有误,终止页数不能大于总页数,请检查!", "提示",MessageBoxButtons.OK, MessageBoxIcon.Warning);return;}while (m_currentPageIndex + 1 < m_PageIndex){m_currentPageIndex++;}Metafile pageImage = new Metafile(m_streams[m_currentPageIndex]);ev.Graphics.DrawImageUnscaledAndClipped(pageImage, new System.Drawing.Rectangle(0, 0, ev.PageBounds.Width, ev.PageBounds.Height));ev.HasMorePages = false;pageImage.Dispose();}}/// <summary>/// //用来记录当前打印到第几页了 /// </summary>/// <param name="DocumentName"></param>/// <param name="DispalyPageSetupDialog"></param>private void Print(string DocumentName, bool DispalyPageSetupDialog)//"体检指引单打印", false {if (m_streams == null || m_streams.Count == 0){return;}PrintDocument printDoc = new PrintDocument();printDoc.DocumentName = DocumentName;if (!PrinterExists())//检查是否有打印机 {return;}if (PagePrinter != "")//打印机 {bool IsExists = false;//设置打印机名称是否存在for (int x = 0; x < PrinterSettings.InstalledPrinters.Count; x++){if (PrinterSettings.InstalledPrinters[x].ToString() == PagePrinter){printDoc.PrinterSettings.PrinterName = PagePrinter;//获得打印机的名称IsExists = true;break;}}if (!IsExists){MessageBox.Show("打印机:" + "【" + PagePrinter + "】不存在,请联系管理员!", "提示",MessageBoxButtons.OK, MessageBoxIcon.Warning);return;}}if (PaperName != "")//纸张名称:A4,A3 {if (!Printer.FormInPrinter(printDoc.PrinterSettings.PrinterName, PaperName))//纸张不存在自己创建 {decimal width = Convert.ToDecimal(PageWidth.Replace("cm", "")) * 10;decimal height = Convert.ToDecimal(PageHeight.Replace("cm", "")) * 10;Printer.AddCustomPaperSize(printDoc.PrinterSettings.PrinterName, PaperName, width, height);}int index = 0;//纸张的索引bool IsExists = false;//打印机纸张是否存在该纸张名称for (int j = 0; j < printDoc.PrinterSettings.PaperSizes.Count; j++){if (printDoc.PrinterSettings.PaperSizes[j].PaperName == PaperName){ index = j;IsExists = true;break;}}if (IsExists){printDoc.DefaultPageSettings.PaperSize = printDoc.PrinterSettings.PaperSizes[index];}else{MessageBox.Show("【" + PaperName + "】自定义纸张不存在,请联系管理员!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);return;}}//事件委托printDoc.PrintPage += new PrintPageEventHandler(PrintPage);if (DispalyPageSetupDialog){PageSetupDialog pageDialog = new PageSetupDialog();pageDialog.Document = printDoc;if (pageDialog.ShowDialog() == DialogResult.OK){printDoc.Print();}}else{if (hxdy)//横向打印 {printDoc.DefaultPageSettings.Landscape = true;}printDoc.Print(); }}/// <summary>/// 打印rdlc文件/// </summary>/// <param name="report">本地报表</param>/// <param name="DocumentName">打印文件名称</param>/// <param name="DispalyPageSetupDialog">是否显示打印设置对话框</param>/// <param name="PageName">打印单据的名字</param>public void Run(LocalReport report, string DocumentName, bool DispalyPageSetupDialog, string PageName)//report, "体检指引单打印", false, "A4" {// pw.StartThread();if (PageName != "")//取自定义纸张大小 {xtBiz xtbiz = new xtBiz();DataTable dt = xtbiz.Get_Xt_ggdy(PageName);//获得到设置的纸张的大小.if (dt.Rows.Count == 1){PaperName = dt.Rows[0]["PaperName"].ToString();PageWidth = dt.Rows[0]["PageWidth"].ToString();PageHeight = dt.Rows[0]["PageHeight"].ToString();MarginTop = dt.Rows[0]["MarginTop"].ToString();MarginLeft = dt.Rows[0]["MarginLeft"].ToString();MarginRight = dt.Rows[0]["MarginRight"].ToString();MarginBottom = dt.Rows[0]["MarginBottom"].ToString();PagePrinter = dt.Rows[0]["PagePrinter"].ToString();if (PageWidth == "") PageWidth = "0cm";if (PageHeight == "") PageHeight = "0cm";if (MarginTop == "") MarginTop = "0cm";if (MarginLeft == "") MarginLeft = "0cm";if (MarginRight == "") MarginRight = "0cm";if (MarginBottom == "") MarginBottom = "0cm";}else{MessageBox.Show("该单据纸张配置没有设置,请联系管理员!", "提示",MessageBoxButtons.OK, MessageBoxIcon.Warning);return;}}Export(report, PageName);//导出报表的每一个页面到一个EMF文件 m_currentPageIndex = 0;Print(DocumentName, DispalyPageSetupDialog);// "体检指引单打印", false//释放资源 Dispose();//一定释放资源 }/// <summary>/// 打印rdlc文件/// </summary>/// <param name="report">本地报表</param>/// <param name="DocumentName">打印文件名称</param>/// <param name="DispalyPageSetupDialog">是否显示打印设置对话框</param>/// <param name="PageName">打印单据的名字</param>/// <param name="PageFw">打印单据的范围</param>public void Run(LocalReport report, string DocumentName, bool DispalyPageSetupDialog, string PageName, string PageFw){//pw.StartThread();if (PageName != "")//取自定义纸张大小 {xtBiz xtbiz = new xtBiz();DataTable dt = xtbiz.Get_Xt_ggdy(PageName);if (dt.Rows.Count == 1){PaperName = dt.Rows[0]["PaperName"].ToString();PageWidth = dt.Rows[0]["PageWidth"].ToString();PageHeight = dt.Rows[0]["PageHeight"].ToString();MarginTop = dt.Rows[0]["MarginTop"].ToString();MarginLeft = dt.Rows[0]["MarginLeft"].ToString();MarginRight = dt.Rows[0]["MarginRight"].ToString();MarginBottom = dt.Rows[0]["MarginBottom"].ToString();PagePrinter = dt.Rows[0]["PagePrinter"].ToString();if (PageWidth == "") PageWidth = "0cm";if (PageHeight == "") PageHeight = "0cm";if (MarginTop == "") MarginTop = "0cm";if (MarginLeft == "") MarginLeft = "0cm";if (MarginRight == "") MarginRight = "0cm";if (MarginBottom == "") MarginBottom = "0cm";}else{MessageBox.Show("该单据纸张配置没有设置,请联系管理员!", "提示",MessageBoxButtons.OK, MessageBoxIcon.Warning);return;}} //导出报表的每一个页面到一个EMF文件 Export(report, PageName);if (PageFw == ""){m_currentPageIndex = 0;Print(DocumentName, DispalyPageSetupDialog); }else{string[] str_fw = PageFw.Split('-');int begin = 0;int end = 0;try{if (str_fw.Length == 1){begin = Convert.ToInt32(str_fw[0]);end = Convert.ToInt32(str_fw[0]);}else{begin = Convert.ToInt32(str_fw[0]);end = Convert.ToInt32(str_fw[1]);}if (begin > end){MessageBox.Show("该单据自定义打印页数填写有误,请检查!", "提示",MessageBoxButtons.OK, MessageBoxIcon.Warning);return;}}catch{MessageBox.Show("该单据自定义打印页数填写有误,请检查!", "提示",MessageBoxButtons.OK, MessageBoxIcon.Warning);return;}for (int i = begin; i <= end; i++){m_PageIndex = i;m_currentPageIndex = 0;Print(DocumentName, DispalyPageSetupDialog);//pw.StopThread(); }}//释放资源Dispose();}/// <summary>/// 释放资料源/// </summary>public void Dispose(){if (m_streams != null){foreach (Stream stream in m_streams)stream.Close();m_streams = null;}}/// <summary>/// 判断系统中是否存在打印机/// </summary>/// <returns>TRUE:存在打印机;FALSE:不存在打印机</returns>private bool PrinterExists(){PrinterSettings.StringCollection snames = PrinterSettings.InstalledPrinters;foreach (string s in snames){if (s.ToLower().Trim() == s.ToLower().Trim()){return true;}} MessageBox.Show("没找到打印机!\n只有安装了打印机才能进行打印", "没找到打印机",MessageBoxButtons.OK, MessageBoxIcon.Warning);return false;} }}
这样就可以调用硬件的打印机啊。。里面的原理就是:把之前设计好的报表参数和数据源加载装填好之后调用该方法,这个方法做了什么呢?它就是把这个本地报表将输出的数据保存为文件( Stream stream = new FileStream(name + XtNumber.Name.ToString() + "." + fileNameExtension, FileMode.Create);),再次把数据流转化把EMF矢量图片并且保存放在本地( Metafile pageImage = new Metafile(m_streams[m_currentPageIndex]);),在指定位置并且按指定大小绘制原图片的指定部分 (注意重点: 一不小心打印出就会出问题,所以要注意这个方法的使用“ev.Graphics.DrawImage(原始图片, new System.Drawing.Rectangle(0, 0, 缩略图片的宽, 缩略图片的高), new System.Drawing.Rectangle(0, 0, 原始图片的宽, 原始图片的高), System.Drawing.GraphicsUnit.Pixel);”),相当于矢量图片缩略为系统设置的值。如:A4、A3等。然后就调用 “Print(DocumentName, DispalyPageSetupDialog);"就可ok 了。
转载于:https://www.cnblogs.com/LikeNeng/p/3285970.html
C# 报表(report)和LocalReport类如何实现打印?相关推荐
- Android 日志打印工具类 可显示打印所在的方法和行号
Android 日志打印工具类 可显示打印所在的方法和行号.便于开发人员查看Log信息~~ package com.newland.util;import java.io.BufferedWriter ...
- 从零开始学USB(二十二、USB接口HID类设备(四)_报表描述符Local类)
本地项目标签定义控件的特征. 这些项目不会转移到下一个主要项目. 如果Main项定义了多个控件,则可能会有几个类似的Local项标签. 例如,一个Input项可能有几个与之关联的Usage标签,每个控 ...
- 从零开始学USB(二十一、USB接口HID类设备(三)_报表描述符Global类)
Global Item 用于描述一个操作( Main Item )所用到的数据格式,它可以改变一个 state table 的量, 这个 state table 的参数用于修饰 Main Item . ...
- 固定资产管理子系统报表分为什么大类,包括哪些科目
固定资产管理系统会包含报表:资产台账报表.盘点.盘盈和盘亏报表.资产报废报表.部门库存报表.资产增减统计.综合操作报表.操作记录 固定资产管理系统内置的图形工具可以智能地分析系统中的所有统计资产报表, ...
- Qt数据库报表应用-食品小作坊登记证打印系统二
接上篇. qt limereport报表详细介绍. 多平台支持 纯 qt4/qt5兼容代码 嵌入式报表设计器 嵌入式预览 各种复杂的报告的带区类型 页面 header 和页脚 数据分组( 页脚,页脚, ...
- java 打印对象属性 工具类_关于java实现任意对象输出字符串的工具类ObjectUtils用户打印日志、接口调试及监控等...
通过该对象工具类ObjectUtils(参考org.springframework.util.ObjectUtils)实现了类集.数组及基本数据类型转换及字符串输出,常用在日志输出打印.接口联调及对象 ...
- 水晶报表使用经验谈1--建立水晶报表第一步及编译最易出现错误的解决方法及报表转换成pdf文档进行打印方法...
初用水晶报表(vs .net2003集成,版本Version=9.1.5000.0) 装好后要注册 注册号:6707437608 密码:AAP5GKS0000GDE100DS 想要在.aspx文件中使 ...
- 水晶报表工具栏出现红叉叉无法打印导出等问题的解决方法
常见场景: 使用WebForm方式开发水晶报表应用,在本机调试一切正常.但是发布到服务器上以后,报表可以正确显示. 但是工具栏上的图标却成了红叉叉,无法执行打印.导出操作,页面提示有脚本错误. 解决方 ...
- python类的属性打印_python 打印类的属性、方法
打印变量db的类(class): [root@fuel ~]# python Python 2.6.6 (r266:84292, Jan 22 2014, 09:42:36) [GCC 4.4.7 2 ...
最新文章
- 使用class-dump导出其他应用头文件
- 通过文件读写方式实现Matlab和Modelsim的联合仿真
- Linux中表示“时间”的结构体和相关函数
- 周杰伦新动作的老朋友是谁?程序员:送分题!
- bzoj 3232 圈地游戏——0/1分数规划(或网络流)
- 土城战役_避免使用FOR –反假战役
- shell 需要注意的点
- 图的单源最短路径(Dijkstra算法)
- 王文汉:大学毕业后的5-10年最重要
- js 读取json文件_JavaScript 项目中常见配置文件介绍
- Shell脚本中的并发(转)
- 64.Linux/Unix 系统编程手册(下) -- 伪终端
- 机器学习入门09 - 特征组合 (Feature Crosses)
- 【JavaScript 逆向】webpack 之某妹游戏登录逆向
- python3几种常见解压压缩包的方法
- 安利个神器, Python 脚本可轻松打包为 exe
- 【Proteus仿真】BCD码转十进制(74HC42)
- 栈(Stack) C 语言实现
- template 的用法
- HCCG-CycleGAN网络结构、原理、以及相关代码--Generating Handwritten Chinese Characters using CycleGAN