会员管理系统的设计和开发(2)-- RDLC报表的设计及动态加载

在上篇《会员管理系统的设计和开发(1)》介绍了关于会员系统的一些总体设计思路和要点,经过一段时间开发,软件终于完成并发布。在这期间,碰到了不少技术难点,并积累了不少开发心得和经验,本篇继续介绍这个开发过程中相关的技术要点,主要介绍其中RDLC报表的相关操作,如报表的设计和通用的动态加载模块的处理等内容。

什么是RDLC呢,它的全称是Report Definition Language Client-Side,原来是微软基于SQL Server 报表服务中经提供了一种被称为报表定义语言(Report Definition Language, RDL)的改进版本,增加了客户端处理报表功能,在WinForm和WebForm中均可以使用这种报表。

1、RDLC报表的设计

我们知道,RDLC报表展现是基于一个定义的报表文件的,一般是以rdlc后缀名的报表文件,在VS里面新建一个项,选定报表文件即可,如下所示。

会员管理系统的设计和开发(2)-- RDLC报表的设计及动态加载

RDLC的报表设计界面,提供了很多相关的控件进行绘制。

会员管理系统的设计和开发(2)-- RDLC报表的设计及动态加载

通过这些操作我们可以创建一些报表的元素在里面,如可以增加一些数据字段和列表字段在里面,最简单的报表例子里面,可以增加一些图片,标题,列表等内容,如下所示。

会员管理系统的设计和开发(2)-- RDLC报表的设计及动态加载

但往往这个只是测试阶段的学习,一般情况下,我们的报表比上面的规范很多,要考虑样式还有布局设计等方面,下面给出一些我会员系统里面的报表例子供参考对比。

下面是一个会员消费清单的报表设计,包括总的消费情况和明细报表设计。

会员管理系统的设计和开发(2)-- RDLC报表的设计及动态加载

以及一个会员身份的打印报表设计。

会员管理系统的设计和开发(2)-- RDLC报表的设计及动态加载

设计报表完成,只是完成了一部分工作,我们还需要建立数据集,把字段绑定到报表上面去,如上面的[Name]这样标识的就是字段已经绑定的了,一开始这些可能是没有的,需要我们先创建数据集对象。

会员管理系统的设计和开发(2)-- RDLC报表的设计及动态加载

创建数据集对象,可以选择是DataSet类型的或者是实体类型的,网上介绍很多是基于DataSet方式的,由于我的Winform框架及整个系列的产品是基于实体类的,因此我的报表创建的数据集对象也是基于实体对象的。

从上面可以看出,创建的数据集对象,是引用我的实体类对象,里面包含了很多对象属性,非常容易理解。

创建了相应的数据集对象后,我们进一步就是把这些信息绑定到设计的报表上面了。

先在报表视图里面,把列表对象选中,绑定它的数据集对象,操作如下面两个图所示。

会员管理系统的设计和开发(2)-- RDLC报表的设计及动态加载

会员管理系统的设计和开发(2)-- RDLC报表的设计及动态加载

这样我们就可以随意指定列表里面的列的字段绑定操作了。

会员管理系统的设计和开发(2)-- RDLC报表的设计及动态加载

2、RDLC报表的动态加载

通过第一节介绍的报表设计和数据集对象的创建,然后进行绑定操作后,基本上设计部分就已经完成了,注意的就是调整好对应的格式,加载测试后进行微调整即可了。

本小节继续介绍,如何把数据进行动态加载进行绑定。

为了实现报表的预览,我们需要在UI项目里面添加下面两个程序集对象。

会员管理系统的设计和开发(2)-- RDLC报表的设计及动态加载

然后在一个预览报表的窗体里面,放置一个报表查看控件ReportViewer,设计报表预览界面窗体如下所示。

会员管理系统的设计和开发(2)-- RDLC报表的设计及动态加载

以后我们设计的报表,就准备通过这个界面进行展现的了。

通过ReportViewer我们可以获得LocalReport对象的引用,然后对它进行处理即可。

LocalReport report = this.rpViewer.LocalReport;

报表的数据绑定,主要就是增加报表对象里面的对应的ReportDataSource对象即可。

通过报表对象LocalReport,我们可以使用代码增加对应的数据源给它的报表对象,这样我们需要展现的报表数据源就可以和报表进行绑定了,具体的处理代码如下所示。

会员管理系统的设计和开发(2)-- RDLC报表的设计及动态加载

那么我们如何在界面窗体里面进行报表的绑定操作呢?

封装好通用的报表展现界面后,我们只需要调用他们的接口进行绑定一个新的报表和数据源了。具体代码如下所示。

        private void menuPrintReport_Click(object sender, EventArgs e)
{
string headerID = this.winGridViewPager1.gridView1.GetFocusedRowCellDisplayText("ID");
if (!string.IsNullOrEmpty(headerID))
{
MemberConsumptionInfo consumptionInfo = BLLFactory<MemberConsumption>.Instance.FindByID(headerID);
if (consumptionInfo != null)
{
//修改一些属性值
//会员姓名
consumptionInfo.Data1 = BLLFactory<Member.BLL.Member>.Instance.GetNameByID(consumptionInfo.Member_ID);
consumptionInfo.Data2 = SecurityHelper.GetFullNameByID(consumptionInfo.Creator); List<MemberConsumptionInfo> list = new List<MemberConsumptionInfo>();
list.Add(consumptionInfo); List<ConsumptionDetailInfo> detailList = BLLFactory<ConsumptionDetail>.Instance.FindByBillNo(consumptionInfo.BillNo);
foreach (ConsumptionDetailInfo info in detailList)
{
//修改ProductID为商品编码
info.Product_ID = BLLFactory<MemberProduct>.Instance.GetHandNoByID(info.Product_ID);
} ReportViewerDialog dlg = new ReportViewerDialog();
dlg.DataSourceDict.Add("MemberConsumptionInfo", list);
dlg.DataSourceDict.Add("ConsumptionDetailInfo", detailList);
dlg.ReportName = "WHC.Member.ConsumptionReport"; AppConfig config = new AppConfig();
string companyName = config.AppConfigGet("CertificatedCompany");
dlg.Parameters.Add("CompanyName", companyName);
dlg.ShowDialog();
}
}
}

3、RDLC报表的展现效果

在上面两个小节里面,我们已经介绍过RDLC报表如何设计、如何绑定到ReportViewer报表预览界面上了,还有也说明了如何在主窗体里面使用数据源进行动态的加载操作,但到底具体的报表展现效果如何呢,下面我给出几个案例作为参考。

1)消费清单报表

会员管理系统的设计和开发(2)-- RDLC报表的设计及动态加载

2)收费记录报表

会员管理系统的设计和开发(2)-- RDLC报表的设计及动态加载

3)会员卡片打印报表

会员管理系统的设计和开发(2)-- RDLC报表的设计及动态加载

上一篇:《Publish or Perish》——从某种角度来说,我们也算和世界同步了呢。


下一篇:从零开始学Python第七周:面向对象进阶(需修改)