资源描述
RDLC使用总结
1、 为何要使用RDLC报表(介绍)
VS .NET开发中,用什么进行报表设计?可能回复是Crystal Report,当然,必需认可Crystal Report功效还是很强大,被Business Object收购以后,商业成份也在逐步增加,也形成了一定规模用户群。
Visual Studio .NET进入本以后,Crystal Report和IDE结合更“紧密”了,最少我们看不到那个讨厌注册窗口了。不过,Microsoft似乎并不容忍在自己超级工具中竟然没有报表工具,于是Report Viewer Control出现了,我把它报表称为RDLC报表。
在VS .NET 之前,SQL Server Reporting Services中已经提供了一个被称为报表定义语言(Report Definition Language, RDL)语言;在VS .NET 中,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;
6) 数据源处理极其方便,开发人员能够自己接管数据库连接、取数,然后将数据结果赋值给RDLC数据集即可。
7) 展示和数据分离,程序员更是能够编写一个RDLC设计器交有用户使用,这么用户就能够自行设计RDLC报表格式,程序员只负责定制数据接口即可。
RDLC MSDN:(VS.80).aspx
2、 RDLC简单Demo
本文全部RDLC例子全部是基于VS C#,全部ReportViewer处理模式全部是Local模式。本报表Demo显示上文中提到RDLC手册各节内容,下述为Demo具体steps。
1) 新建项目,选择Windows应用程序项目类型,输入工程名称RDLCDev;
2) 修改Form1窗体名称为FrmRdlcUserGuide,在工具箱—>数据Tab选项卡中选择ReportViewer控件,将其拖入到FrmRdlcUserGuide,默认命名为reportViewer1,调整ReportViewer控件大小和布局;
3) 在处理方案资源管理器中选择RDLCDev工程,鼠标右击RDLCDev工程,添加新建项,在添加新项模板中选择“报表”,取名为rdlcuserguide.rdlc,单击添加按钮,然后在处理方案资源管理器中RDLCDev工程下会增加一个rdlcuderguide.rdlc文件,而且会自动打开RDLC设计器;
4) 在RDLC设计器中添加11个TextBox控件,1个作为标题,其它10个作为RDLC使用手册具体内容,对每个TextBox控件进行TextAlign、Color、BorderStyle、Font和TextDecoration等相关属性设置,设计完成以后,大致以下图所表示。
5) 在FrmRdlcUserGuide窗体Load事件中添加下述代码
private void Form1_Load(object sender, EventArgs e)
{
this.reportViewer1.ProcessingMode = Microsoft.Reporting.WinForms.ProcessingMode.Local;
this.reportViewer1.LocalReport.ReportPath = "rdlcuserguide.rdlc";
this.reportViewer1.RefreshReport();
}
6) 编译、运行RDLCDev工程,运行结果大致以下图所表示。
3、 RDLC常见控件介绍
RDLC设计工具箱上总共有9种控件:文本框(TextBox)、折线(Line)、表(Table)、矩阵(Matrix)、矩形(Rectangle)、列表(List)、子报表(SubReport)、图表控件(Chart)、图像控件(Image)。下图ctlsDemo.rdlc设计器所表示为全部控件设计演示。
1) 因为表格控件、矩阵控件、列表控件和图表控件必需填充数据集,所以把全部控件布局完成以后,创建一个数据集。处理方案资源管理器中,选中RDLCDev工程,右击添加新建项,在新建项类型模板里选择“数据集”,取名“ctlsDemo.xsd”,单击“添加”。
ctlsDemo.xsd添加完成以后,在处理方案资源管理器中会增加一个ctlsDemo.xsd文件,并前VS IDE会自动打开ctlsDemo.xsd设计页面。在设计页面中右击,添加Datatable,将其命名为vSales,该表描述是产品销售额信息,为vSales表添加列,列信息以下:
ProdCat System.String
SubCat System.String
OrderYear System.Int32
OrderQtr System.String
Sales System.Double
2) 文本框控件、折线控件、矩形控件使用相对简单,这里不细说;
3) Image控件,现在RDLC设计器模式下,选择“报表”菜单,“嵌入图像”,在“嵌入图像”对话框中,载入一个当地图像文件即可。然后设置Image控件Source属性为Embedded,设置Value属性为刚才处理嵌入图像即可。当然还有别方法能够显示图像,大家能够谷歌一下,关键字为RDLC、嵌入图像;
4) 图表控件,使用图表控件一个关键是要设置好图表属性页面中数据TAB页相关内容。关键有值、类别组和序列组定义,大家能够参考Demo;
5) 表格控件、矩阵控件和子报表控件,在后续内容中会具体介绍;
4.1 表格控件使用介绍
1) Table控件是RDLC报表显示数据一个关键控件,相关Table控件,在微软提供RDLC规范里有具体介绍,其大致内容能够用下述一张类UML图来表示;
2) 新建报表文件,命名为ctlTableDemo.rdlc;
3) 在ctlTableDemo.rdlc设计器中,拖入Table控件,默认情况下是3行3列,其中第1行为表头行(我们了解为列标题行),第二行为具体信息行(我们了解为报表内容展示区域),第三行为表尾行(我们了解为汇总区域)。能够整行选中,然后右击鼠标添加行或删除行,也能够整列选中,然后右击鼠标添加或删除列。上文中提到数据集合有5个字段,所以需要5列来显示,为此需要增加两列。
4) 在数据源窗口中(假如没有显示话,选择【数据】菜单下【显示数据源】即可)选择上文中创建ctlsDemo.xsd数据集,将ProdCat、SubCat、OrderYear 、OrderQtr和Sales分别拖入到Table控件具体信息行不一样列中去。
5) 设置标题行文字显示全部居中,Sales内容显示右对齐,ProdCat、SubCat、OrderYear、OrderQtr和Sales文本框字体颜色全部设置成Blue,Sales文本框因为显示内容为销售额,所以需设置数字显示格式,小数位数。鼠标右击Sales文本框,选择【属性】,在文本框属性窗口中,选择格式Tab页,在格式代码处,选择数字1,234.00格式即可,选择完成以后该文本框数字就以逗号千分位作为分割符,保留2位小数显示,效果以下图所表示。
6) 插入一个组实现分组统计功效。选中整行,鼠标右击,选择【插入组】,弹出分组和排序属性对话框,设置分组名称、分组方法、是否显示组头或组尾等属性即可,本文分组设置以下:
·分组名称:table1_Group1
·分组表示式:=Fields!ProdCat.Value;=Fields!SubCat.Value;=Fields!OrderYear.Value,实现产品年度销售额汇总统计功效。
·不显示组头、显示组尾(至于组头、组尾是个什么样东西,大家只要动手试一下就一目了然了)
·在textbox15中输入汉字“累计”,在textbox16文本框中输入累计表示式=Sum(CDbl(Fields!Sales.Value)),设置完以后效果以下图所表示。
7) 新建窗体FrmCtlTableDemo,然后在该窗体上添加ReportViewer控件,在窗体FrmCtlTableDemo代码窗口里输入以下代码:
private void FrmCtlTableDemo_Load(object sender, EventArgs e)
{
this.reportViewer1.ProcessingMode = Microsoft.Reporting.WinForms.ProcessingMode.Local;
this.reportViewer1.LocalReport.ReportPath = @"rdlc\ctlTableDemo.rdlc";
//
reportViewer1.LocalReport.DataSources.Add(new ReportDataSource("ctlsDemo_vSales", LoadData()));
//
this.reportViewer1.RefreshReport();
}
private DataTable LoadData()
{
DataSet dataSet = new DataSet();
dataSet.ReadXml(@"data\ctlsDemo.xml");
return dataSet.Tables[0];
}
8) 运行效果以下图所表示
4.2 矩阵控件使用介绍
1) 矩阵控件关键用于显示CrossTable之类报表,所以其列数能够是Static,也能够是Dynamic而且Can grow,相关矩阵控件,在RDLC协议规范里也有介绍,其大致内容能够用下图表示。
2) 新建报表文件,命名为ctlMatrixDemo.rdlc;
3) 在ctlMatrixDemo.rdlc设计器中,拖入Matrix控件,默认情况下是2行2列,左上角单元格为空白区域(通常见来显示报表摘要信息如产品/年度等),右上单元格显示为“列”,单击此处能够增加列分组,左下单元格显示为“行”,单击此处能够添加行分组,右下单元格显示为“数据”,单击此处能够添加静态行、静态列。
4) 在矩阵左上角单元格空白区域拖入矩形控件,然后在该矩形控件中拖入一个折线控件和两个文本框控件,折线当做矩形对角线,两个文本框内容为产品和年度分布在折线两侧。
5) 增加两个行分组,分别为matrix1_RowGroup1和matrix1_RowGroup2,matrix1_RowGroup1表示式为=Fields!ProdCat.Value,matrix1_RowGroup2表示式为=Fields!SubCat.Value。
6) 增加两个列分组,分别为matrix1_ColumnGroup1何matrix1_ColumnGroup2,matrix1_ColumnGroup1表示式为=Fields!OrderYear.Value,matrix1_ColumnGroup2表示式为=Fields!OrderQtr.Value。
7) 在“数据”单元格中编辑表示式=Sum(CDbl(Fields!Sales.Value))
8) 设计完以后,效果以下图所表示;
9) 新建窗体FrmCtlMatrixDemo,然后在该窗体上添加ReportViewer控件,在窗体FrmCtlMatrixDemo代码窗口里输入以下代码:
private void FrmCtlMatrixDemo_Load(object sender, EventArgs e)
{
this.reportViewer1.ProcessingMode = Microsoft.Reporting.WinForms.ProcessingMode.Local;
this.reportViewer1.LocalReport.ReportPath = @"rdlc\ctlMatrixDemo.rdlc";
//
reportViewer1.LocalReport.DataSources.Add(new ReportDataSource("ctlsDemo_vSales", LoadData()));
//
this.reportViewer1.RefreshReport();
}
private DataTable LoadData()
{
DataSet dataSet = new DataSet();
dataSet.ReadXml(@"data\ctlsDemo.xml");
return dataSet.Tables[0];
}
10) 运行效果以下图所表示
4.3 子报表控件使用介绍
子报表作为主报表一个补充,在显示明细内容时候比较管用,本文从怎样填充子报表数据,怎样传输参数两方面介绍子报表怎样使用。
1) 新建RDLC报表,命名为subReportDemo.rdlc;
2) 在subReportDemo.rdlc设计器中,拖入一个文本框和一个子报表控件;
3) 设置文本框文本显示为“子报表控件演示”;
4) 设置子报表控件属性,关键设置其“子报表”值,这里设为上文讲到ctlTableDemo报表,效果以下图所表示;
5) 新建一个窗体FrmSubReportDemo,添加以下代码
private void FrmCtlSubReportDemo_Load(object sender, EventArgs e)
{
reportViewer1.LocalReport.SubreportProcessing += new SubreportProcessingEventHandler(LocalReport_SubreportProcessing);
//
this.reportViewer1.ProcessingMode = Microsoft.Reporting.WinForms.ProcessingMode.Local;
this.reportViewer1.LocalReport.ReportPath = @"rdlc\subReportDemo.rdlc";
//
reportViewer1.LocalReport.DataSources.Add(new ReportDataSource("ctlsDemo_vSales", LoadData()));
//
this.reportViewer1.RefreshReport();
}
void LocalReport_SubreportProcessing(object sender, SubreportProcessingEventArgs e)
{
e.DataSources.Add(new ReportDataSource("ctlsDemo_vSales", LoadData()));
}
private DataTable LoadData()
{
DataSet dataSet = new DataSet();
dataSet.ReadXml(@"data\ctlsDemo.xml");
return dataSet.Tables[0];
}
这里,区分于其它显示RDLC报表程序代码就是对子报表处理,本文在FrmCtlSubReportDemo_Load事件里添加了一个对子报表事件处理:reportViewer1.LocalReport.SubreportProcessing += new SubreportProcessingEventHandler(LocalReport_SubreportProcessing);
6) 相关子报表参数怎样传输,在RDLC报表参数介绍一文中介绍;
7) 运行效果以下图所表示
4、 RDLC参数介绍
5.1 报表参数处理
1) 修改上文提升ctlTableDemo.rdlc报表为例,该报表用于显示产品每三个月销售额。修改该报表,给该报表添加一个参数prod_cat,用于过滤只显示产品系统为参数prod_cat值对应产品季度销售额。
2) 在ctlTableDemo.rdlc设计器中,选择【报表】菜单,【报表参数】菜单,在报表参数界面中,添加一个报表参数取名为“prod_cat_sub”,类型为String,提醒信息为“输入产品系列名称”,许可空白值;
3) 选中table1控件,鼠标右击,选择【属性】,选中【筛选器】Tab页,在筛选器列表中添加:=Fields!ProdCat.Value = =Parameters! prod_cat_sub.Value;
4) 在FrmCtlTableDemo窗体中添加下述代码,用红色表示2行代码:
private void FrmCtlTableDemo_Load(object sender, EventArgs e)
{
this.reportViewer1.ProcessingMode = Microsoft.Reporting.WinForms.ProcessingMode.Local;
this.reportViewer1.LocalReport.ReportPath = @"rdlc\ctlTableDemo.rdlc";
//
reportViewer1.LocalReport.DataSources.Add(new ReportDataSource("ctlsDemo_vSales", LoadData()));
//
ReportParameter p = new ReportParameter("prod_cat_sub", "Component");
reportViewer1.LocalReport.SetParameters(new ReportParameter[] { p });
//
this.reportViewer1.RefreshReport();
}
5) 运行结果以下图所表示,显示Component产品系列产品季度销售额;
5.2 子报表参数处理
1) 在程序里面,本人还未找到直接向子报表传输参数方法,不过能够用其它方法变通实现,在主报表subreport控件属性里面设置参数,经过主报表传输过去。
2) 以上文提到FrmSubReportDemo为例,其主报表为subReportDemo.rdlc,先设置主报表参数。在subReportDemo.rdlc报表设计器中选择【报表】,【报表参数】,在报表参数对话框中,增加一个参数。参数名称为prod_cat,参数类型为String,参数提醒为“输入产品系列名称”。
3) 选中子报表subreport1,鼠标右击,选择【属性】,选择【参数】tab页,添加一个参数。参数名称为“prod_cat_sub”,参数值=Parameters!prod_cat.Value。为此,主报表参数名和子报表参数名称要不一致。
4) 打开subreport1对应子报表设计器,本文为ctlTableDemo.rdlc,该ctlTableDemo.rdlc参数在上文中已经设置,这里不再赘述。
5) 运行效果以下图所表示。(源码网整理:.com)
5、 RDLC钻取功效实现
本Demo在主报表会显示一个部门列表(部门ID、部门名称等),然后经过钻取功效可实现特定部门职员信息展示,下述为具体操作步骤。
1) 准备好两个数据源,本文为2个xml文件(departments.xml和Employees.xml),这两个文件放在项目标Data文件夹下,尤其注意是这两个文件【复制到输出目录】属性要选择“一直复制”,负责工程编译时候不会将这两个文件生成到bin目录下。
2) 新建报表,命名为“drillthrough.rdlc”;新建一个数据集,命名为“departments”,在该数据集中添加一个Datatable,表结构以下:
DepartmentID Int32
Name String
GroupName String
ModifiedDate DateTime
rowguid String
3) 在drillthrough.rdlc设计器中,拖入一个文本框和一个Table控件。文本框显示内容为“Drill Through Demo”,在Table控件中拖入DepartmentID和Name两列。
4) 添加Name列导航、钻取功效。右击Name文本框,选择【属性】,选择【导航】Tab页,在“超级链接”处选择“跳至报表”(该报表为显示钻取实现目标报表,假设为drillthroughDetail.rdlc,且已经存在,所以在实践时,能够再本操作之前,先创建一个drillthroughDetail.rdlc报表),设置“跳至报表”为drillthroughDetail,点击【参数】按钮,会弹出参数设置对话框。在对话框中,添加一个参数,名称为DepartmentID,值为=Fields!DepartmentID.Value;
5) 设计drillthroughDetail.rdlc报表,先新建一个该报表对应数据集,名称为employees,添加一个DataTable,名称为employee,employee表部分内容以下:
<table>
<EmployeeID>1</EmployeeID>
<FirstName>Terri</FirstName>
<AddressID>1</AddressID>
<ShiftID>1</ShiftID>
<LastName>Duffy</LastName>
<MiddleName>Lee</MiddleName>
<NameStyle>false</NameStyle>
<NationalIDNumber></NationalIDNumber>
<Title>VP Engineering</Title>
<HireDate>1998-03-03T00:00:00.0000000-08:00</HireDate>
<BirthDate>1961-09-01T00:00:00.0000000-07:00</BirthDate>
<LoginID>adventure-works\Terri</LoginID>
<EmailAddress></EmailAddress>
<DepartmentID>1</DepartmentID>
<MaritalStatus>S</MaritalStatus>
<EmergencyContactName>Tad Orman</EmergencyContactName>
<EmergencyContactPhone>586-883-8338</EmergencyContactPhone>
<SalariedFlag>true</SalariedFlag>
<Gender>F</Gender>
<ManagerID>300</ManagerID>
<PayFrequency>2</PayFrequency>
<BaseRate>63.4615</BaseRate>
<VacationHours>1</VacationHours>
<SickLeaveHours>20</SickLeaveHours>
<SalesPersonFlag>false</SalesPersonFlag>
<CurrentFlag>true</CurrentFlag>
<ModifiedDate>-01-15T19:26:13.9000000-08:00</ModifiedDate>
<rowguid>1b76e019-0d60-4d48-b405-c9144fb9b3ab</rowguid>
</table>
从表内容中,我们能够大致判定出其结构是什么样啦。
6) 拖入一个文本框控件和表格控件到drillthroughDetail.rdlc报表设计器中,并从employees数据集中拖入对应字段到表格控件中,设置完成以后,效果以下图所表示。
7) 设置drillthroughDetail.rdlc报表参数:参数名称为DepartmentID,类型为Integer;
8) 设置drillthroughDetail.rdlc报表表格控件筛选器,表示式为=CInt(Fields!DepartmentID.Value),运算符为=,值为=Parameters!DepartmentID.Value。
9) 新建一个窗体FrmDrillThrough,添加一个ReportViewer控件,在代码编辑窗口,添加下述代码:
private void FrmDrillThrough_Load(object sender, EventArgs e)
{
reportViewer1.ProcessingMode = ProcessingMode.Local;
reportViewer1.LocalReport.ReportPath = @"Rdlc/drillthrough.rdlc";
reportViewer1.LocalReport.DataSources.Add(new ReportDataSource("departments_department", LoadData(@"Data\departments.xml")));
reportViewer1.RefreshReport();
}
//读取XML数据
private DataTable LoadData(string xmlFilePath)
{
DataSet dataSet = new DataSet();
dataSet.ReadXml(xmlFilePath);
return dataSet.Tables[0];
}
private void reportViewer1_Drillthrough(object sender, DrillthroughEventArgs e)
{
LocalReport localReport = (LocalReport)e.Report;
localReport.DataSources.Add(new ReportDataSource("employees_employee", LoadData(@"Data\Employees.xml")));
}
10) 运行效果以下图所表示。
鼠标移到Name一列,会变成手形状,如单击Engineering,就会钻取取来Engineering部门职员信息,以下图所表示。
6、 RDLC自定义工具条
1) 自定义工具条能够了解为对ReportViewerToolBar功效一个变通实现,如添加代码实现ToolBar刷新按钮功效、ToolBar页导航功效。
如刷新功效代码实现为:
this.rptViewer.RefreshReport();
如ToolBar停止按钮代码实现为:
this.rptViewer.CancelRendering(0);
。。。
2) 在做项目标时候,假如用ReportViewer控件做报表展示工具话,打印和导出代码实现,应该要掌握。
导出功效:ReportViewer导出全部是经过Render来实现,以下代码为导出Excel
Microsoft.Reporting.WinForms.Warning[] Warnings;
string[] strStreamIds;
string strMimeType;
string strEncoding;
string strFileNameExtension;
//this.rptViewer.LocalReport.Render(
byte[] bytes = this.rptViewer.LocalReport.Render("Excel", null, out strMimeType, out strEncoding, out strFileNameExtension, out strStreamIds, out Warnings);
string strFilePath = @"D:\exportdemo.xls";
using (System.IO.FileStream fs = new FileStream(strFilePath, FileMode.Create))
{
fs.Write(bytes, 0, bytes.Length);
}
打印例子下载,打印也是一个间接行为,有点类似ReportViewer控件需要经过点击打印按钮来打印一样,并没有提供直接打印函数,为此本人封装了打印功效(在附件whhrdlc.dll文件中)并开放了打印函数,用户能够调用下面语句打印报表:
//打印犯错时,错误信息描述
String errMsg = String.Emptys;
//调用打印函数(弹出打印设置对话框)返回false打印失败;
bool bln = Printer.PrintDialog(this.reportViewer1.LocalReport, out errMsg);
//调用打印函数(直接打印)返回false打印失败;
bool bln = Printer.Print (this.reportViewer1.LocalReport, out errMsg);
7、 设计器实现
8.1 RDLC XML分析
1) RDLC文件其实就是一个XML文件,有很多结点和元素,在处理方案资源管理器中选中某个rdlc文件,鼠标右击,选择【打开方法】,在打开方法对话框中选择XML编辑器,单击确定按钮即可。
在xml文件中我们能够看到DataSources、PageHeader、DataSets、ReportItems等结点,网上有篇Vs报表设计器XML分析总结博文
,写比较具体,大家能够参考。
2) 这里比较关键就是DataSet处理,Rdlc报表不管是表格显示还是矩阵显示或列表显示数据,全部需要关联DataSet。在前面提到全部篇幅中,全部是先创建一个数据集,并为该数据集添加一个DataTable,然后将表字段拖放到表格控件、矩阵控件或列表控件,用以显示数据。这么做,从效率上来看不是最高,因为手工产生一个目标DataTable比较耗时。为此,我们能够先直接编辑rdlcxml文件,编辑器dataset内容即可,以下所表示:
<DataSets>
<DataSet Name="ctlsDemo_vSales">
<Fields>
<Field Name="ProdCat">
<DataField>ProdCat</DataField>
<rd:TypeName>System.String</rd:TypeName>
</Field>
<Field Name="SubCat">
<DataField>SubCat</DataField>
<rd:TypeName>System.String</rd:TypeName>
</Field>
<Field Name="OrderYear">
<DataField>OrderYear</DataField>
<rd:TypeName>System.Int32</rd:TypeName>
</Field>
<Field Name="OrderQtr">
<DataField>OrderQtr</DataField>
展开阅读全文