RDLC报表详细讲解与分析Word版

上传人:每**** 文档编号:66258941 上传时间:2022-03-27 格式:DOC 页数:104 大小:1.88MB
返回 下载 相关 举报
RDLC报表详细讲解与分析Word版_第1页
第1页 / 共104页
RDLC报表详细讲解与分析Word版_第2页
第2页 / 共104页
RDLC报表详细讲解与分析Word版_第3页
第3页 / 共104页
点击查看更多>>
资源描述
如果您需要使用本文档,请点击下载按钮下载!RDLC报表随笔(转载,感谢网友”蜡人张”)(一)VS .NET开发中,用什么做报表? 可能的回答是Crystal Report,自.NET“紧密”集成Crystal Report后,这可能是开发人员比较单一的选择。但是,这种集成似乎并不非常紧密,网络上充斥着关于使用Crystal Report的抱怨,太复杂也许是其最为令人诟病的地方,自定义性比较差也不能为程序员们所容忍。 当然,必须承认Crystal Report的功能还是非常强大的,被Business Object收购以后,商业职能的成分也在逐渐增加,也形成了一定规模的用户群。 Visual Studio .NET进入2005版本以后,Crystal Report与IDE的结合更“紧密”了,至少我们看不到那个讨厌的注册窗口了。但是,Microsoft似乎并不容忍在自己的超级工具中竟然没有报表工具,于是Report Viewer Control出现了,我把它的报表称为RDLC报表。 在VS .NET 2005之前,SQL Server Reporting Services中已经提供了一种被称为报表定义语言(Report Definition Language, RDL)的语言;在VS .NET 2005中,Microsoft提供了针对这种报表的设计器,并提供了在WinForm和WebForm中使用这种报表的能力。Microsoft将这种报表的后缀定为RDLC,RDL仍然是Report Definition Language的缩写,那么C代表什么呢?C代表Client-side processing,凸显了它的客户端处理能力。 这种报表的易用性和可定制性让我们完全有理由放弃Crystal Report,让我们来看看它的强大功能吧:1、简单易用的控件,特别是Table控件,非常方便字段在报表上的排列;2、灵活的可定制性,用XML来描述一个报表相关的一切,不用说了吧?3、高度可编程性,在你的项目中,甚至不需要有一个报表文件,通过代码就可以实现报表生成、预览和打印等一系列操作;4、支持DrillThrough数据钻取功能;5、导出的Excel文件格式非常完美,任何其它报表在这方面都不能与之比拟,而且并不需要安装Excel; 偷偷懒,其实我并不擅长总结某某的特点,我只能从实际经验中得到一点点结论,而且我也不原意去抄袭帮助中的New Features,呵呵如果您需要使用本文档,请点击下载按钮下载! 在以后的几篇随笔中,我将结合最近一段时间使用RDLC报表的经验继续探讨相关的一些问题,大致内容包括:报表设计器的使用、LocalReport的一些相关操作,如何自定义纸张等等,欢迎大家提出参考意见。(二) 需要说明的是,现在关于VS. NET 2005中的Report Viewer Control的内容非常少,我只能按照自己的理解来说一些东西,这其中肯定会有一些偏差,欢迎各位的批评指正。另外,我所涉及的内容都是关于LocalReport的,对于ServerReport没有进行研究。在这篇随笔中,我主要分析一下GotReportViewer上的几个经典例子,我们可以从中看到ReportViewer Control的强大功能: 1、Web Log Analyzer 这是一个比较典型的OLAP应用,我们可以看到RDLC报表强大的Chart和Navigation功能。当然了,例子中解析W3C标准日志文件的代码也非常有借鉴意义。这个Starter Kit在我的随笔 2、子报表 展示如何使用子报表显示主记录的详细信息,这种应用很像Access中的子报表功能。主要使用SubreportProcessing事件为子报表提供数据。 3、钻取报表 钻取报表是通过设置Navigation(HyperLink)和Parameters来实现的,通常在OLAP应用程序中很有用。 如果您需要使用本文档,请点击下载按钮下载!4、具有子报表的钻取报表 这个例子实现的功能类似Excel中数据透视表(Pivot Table)的功能,在一个复杂的交叉表中可以进行时间和商品两个维度的向下钻取。这在别的报表中恐怕是很难实现的。如图所示, 5、引用外部代码块 此示例演示从另外一个类Util中读取函数返回值到报表中:首先,使用LocalReport的AddTrustedCodeModuleInCurrentAppDomain方法允许Util类中的方法在Report Viewer中执行,然后在报表中使用TextBox控件的Value节点调用Util中的静态方法Factorial在报表中显示其返回值。 另外一个相关的示例基本上与此相同,只不过在Util类中访问一个文本文件并将该文本文件中的字符显示在报表中 6、导出到Excel RDLC报表导出到Excel中的效果非常好,曾经看到另外一个报表设计器(好像就是Crystal Report)导出为Excel文件后的效果非常差,单元格根本不对齐,用户无法在其基础上进行二次操作,而RDLC报表导出的Excel文件就没有这个缺点,而且基本上完全保留了原报表设置的格式。如图所示,如果您需要使用本文档,请点击下载按钮下载! 可以直接使用Report Viewer控件自带的按钮生成Excel文件,也可以使用如下代码来完成操作:Microsot.Reporting.WinForms.WarningWarnings; stringstrStreamIds; stringstrMimeType; stringstrEncoding; stringstrFileNameExtension; bytebytes=this.rptViewer.LocalReport.Render(Excel,null,outstrMimeType,outstrEncoding,outstrFileNameExtension,outstrStreamIds,outWarnings); stringstrFilePath=D:report.xls; using(System.IO.FileStreamfs=newFileStream(strFilePath,FileMode.Create) fs.Write(bytes,0,bytes.Length); 如果您需要使用本文档,请点击下载按钮下载! 对于LocalReport的Render方法,以后的随笔中将进行详细阐述。 7、交互排序 在RDLC报表的众多交互功能中,这个功能是比较新颖的,终端用户可以通过报表中列标题上的图标进行数据的排序,而预览及打印的效果完全取决于用户的排序。此处好像有一个Bug,即对数据进行一种排序后的预览效果会保持不变,除非再次开启这个应用程序并重新排序。而这一切不需要在代码中做任何操作,只需要在报表定义文件中添加节并指定相应的SortExpression和SortExpressionScope。8、RSS新闻阅读器 用ReportViewer实现RSS新闻阅读器?是的!如图所示, 当然这个sample是为了展示对Object类型数据源的支持,报表参数ReportParameter的使用也在其中得到体现。 如果您需要使用本文档,请点击下载按钮下载!9、允许钻取的主子表 另外一种允许向下钻取的主子报表。如图所示,10、从命令行中打印报表 RDLC报表允许用户不通过ReportViewer图形界面直接使用代码控制输出和打印,还是使用LocalReport的Render方法,以后的随笔中将参照这个示例介绍一个如何自定义纸张的方法。11、票据生成 这个示例允许用户输入一个单据及其明细后直接生成一个可供打印的票据。如图所示,如果您需要使用本文档,请点击下载按钮下载!12、动态生成一个RDLC文件 这可能是一个最最重要的示例了,RDLC文件是用XML来描述的,可以直接使用代码生成之,这样的报表就可以非常灵活了。像网上比较流行的从DataGridView直接预览、打印数据的程序完全可以用这种方法来替代;进一步引申的话,完全可以实现一个自己的基于RDLC的报表设计器,这样可以让终端用户参与到报表的设计中,至少可以使他们能够修改报表中一些标题、表头等。如果您需要使用本文档,请点击下载按钮下载! GotReportViewer还提供了几个其他的例子,如设置报表参数、通过Email邮寄报表等,由于不是非常典型,不再赘述。 GotReportViwer不知道为什么最近上不去了,有需要这些例程的朋友可以留下Email。(三)仔细想了一下,我觉得一篇step by step的随笔似乎是不必要的,由于RDLC报表设计时的简易性,任何有报表经验的人都可以在摸索后很容易就掌握其报表的设计方法。本来在这篇随笔中想谈一下对RDLC报表文件的解析,但是MISGoldPrinter的作者flygoldfish(长流支流)已经对这方面进行了详细的总结(见 另外,我手头有一份RDL规范(Report Definition Language Specification),非常值得阅读,推荐给大家如果您需要使用本文档,请点击下载按钮下载!Matrix如果您需要使用本文档,请点击下载按钮下载!Table 本来打算不要这篇随笔了,因为没有什么具体的内容,但为了保证完整性,还是放在这吧,不过我不放在首页了,免得污染大家的视线,呵呵 下一篇随笔可能是关于Table和Matrix这个两个控件的,不过我还没具体想好。(四)RDLC报表中有一个概念叫数据区域(Data Region),数据区域是数据绑定的报表项目,在数据区域中可以显示来自数据集的多行数据。RDLC报表设计器中的数据区域包含控件面板上的一系列控件:List、Table、Matrix、Chart,如图所示, 如果您需要使用本文档,请点击下载按钮下载! List控件的用处在于这是一个在其中可以自由安排像TextBox、Image等控件;Chart控件用于显示图表,和Excel中的图表比较相似。这篇随笔不会涉及到这两个控件,主要讲一下Table和Matrix两个控件。 先来看Table控件。Table控件有多个部分组成,如标题行(header)、表尾(footer)、数据行(detailed rows)、分组表头(group header)、分组表尾(group footer)等,如图所示,如果您需要使用本文档,请点击下载按钮下载! 之所以设计这样一个控件,我想Microsoft一定是在简化报表的设计: 在这个控件未出现之前,我们看一下一个具有heaer、detailed rows和带统计信息的footer的报表时如何实现的。首先,这个报表需要显示报表页眉、主体和报表页脚三个部分,然后在报表页眉中拖曳进一系列Label形成表格的标题行,接着在主体部分拖曳进一系列TextBox用于显示数据行,并在报表页脚中拖曳进一系列Label或TextBox用于显示统计信息;要命的是,这些Label或TextBox需要在某个方向上进行对齐,控件宽度的调节也非常麻烦,如果需要显示表格线,那么没办法,需要使用Line控件手工画,这是非常麻烦的一件差事,相信没人会喜欢用这么麻烦的方法来设计这么一个简单的报表。 现在,Microsoft推出了Table控件,你需要做的只是确定表格的列数(因为表格的列数需要是固定的),然后将字段从Data Sources面板中拖曳到Table控件的数据行中就可以了,报表设计器会自动为你生成标题行中的标题信息;至于footer中的统计信息Microsoft甚至为我们设计了一个表达式生成器,使用起来非常简便;列宽可以通过拖曳来调整,表格线可以通过设置Table控件的属性来完成。 是的,一切就是这么简单!这也很可能是为什么你在Visual Studio 2005的报表设计器中找不到报表页眉和报表页脚的原因,只有页面页眉(page header)和页面页脚(page footer)就足够了! 当然,可能报表中也需要不是像表格这么整齐排列的数据区域,这时候就需要用到List控件了。 在实际应用中,发现一个表格控件可以具有零个、一个或多个header或footer,甚至可以没有detailed rows,这样的表格控件有什么作用呢?我们知道detailed rows是用来显示多行数据的,而heaer或footer都可以用来显示sum、count等统计信息。假如我们的数据集中同时具有主子表(如通过Inner Join获得的一个查询)的信息,而这时候我们需要将主报表的信息单独显示出来使整个报表形成一个主子表的样式,那么我们就可以用到没有detailed rows的Table控件了,为header或footer中的单元格指定First(Fields!字段名称.Value, 数据源名称)就可以了,这样至少减少了我们排列这些字段信息的烦恼。也就是说,Table控件是非常灵活的。CodeProject上有一篇文章One to Many Reports with VS.NET 2005 (2.0) Report Designer(如果您需要使用本文档,请点击下载按钮下载!)即是用这种主子数据集显示的主子报表,但是个人觉得不如上面描述的方法来的简单,顶多给报表增加一个可以标识主记录的参数而已。当然,正儿八经的主子报表还是需要借助SubReport控件来实现。 再来看一下Matrix控件,这个控件可以看作是Microsoft的又一个创新,以前的报表中可能会有交叉表(crosstab),但Matrix控件反映的不只是一个交叉表,还可以看作是一个带钻取功能的数据透视表(pivot table)。Matrix控件由以下部分组成: 如果由我们自己使用一个普通的数据集来绘制一个crosstab,那会是一个非常麻烦的工作,我们需要:为数据透视报表设置行标题;计算可能的列标题数量并设置列标题,根据行标题和列标题在数据集中循环查询由当前行标题和列标题决定的值,整个过程的计算量就够受的了。作为被Microsoft封装过的一个控件,Matrix控件显然不需要这么麻烦,简单的拖曳操作并设置其属性就可以了。当然,在报表中使用交叉表最重要的一点是最终显示的结果必须是有意义的。 需要注意的是,当包含Matrix控件的报表导出到Excel文件中以后,即使是未显示的带有钻取标志的区域也将被显示出来,可能你会有这样的疑问:既然是数据透视表,为什么在Excel中不能显示成折叠的样式呢?这是因为报表的导出功能是并不依赖于Excel的。 下一篇随笔可能是关于ReportViewer控件的。如果您需要使用本文档,请点击下载按钮下载!(五)随着Visual Studio 2005中文版的推出,Microsoft汉化了MSDN的大部分内容,开发者再也不用啃英文了,本来想介绍一下LocalReport的Render方法,现在您可以到 Report中无法实现的自定义票据打印纸张的方法。Anyway,现在我直接向大家介绍这种方法,可能这种方法并不是很好的,但是确实是我经过一段时间的摸索总结出来的。萝卜()曾经提到过的变通的方法不知道是不是我要介绍的这一种,欢迎和我进行交流! 要想使用RDLC报表并进行页面设置,我们先来看一下LocalReport是否有类似PageSettings的类、属性、方法或事件等,我仔细找了一下,发现Microsoft.Reporting.WinForms.ReportPageSettings类具有PaperSize属性和Margin属性,但可惜的是它们都是只读的,对我们来说没有意义;另外,LocalReport具有GetDefaultPageSettings()方法,这也只能是获取当前报表的页面设置。没办法,只能采用变通的方法了。在.NET中如果想使用自定义纸张,最好的方法莫过于使用System.Drawing.Printing.PrintDocument类了,还记得我在前面提到的一个GotReportViewer的例子吗?privateintm_currentPageIndex;privateIListm_streams;privateStreamCreateStream(stringname,stringfileNameExtension,Encodingencoding,stringmimeType,boolwillSeek)Streamstream=newFileStream(name+.+fileNameExtension,FileMode.Create);m_streams.Add(stream);returnstream;privatevoidExport(LocalReportreport)如果您需要使用本文档,请点击下载按钮下载!stringdeviceInfo=+EMF+8.5in+11in+0.25in+0.25in+0.25in+0.25in+;Warningwarnings;m_streams=newList();report.Render(Image,deviceInfo,CreateStream,outwarnings);foreach(Streamstreaminm_streams)stream.Position=0;privatevoidPrintPage(objectsender,PrintPageEventArgsev)MetafilepageImage=newMetafile(m_streamsm_currentPageIndex);ev.Graphics.DrawImage(pageImage,ev.PageBounds);m_currentPageIndex+;ev.HasMorePages=(m_currentPageIndexm_streams.Count);privatevoidPrint()如果您需要使用本文档,请点击下载按钮下载!conststringprinterName=MicrosoftOfficeDocumentImageWriter;if(m_streams=null|m_streams.Count=0)return;PrintDocumentprintDoc=newPrintDocument();printDoc.PrinterSettings.PrinterName=printerName;if(!printDoc.PrinterSettings.IsValid)stringmsg=String.Format(Cantfindprinter0.,printerName);Console.WriteLine(msg);return;printDoc.PrintPage+=newPrintPageEventHandler(PrintPage);printDoc.Print();privatevoidRun()LocalReportreport=newLocalReport();report.ReportPath=Report.rdlc;report.DataSources.Add(newReportDataSource(Sales,LoadSalesData();Export(report);m_currentPageIndex=0;Print();如果您需要使用本文档,请点击下载按钮下载! 对,就是那个通过命令行而不是ReportViewer的GUI界面进行打印报表的例子,这个例子就使用LocalReport的Render方法将报表的内容导出为EMF图像流,然后在PrintDocument的PrintPage事件中使用时事件参数System.Drawing.Printing.PrintEventArgs类的DrawImage方法将EMF图像流输出到打印机。我在上面说的变通的方法也要使用这种方法。具体的细节将在以后的随笔中陆续给出。 既然我们使用这种方法进行报表的打印,那么Visual Studio的控件ReportViewer的工具栏就不再符合我们的要求了。因为这个报表浏览器的工具栏上的按钮虽然可以设置属性显示或隐藏其中的一部分,但是我们却不能自己往这个工具栏上添加按钮(显然,我们需要实现自己的页面设置、预览和打印按钮),在这一点上,建议Microsoft将工具栏和报表浏览器分离,应该做得和BindingNavigator那样就好了。 我们先设置ReportViewer控件的ShowToolBar方法为false,然后在ReportViewer控件纸上添加除页面设置、预览、打印外的应该有的按钮,像刷新、终止、导出、缩放、搜索、导航等,这些按钮的Click事件定义如下:/*/获取当前时间组成的字符串,用作生成不会重复的文件名/privatestringGetTimeStamp()stringstrRet=string.Empty;System.DateTimedtNow=Pub.DateTimeEx.ServerTime;strRet+=dtNow.Year.ToString()+dtNow.Month.ToString(00)+dtNow.Day.ToString(00)+dtNow.Hour.ToString(00)+dtNow.Minute.ToString(00)+如果您需要使用本文档,请点击下载按钮下载!dtNow.Second.ToString(00)+System.DateTime.Now.Millisecond.ToString(000);returnstrRet;/*/导出到Excel/privatevoidtoolExcel_Click(objectsender,EventArgse)Microsoft.Reporting.WinForms.WarningWarnings;stringstrStreamIds;stringstrMimeType;stringstrEncoding;stringstrFileNameExtension;bytebytes=this.rptViewer.LocalReport.Render(Excel,null,outstrMimeType,outstrEncoding,outstrFileNameExtension,outstrStreamIds,outWarnings);stringstrFilePath=D:+this.GetTimeStamp()+.xls;using(System.IO.FileStreamfs=newFileStream(strFilePath,FileMode.Create)fs.Write(bytes,0,bytes.Length);如果您需要使用本文档,请点击下载按钮下载!if(Pub.WinForm.Msg.Question(报表打印:rn成功导出Excel文件!+strFilePath+rn要现在打开文件+strFilePath+吗?)=DialogResult.Yes)System.Diagnostics.Process.Start(strFilePath);/*/刷新报表数据/privatevoidtool刷新_Click(objectsender,EventArgse)this.rptViewer.RefreshReport();/*/在加载报表数据时终止报表数据的加载/privatevoidtool终止_Click(objectsender,EventArgse)this.rptViewer.CancelRendering(0);如果您需要使用本文档,请点击下载按钮下载!/*/从DrillThrough报表返回到导航页面/privatevoidtool返回_Click(objectsender,EventArgse)if(this.rptViewer.LocalReport.IsDrillthroughReport)this.rptViewer.PerformBack();/*/回到报表的第一页/privatevoidtool第一页_Click(objectsender,EventArgse)this.rptViewer.CurrentPage=1;/*/跳转到报表的最后一页/privatevoidtool最后一页_Click(objectsender,EventArgse)this.rptViewer.CurrentPage=this.rptViewer.LocalReport.GetTotalPages();如果您需要使用本文档,请点击下载按钮下载!/*/以25%的比例显示报表/privatevoidtool25_Click(objectsender,EventArgse)this.rptViewer.ZoomMode=ZoomMode.Percent;this.rptViewer.ZoomPercent=25;/*/以50%的比例显示报表/privatevoidtool50_Click(objectsender,EventArgse)this.rptViewer.ZoomMode=ZoomMode.Percent;this.rptViewer.ZoomPercent=50;/*/以100%的比例显示报表/如果您需要使用本文档,请点击下载按钮下载!/privatevoidtool100_Click(objectsender,EventArgse)this.rptViewer.ZoomMode=ZoomMode.Percent;this.rptViewer.ZoomPercent=100;/*/以200%的比例显示报表/privatevoidtool200_Click(objectsender,EventArgse)this.rptViewer.ZoomMode=ZoomMode.Percent;this.rptViewer.ZoomPercent=200;/*/以400%的比例显示报表/privatevoidtool400_Click(objectsender,EventArgse)this.rptViewer.ZoomMode=ZoomMode.Percent;this.rptViewer.ZoomPercent=400;如果您需要使用本文档,请点击下载按钮下载!/*/将缩放模式设置为整页/privatevoidtool整页_Click(objectsender,EventArgse)this.rptViewer.ZoomMode=ZoomMode.FullPage;/*/将缩放模式设置为页宽/privatevoidtool页宽_Click(objectsender,EventArgse)this.rptViewer.ZoomMode=ZoomMode.PageWidth;/*/在报表中搜索txtSearch中的字符/privatevoidtool搜索_Click(objectsender,EventArgse)if(this.txtSearch.Text.Trim()=string.Empty)return;如果您需要使用本文档,请点击下载按钮下载!this.rptViewer.Find(this.txtSearch.Text.Trim(),1);/*/搜索报表中下一处txtSearch中的字符/privatevoidtool搜索下一个_Click(objectsender,EventArgse)if(this.txtSearch.Text.Trim()=string.Empty)return;this.rptViewer.FindNext();/*/跳转到上一页/privatevoidtool上一页_Click(objectsender,EventArgse)if(this.rptViewer.CurrentPage!=1)this.rptViewer.CurrentPage-;/*/跳转到下一页/如果您需要使用本文档,请点击下载按钮下载!/privatevoidtool下一页_Click(objectsender,EventArgse)if(this.rptViewer.CurrentPage!=this.rptViewer.LocalReport.GetTotalPages()this.rptViewer.CurrentPage+;/*/跳转到由txt跳转中指定的页数/privatevoidtool跳转_Click(objectsender,EventArgse)if(this.txt跳转.Text.Trim()=string.Empty)return;intintJump=0;if(System.Int32.TryParse(this.txt跳转.Text.Trim(),outintJump)if(intJump=this.rptViewer.LocalReport.GetTotalPages()this.rptViewer.CurrentPage=intJump;(六)你可能已经注意到了在调用LocalReport的Render方法时用到了一个XML格式的DeviceInfo结构,在SQL Server 2005 Report Services中,DeviceInfo结构是为了给特定的呈现格式传递参数。来看一个简单的DeviceInfo结构:如果您需要使用本文档,请点击下载按钮下载!EMF21cm29.70cm2cm2cm2cm2cm 这个简单的DeviceInfo结构至少为LocalReport的Render方法指定了输出格式、页宽、页高、左边距、右边距、下边距信息,在我们使用PrintPage的方法将LocalReport呈现为EMF图片时,EMF图片在页面上显示的大小、边距就是由这个DeviceInfo结构来决定的,如果为DeviceInfo结构和PrintDocumnt设置不匹配的页面大小或边距,那么在PrintPage事件中使用DrawImage方法画出的图片将出现放大或缩小的情况,这是我们不愿意看到的结果。也就是说,在使用自定义纸张进行单据打印时,我们不仅要为PrintDocument设置页面大小和边距,还要为LocalReport设置与PrintDocument相同的页面大小和边距。关于DeviceInfo的结构,可以参考 下面是我封装的一个为生成DeviceInfo结构使用的类:usingSystem;usingSystem.Collections.Generic;usingSystem.Text;namespaceRDLCReportpublicclassEMFDeviceInfoprivateboolm_Landscape=false;如果您需要使用本文档,请点击下载按钮下载!publicboolLandscape
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 图纸专区 > 课件教案


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!