前一段时间,发了几篇关于RDLC报表的随笔,由于这些随笔中没有关于报表设计方面的内容,于是不少网友和我联系,问了一些关于报表设计方面的问题,最近准备写几篇关于RDLC报表设计的随笔。
这篇随笔主要描述实现钻取报表的步骤。
钻取报表的数据源应该是两个具有主子关系的表,在这篇随笔中以Northwind数据库中的订单和订单明细作为数据源。
1、在Visual Studio 2005中创建一个Windows应用程序RDLCDR。
2、在项目中添加数据源,数据源并不一定用来为报表提供数据(当然Visual Studio 2005提供的操作非常方便),主要是在报表设计时可以方便向报表中进行字段拖曳。添加数据源意味着在项目中添加了一个数据集Orders.xsd文件,当报表的数据不是来源于关系型数据库(如Flat Files或Web Services等)时,我们可以自己定义一个xsd文件作为报表设计时的数据源,而在程序中重新为报表载入数据。
3、在项目中添加报表rptOrder.rdlc,这个报表非常简单,不具体介绍其设计步骤。报表文件中将显示“订单”的内容,其结构如下图1所示:
图1 “订单”报表的结构
4、同上,添加报表rptOrderDetails.rdlc,其结构如下图2所示:
图2 “订单明细”报表的结构
5、在报表rptOrder.rdlc中,选中表控件的“表详细信息”行的第一列“=Fields!订单ID.Value”单元格,右键“属性”弹出“文本框属性”对话框(如图3所示),在“导航”选项卡的“超链接操作”中,选中“跳至报表”并在下拉列表中选择报表rptOrderDetails,单击下拉列表右边的“参数...”按钮,进行入图4所示的设置。
图3 “文本框属性”对话框
图4 “跳至报表”参数设置
6、在报表rptOrderDetails中,使用菜单“报表” →“报表参数”进入“报表参数”对话框,并如下图5所示设置参数orderid,这个参数主要用于从rptOrder接收传值。
7、选中报表rptOrderDetail中的表格控件,右键“属性”,进入“表属性”对话框,在“筛选器”选项卡中,设置如下图6所示的筛选器。在构造筛选器时,最好使用“编辑表达式”对话框生成表达式,除非足够熟悉,否则,手写表达式很可能会出现错误,例如表达式前面一定要有“=”。
图6 筛选器设置
OK,至此,报表设计需要做的内容就完成了,下面是如何为报表提供数据,并显示在ReportViewer中了。
8、在WinForm窗体上放置ReportViewer控件,并单击控件右上角的三角符号,弹出“ReportViewer 任务”对话框中(图7),选择报表RDLCDR.rptOrder.rdlc。如果前面提到的数据集文件(.xsd文件)是由系统自动生成的话,系统会自动为窗体生成DataAdapter、BindingSource和DataSet,删除之,我们在下面的步骤中手动指定报表的数据源,否则可能会出现报表不报错,但报表内无数据的情况。
图7 ReportViewer任务对话框
9、在窗体中使用下图8所示的代码为报表和钻取报表指定数据源,完成最后的操作。需要注意的是下图8中的“数据集名称”必须指定正确,而这个名称可以从下图9所示的对话框中取得。
图9 “数据集名称”的出处
结果截图如下:
图10 “订单”报表
图11 “订单明细”钻取报表
Demo下载
另外,在Web应用程序中,也可以使用此方法建立DrillThrough报表,不过代码中的Microsoft.Reporting.WinForms.ReportDataSource要改为Microsoft.Reporting.WebForms.ReportDataSource。
前两天,有网友在Blog上评论要求将子报表的配置贴出来,由于这两天有些别的事情,所以耽搁了;另外,自己也比较懒,有些东西明明应该早就写出来的。呵呵,说声“对不起”,然后还有“谢谢你”!
OK,这篇随笔就讲一下RDLC报表中子报表SubReport的实现步骤。
首先来看一下,本文的示例的运行结果。
图1 主子报表示例运行结果
主子报表的数据源显然也应该是两个具有主子关系的数据表,本文示例依然使用Northwind数据库的订单和订单明细表作为数据源。
1、在Visual Studio 2005中创建一个Windows应用程序RDLCSR。
2、在项目中添加数据源,数据源并不一定用来为报表提供数据(当然Visual Studio 2005提供的操作非常方便),主要是在报表设计时可以方便向报表中进行字段拖曳。添加数据源意味着在项目中添加了一个数据集Orders.xsd文件,当报表的数据不是来源于关系型数据库(如Flat Files或Web Services等)时,我们可以自己定义一个xsd文件作为报表设计时的数据源,而在程序中重新为报表载入数据。
3、在项目中添加报表rptOrder.rdlc和rptOrderDetail.rdlc分别作为示例的主报表和子报表。
4、为子报表rptOrderDetail.rdlc添加参数pOrderId,指定其数据类型为Integer,然后如图2进行子报表的布局设计。
图2 子报表rptOrderDetail.rdlc布局设计
5、为主报表rptOrder.rdlc进行如图3所示的布局设计。
图3 主报表rptOrder.rdlc布局设计
6、在主报表rptOrder.rdlc的子报表控件上单击右键,使用“属性”菜单调出“子报表属性”对话框。在“常规”选项卡中的子报表下拉列表中选择rptOrderDetail;切换到“参数”选项卡,在“参数名称”列中,系统会自动检测到步骤4中定义的子报表的参数pOrderId,并在“参数值”列中指定参数值为=Fields!订单ID.Value。
7、在子报表rptOrderDetail.rdlc中选择表格控件,使用右键菜单“属性”调出“表属性”对话框,在“筛选器”选项卡中进行入图4的设置。这主要是为了在订单明细中筛选当前订单的明细数据,当然这一步骤可以在程序中用代码指定。
图4 在子报表rptOrderDetail.rdlc中指定筛选器
好了,至此报表布局的设置已经完成了,下面需要在应用程序中显示报表并给主子报表分别提供数据。
8、在窗体frmMain中添加ReportViewer控件rptMain,并在rptMain的“ReportViewer任务”中选择报表rptOrder.rdlc。
9、在窗体frmMain中添加图5所示的代码:
图5 窗体frmMain的代码
可见,必须对ReportViewer控件的LocalReport对象添加SubReportProcessing事件,而该事件主要也就是为了子报表提供数据。
现在就可以运行应用程序查看结果了,如图6所示。
图6 示例运行结果(未给列表指定分组)
在图6中,我们看到出现两个订单显示在同一页面,而在实际应用中,我们可能希望,每个页面
上只显示一条订单。此时,可以进行以下的设置:
10、在主报表rptOrder.rdlc中,选择列表控件,右键“属性”弹出“列表属性”对话框,在“常规”选项卡中,单击按钮“编辑详细信息组”弹出“分组和排序属性对话框”并进行如图7所示的设置。
图7 为列表指定分组并设置分页显示选项
事实上,主子报表和钻取报表有着相似的地方,所以如果看了这篇随笔有什么不明白的地方,可以参看一下我的另一篇随笔RDLC Report Step by Step 1: DrillThrough Report。
发表于 2006-07-24 16:23 蜡人张 阅读(3923) 评论(51) 编辑 收藏 引用 网摘 所属分类: C# 、Reporting
Crystal Report在报表向导中提供了三种向导类型给用户进行选择——Standard、Cross-Tab和Mail Label,而Visual Studio/BIDS报表向导只有两种——表格格式和矩阵,这是和Crystal Report的前两种报表类型相对对应的,那么怎么在Visual Studio/BIDS中实现Mail Label呢?
先来看一下什么是Mail Label。Mail Label如果直译成中文的话,就是“邮件标签”,这是一个有歧义的名词,一些邮箱(如Gmail)和客户端邮件工具(如Foxmail)将“邮件标签”作为一种将邮件进行分类以方便信息管理的工具。而本篇随笔讨论的显然无关“电子”邮件,而是一种比较常用的报表。设想如下的场景:如果一个组织(比如一家出版社)需要向一批客户发一份比较正式的书面信件(比如征订启事)。而这些客户的通信地址、收件人邮政编码等又以某种形式(数据库、平面文件等)存储在计算机中,工作人员显然不希望在每一个信封上手工书写这些信息,他/她要做的无非是把这些打印出来并粘贴到信封上就可以了。这样的话,一个普通的报表也可能就已经能够满足他/她的需求了,尽管我们知道邮政编码、通信地址、收件人三个字段之间是需要换行的。但是,如果他/她恰巧使用的是常见的如A4之类的纸张,而同时他/她又不希望浪费纸张,那么他/她希望要的报表可能就是如图1所示的报表了。这就是所谓的“邮件标签”报表了,当然“邮件标签”报表不仅仅局限于多个信件通信地址的一次打印,凡是具有类似结构的报表都可以被称为“邮件标签”报表。
图1 Access的Northwind示例数据库中的“邮件标签”报表(点击小图看大图)
正如图1的标题所示,Access是支持“邮件标签”报表的,不过在报表设计上只是让标签中涉及到的字段纵向排列而已,真正实现多列标签打印是通过对报表的“页面设置”来完成的,如图2所示。
图2 Access中“邮件标签”报表的“页面设置”
在进行报表设计之前,我们先为本文的邮件标签进行数据准备。本文的示例报表的数据来源于SQL Server 2005的示例数据库AdventureWorks,在AdventureWorks数据库中使用以下SQL语句建立视图Production.MailLabel:
代码1:创建视图Production.MailLabel
USE [AdventureWorks]
GO
/**//****** 对象: View [Production].[MailLabel] 脚本日期: 08/26/2006 16:05:26 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE VIEW [Production].[MailLabel]
AS
SELECT Production.Product.Name, Production.Product.Color, Production.ProductPhoto.ThumbNailPhoto
FROM Production.Product INNER JOIN
Production.ProductProductPhoto ON Production.Product.ProductID =
Production.ProductProductPhoto.ProductID INNER JOIN
Production.ProductPhoto ON Production.ProductProductPhoto.ProductPhotoID =
Production.ProductPhoto.ProductPhotoID
WHERE (Production.Product.Color IS NOT NULL)
GO
打开视图,我们可以得到如图3所示的示例数据,这将是本文示例所使用的报表数据。
图3 示例使用数据
也就是说,本文的示例演示的邮件标签中展示的数据是AdventureWorks生产的自行车的名称、颜色以及缩略图。
既然是邮件标签,我们要将Name、Color以及ThumbNailPhoto这三个一行中字段纵向显示,这个比较容易实现;我们还需要将指定行数的数据作为一列显示在报表中,这就涉及到行到列的转换问题。事实上,可以说行列转换问题是邮件标签报表面临的最大的问题,要解决这个问题,一种可行的方案是使用SQL语句中出现在FROM子句中的PIVOT关系运算符将表结构进行转换,然后使用Table控件显示数据。另外,我们知道标准控件中的Matrix控件的功能其实就是一个Pivot Table(数据透视表),我们可以清楚地在控件工具栏上看到对Matrix控件的提示是“用于任何多列样式报表的行列布局”,该控件对数据的处理其实是和PIVOT运算符是相通的,就是说使用该控件可以避免使用PIVOT运算符而实现一个交叉表的结构,所以本文选择使用这种方案来实现邮件标签报表。
1、创建报表服务器项目RDLML。
2、新建共享数据源DataMailLabel,设置到数据库AdventureWorks的连接,并为报表指定相应的访问凭据。
3、不使用向导新建报表rptMailLabel,在报表设计器的“数据”选项卡,新建数据集MailLabel,使用工具栏按钮切换到通用查询设计器,在“关系图”窗格中使用右键菜单“添加表”并选择视图Production.MailLabel,选择Name、Color、ThumbNailPhoto三列作为输出,这样我们在SQL窗口中可以看到以下SQL语句:
代码2:选择数据的SQL语句
SELECT
Name,
Color,
ThumbNailPhoto
FROM Production.MailLabel
4、在SQL窗格中修改代码2中的SQL语句如代码3所示。
代码3:修改代码2得到的SQL语句
SELECT
(ROW_NUMBER() OVER (ORDER BY Name) - 1) / 4 + 1 AS TitleRow,
(ROW_NUMBER() OVER (ORDER BY Name) - 1) % 4 + 1 AS TitleColumn,
Name,
Color,
ThumbNailPhoto
FROM Production.MailLabel
代码3中,ROW_NUMBER()用于为返回数据的行号,需要和OVER关键字结合使用,使用OVER关键字可能会导致图4所示提示信息的出现,这是由于通用查询设计器不支持OVER关键字所导致的,而事实上T-SQL是支持该关键字的,可以忽略此信息的出现。
图4 使用OVER关键字出现的提示信息
代码3选择出的数据如图5所示。
图5 代码3选择出的数据
5、按照图6的方式进行报表布局设计。
图6 报表布局设计
其中,拖动图像控件到报表布局时会出现“图像向导”,在“选择图像源”页面中选中“数据库”,并在接下来的“指定图像字段”页面中,进行如图7所示的设置。
6、选中值为“=Fields!TitleRow.Value”的文本框,右键“属性”,在“文本框属性”对话框的“可见性”选项卡中,选择“初始可见性”为“隐藏”,同样设置值为“=Fields!TitleColumn.Value”的文本框。
7、为了明显区分邮件标签列表中的各个项目,可以选中列表框控件,F4调出属性浏览器,设置BorderColor为LightGray,设置BorderStyle为Dashed;另外,为了使报表看起来更美观,可以在列表框中微调控件的位置。
OK,到此为止,一个邮件标签报表就设计完成了,其预览效果如图8所示。
至于在这些步骤中隐藏的设计思路,请朋友们自己总结。
感谢jimmyhell在本Blog的评论,是他提出了这个问题,不然我不会想到要去做一个邮件标签报表,谢谢!
发表于 2006-09-02 22:29 蜡人张 阅读(1984) 评论(26) 编辑 收藏 引用 网摘 所属分类: Reporting