第14章 Reporting Services

我所写的书中有一些章节重叠了入门篇和高级篇的部分内容。虽然初级和高级内容应该分得很清,但那其实仅限于理想情况:即人人都以同种方式、按同样顺序获得经验,并且对初级和高级的定义有统一的认识。

本章中就有一些重叠的内容,已经阅读过入门篇的读者会注意到这一点。对于Reporting Services而言,这样做的原因是多方面的,主要的两个原因是:

有些人只是出于控制个人报表的目的而进行数据库开发(在这种情况下,他们几乎都是直接从Reporting Services开始学起,然后学习用于支持报表中的数据的查询)。而还有一些人是数据库"专家",他们的目的在于使用SQL Server提供的"额外"功能。

这是一项较新的功能(相对于SQL Server这个具有长久生命力的产品而言),所以它对于许多专业级别的人士来说也是很生疏的。

即使阅读过入门篇中的"报告"一章,对本章内容也不要匆匆一览而过。因为尽管这里重复了一些关键内容,但是会稍作深入讨论,并更着重于介绍真正面向开发人员的内容(而较少关注模型驱动方面的内容)。不过,直接跳至有关数据源和数据源视图的章节也是可以的,我们将从更为"专业"的角度研究其中的内容,包括参数化、钻取以及图表制作。

14.1  报表服务概述

在完成了所有查询语句的编写和存储过程的运行之后,为使得数据有用,还有一件相当重要的事情要做--使数据对终端用户可用。

报表是一种看上去极为简单,实则相当棘手的事物。你不能只是简单地把数字堆在人们面前。这些数字必须是有意义的,可能的话,还要能够抓住报表接受者的注意力。要生成实际可用的、有用的报表,需记住以下几点:

数据的使用量要恰当:一份报表中所列出的数据不能太多,也不能太少。一份充斥了大量数据的报表会令阅读者迅速失去兴趣,并且仅在最初的几个项生成之后就被弃而不用。同样,一份言之无物的报表也仅能得到匆匆一瞥,随即便被毫不犹豫地丢弃。所以,应在恰当的数据和恰当的数据量之间找到一种平衡。

报表要美观大方:不得不说的是,报表的另一个重要要素就是所谓的"美观",也就是说,报表应该做得赏心悦目。难看的报表是没有人会看的。

在这一章中,我们将介绍Reporting Services(通常也称作SSRS)的几个关键概念,然后再进一步介绍一些高级内容。虽然略过了一些"基础"内容,但为了使更高级的内容明白易懂,我们也涉及到了一些必要的基本知识,但接着很快就介绍Report Designer的内容,其涉及Reporting Services提供的最为高级的报表选项。

提示:

出于行文简洁的考虑(也是为了使重复的内容最少化),本书对于报表模型仅介绍其作用,而不附具体示例,以此区分初级和高级内容。不过,即使你在阅读本章之前还不太理解报表模型,也可以通过学习一些核心内容,如数据源和报表设计器,来了解如何使用报表模型器和报表模型设计器。实际报表的构建也是一样简单。

14.2  Reporting Services入门

很有可能,你已经生成过一些报表。它们可能是通过打印机打印出来的纸质报表(采用像Access所提供的那样的初级报表功能,实际上这是我最喜欢的Access的功能之一)。或者你使用了某种相当强大的报表引擎,例如Crystal Reports。即便没有使用过这些工具,你应该也有过从存储过程生成简单(虽然不太美观)的报表来提交给老板的经历。我认为这种可能性很大。

但实际情况是,如今的经理和合作者们的期望越来越高。Reporting Services才会应运而生,它实际上有两种不同的操作:

报表模型(Report Model):它利用一个相对简单、Web驱动的接口让终端用户自行创建简单报表。

在Business Intelligence Development Studio中生成报表:这并不意味着一定要编写代码(实际上通过拖放功能就可以创建一个相当棒的报表),而是可根据所需创建更复杂的报表。

注意,虽然用户最终是可以通过相同的Reporting Services Web主机访问这些报表,但这些报表是基于不同的体系结构(并且以不同的样式创建)。

需要补充的是,Reporting Services提供预生成报表的功能(如果构成报表基础的查询需要一些时间运行,那么这很有用),同样,Reporting Services也提供通过电子邮件分发报表的功能。报表的输出格式可以是PDF、Excel或Word。

14.2.1  管理Reporting Services的工具

Reporting Services提供了多种工具帮助创建、使用及管理报表。它们包括:

Reporting Services配置管理器:在SQL Server主文件夹下的"Configuration Tools"子文件夹中可以找到该工具。使用这一工具可以对下列内容进行配置,如Reporting Services的运行帐户、支持的Web服务器所响应的IP地址和端口、用于Reporting Services的虚拟目录名、使用的电子邮件帐户、跟踪Reporting Services信息的数据库,以及加密密钥和可伸缩性配置信息。

Business Intelligence Development Studio(BIDS):这实质上就是安装了一套针对Reporting Services、Analytics Integration Services和Data Mining的模板的Visual Studio。如果已经安装了Visual Studio 2008,那么BIDS也只是添加了一些模板和访问Visual Studio的快捷方式而已。本书将在后面的多个章节中广泛使用Development Studio(有时它是以SQL Server的基本安装形式存在,有时又作为Visual Studio完整安装的一部分)。

SQL Server Management Studio:在Management Studio中,可以连接到所有和SQL Server相关的服务,以此来管理某个特定的服务。尽管Management Studio中只打包了我认为是功能完全的基本数据引擎,但它仍是执行安全性需求最高的任务和进行作业调度的场所。

Report Server Web站点:在这里实际运行将在Reporting Services中执行的大多数报表,但却是通过"站点设置"链接来进行的(位于浏览器的右上方)。这里也可以管理一些服务器的要素(例如缓存、角色分配以及计划)。

遗憾的是,还没有单个的工具可以囊括Reporting Services中的所有内容。事实上,上述工具距离这一目标都还相差甚远(就像Management Studio之于数据库引擎)。但是,通过组合使用各项工具,可以管理Reporting Services的方方面面。

14.2.2  访问Reporting Services的其他方法

Reporting Services同样也支持一个相当健壮的Web服务模型。通过提供一套库来支持.NET项目访问Reporting Services Web Services API。本章末尾将对其基本内容作一个介绍。

14.3  报表服务器项目

报表模型(在入门篇中是作为Reporting Services的主要内容)仅算是触及到一些皮毛。Reporting Services的灵活性远远不止于此(事实上,有很多专门关于Reporting Services的书籍;其内容相当丰富)。除了报表模型之外,Business Intelligence Development Studio也允许创建报表服务器项目。

前文提到,关于这一主题可以写一整本书,所以这里将采取的方法是通过一个简单的示例开始试着了解。然后再稍微做一点扩展。

提示:

在此次发行版本中,报表服务项目的观感都发生了很大变化。Microsoft购买了Dundas(一家组件开发公司)大量Reporting Services组件的许可。Reporting Services的组件有了重大升级。

在了解报表服务器项目的过程中,将从对报表模型器和报表服务器项目而言都比较常见的几处关键内容开始。如果你已经熟悉了数据源和数据源视图,那么可以浏览下面的两节,选取与项目示例相关的内容即可,或者也可以直接跳至关于实际报表布局的那一节。

让我们从一个报表服务器项目开始。首先打开Business Intelligence Development Studio,打开一个新项目。通过Business Intelligence Development Studio中的"报表服务器项目"模板使用商业智能,如图14-1所示。

 
(点击查看大图)图 14-1

注意:

请注意这一对话框的确切外观将因Visual Studio安装与否以及具体安装的语言和模板而有所不同。该图是Visual Studio的一个完整版本,为的是满足本书中更高级内容的需求。

这一项目将作为本章中大多数操作要进行的对象。在该项目创建之后,便可以深入到报表的一些关键概念。对于已经阅读过初级内容的人而言,其中的某些概念可以说是一次回顾,但是你也一定想将这首份报表的内容整合起来,使其对随后出现的更为健壮的示例而言也是可用的。

14.3.1  数据源

数据源和数据源视图(这将在后文提到)可能是Reporting Services中最为重要的内容了。无论建立的报表是何种类型,也无论报表是使用报表模型器还是报表项目,这两项内容都以某种方式发挥着作用。虽然它们的名称相似,但是在将数据安排进入报表的体系结构中,它们各自服务的层次略有不同。

数据源从本质上讲就是对到从中获取数据的位置的连接的定义。它可以是与一个SQL Server数据源的连接,也可以是与任意OLE DB或ODBC数据源的连接。如果稍稍思考一下这种可能性,那么很快就能得出结论,那就是,虽然Reporting Services与SOL Server相关联,但是却可以在报表中使用广泛的非SOL Server数据源。这确实是一个非常强大的概念。

数据源有两种类型:

嵌入式:这种类型的数据源储存在定义报表的同一文件内。在本章后面的内容中将会介绍到XML(称作报表定义语言或RDL,Report Definition Language),只需说明所有有关数据源的信息都储存在报表定义文件下的XML块中就足够了。对这种数据源定义的访问受限于其所嵌入的报表。

共享式:这种类型的数据源和嵌入式大体相同,区别在于这种数据源的定义存储在其自身文件中(扩展名通常为.ds)。

本章将在后面的内容中使用到共享式数据源。

无论是何种类型,数据源都存储了多条必须的信息,并且有选择地存储了附加选项,以应对可能出现的安全问题。

1. 创建一个数据源

接下来要创建一个数据源,并在本章其后的内容中一直使用它。

如果你的Visual Studio仍是默认设置,那么可以看一下右上方的"解决方案资源管理器"。右击"共享数据源",选择"添加新数据源",如图14-2所示。

然后进入"共享数据源属性"对话框(如图14-3所示)。

 
图14-2
 
(点击查看大图)图14-3

这个对话框有两个主要部分,第一部分需要定义名称(本例中将其命名为将要连接的数据库名)和数据源的连接字符串(对不熟悉连接字符串的人而言,它的作用是为所有连接到数据源的对象指出路径和登录方法)。对连接字符串可以直接编辑,也可以单击"编辑"按钮,弹出如图14-4所示的"连接属性"对话框。

提示:

当我第一次看到这个对话框时,我微微有些吃惊,因为它与我们在Management Studio中多次使用的连接对话框是不同的;但是,它包含了相同的基本要素,只是在视觉上略有不同(简而言之,不用为了外观不同而担心)。

在本例中,选择了本地服务器、系统管理员帐户(sa)以及我们非常熟悉的AdventureWorks2008数据库。

继续单击"确定",然后单击"共享数据源属性"对话框中的"凭据"选项,得到数据源安全选项(见图14-5)。

 
(点击查看大图)图14-4
 
(点击查看大图)图14-5

这里有一些选项颇为值得研究--它们包括:

使用Windows身份验证:顾名思义,这一选项是基于执行报表的用户来进行身份验证。这意味着相关的Windows用户帐户必须不仅能访问报表,而且有权访问和报表相关的所有底层数据。

使用此用户名和密码:引用的用户名和密码为SQL Server登录信息(而不是Windows的)。

凭据提示:与上面一样,这是可预知的。凭据是在运行时从用户处获得的。提供的凭据将传递给报表所使用的任何数据提供程序。

无凭据:该选项强制匿名访问,因此数据提供程序应支持这类访问,否则在运行报表时会出现身份验证错误。

在图14-5中,我们选择了sa,并提供了相关密码。这意味着提供的登录名和密码将与数据源一起被永久保存(以加密形式)在ds文件中。

在该对话框中单击"确定"后,回到较普通的Visual Studio项目,但此时已有了新数据源,开始准备为报表创建更多必须的内容。

14.3.2  使用报表向导

虽然在创建项目时,没有选择报表向导项目类型,但是报表向导中的各部分对报表的创建而言也是可用的。事实上,默认请求一个新报表的简单方式就是进入报表向导。除非你取消了所有向导创建了一张空白报表,否则,Visual Studio也会尝试使用该向导来进行一些操作。

继续看已经建立的示例,这里添加了一个报表以完成报表向导的过程演示。在本例中,假设经理需要一份摘要报表,要求显示David Campbell在2003年7月完成的所有销售订单的销售总量(按类别分类)。并且经理已事先提醒过她可能晚些时候还要查看其他销售人员不同时期业绩的报表,但是现在她只需要Campbell先生在2003年7月的相关信息。

首先右击"解决方案资源管理器"中的"报表"节点,选择"添加新报表",如图14-6所示,进入"报表向导"对话框。

单击"下一步"进入"选择数据源"对话框,如图14-7所示。请注意,虽然这里选择使用的是刚才创建的共享数据源,但也可以在这个对话框中创建一个新数据源(新数据源可以是嵌入式的,但是经过选择之后,也可以在后面转换为共享式)。

 

 
图14-6
 
(点击查看大图)图14-7
再次单击"下一步"进入"查询生成器"对话框,如图14-8所示。这里已经创建了一个查询,语句如下:
 
(点击查看大图)图14-8

  1. SELECT per.FirstName + ' ' + per.LastName AS Employee,  
  2. ps.Name AS Subcategory,  
  3. SUM(sod.LineTotal) AS Sales,  
  4. soh.SalesOrderID,  
  5. soh.SalesOrderNumber,  
  6. p.Name AS Product,  
  7. SUM(sod.OrderQty) AS OrderQty,  
  8. sod.UnitPrice,  
  9. pc.Name AS Category  
  10. FROM Sales.SalesOrderHeader soh  
  11. JOIN Sales.SalesPerson SP  
  12. ON sp.BusinessEntityID = soh.SalesPersonID  
  13. JOIN Sales.SalesOrderDetail sod  
  14. ON soh.SalesOrderID = sod.SalesOrderID  
  15. JOIN HumanResources.Employee e  
  16. ON soh.SalesPersonID = e.BusinessEntityID  
  17. JOIN Person.Person per  
  18. ON per.BusinessEntityID = sp.BusinessEntityID  
  19. JOIN Production.Product p  
  20. ON sod.ProductID = p.ProductID  
  21. JOIN Production.ProductSubcategory ps  
  22. ON p.ProductSubcategoryID = ps.ProductSubcategoryID  
  23. JOIN Production.ProductCategory pc  
  24. ON ps.ProductCategoryID = pc.ProductCategoryID  
  25. WHERE (DATEPART(Year, soh.OrderDate) = 2003)  
  26. AND (DATEPART(Month, soh.OrderDate) = 7)  
  27. AND (soh.SalesPersonID = 283)  
  28. GROUP BY per.FirstName + ' ' + per.LastName,  
  29. DATEPART(Month, soh.OrderDate),  
  30. soh.SalesOrderID,  
  31. soh.SalesOrderNumber,  
  32. p.Name,  
  33. ps.Name,  
  34. sod.UnitPrice,  
  35. pc.Name 

这个查询中并没有什么深奥的内容,它只是把ID号为283的销售员(也就是David Campbell)在2003年7月的总销售额收集起来。本章稍后将演示如何使其变得可选,但是现在采用的简单的、硬编码查询。

粘贴这段查询代码(可在wrox.com或www.professionalsql.com 网站上可获得这一示例代码),单击"下一步",选择报表格式是表格式还是矩阵式。表格式报表采用传统的逐行显示数据的布局。矩阵式报表查找的是数据的交集,主要显示行和列的交集的汇总。具体到本例中的报表,这里选择的是表格式,单击"下一步"进入图14-9所示的对话框。

 
(点击查看大图)图14-9

生成的销售报表将显示出Campbell先生在2003年7月所发出的所有销售订单的总和。现在所做的选择是要让向导创建我们所需要的格式。选择SalesOrderNumber作为"组",选择Category和Sales字段作为"详细信息"项,单击"下一步"。在下一个对话框中(如图14-10所示),我选择了"块"格式,其中并没藏着什么玄机,选择这种格式只是因为我认为它与具体数据最为相配。我还勾选了"包括小计"复选框。因为我们是按SalesOrderNumber进行分组的,所以将会得到一个所有SalesOrderNumber值的总和。

再次单击"下一步",选择一种向导样式,用它来配置报表。这里选择"海洋"样式,不过所有样式都能正常工作。最后一次单击"下一步",得到一个报表摘要,如图14-11所示,内容包括向导的任务以及为报表名称(我选择了SalesOrderSummary,建议你也使用这一名称,因为在本章的学习过程中,将对报表作出改动)。然后就可以单击"完成",生成实际报表。

 
(点击查看大图)图14-10

 
(点击查看大图)图14-11

第一次出现的报表(如图14-12所示)看上去并不复杂。

接下来,选择"预览"选项卡,预览包含真实数据的报表外观(如图14-13所示)。

 
(点击查看大图)图14-12

 
(点击查看大图)图14-13

这是一个好的开始,但还有一些重大的缺陷,所以接下来要学习对报表进行编辑。

要编辑报表,需先回到Visual Studio报表中的"设计"选项卡。继续使用已有的示例,为了使报表看上去清爽整洁,需要注意以下几个问题:

标题格式尽量恰当得体。

数字值尽量接近货币值。

我们要查看每个销售类别的信息,而不是总和。

下面将逐条讨论这些问题。

首先,要更改标题。这是最简单的一项改动,只要在标题区域内单击一次选中标题,然后再单击一次激活光标,就可以像对其他选项卡对象一样对标题进行编辑。直接双击也是可以的。按此操作将标题改为D.Campbell, July 2003 Summary。

接下来,要处理数字格式的问题。这个问题也不复杂。只要右击存储Sales信息的字段,选择"文本框属性"即可,如图14-14所示。

打开如图14-15所示的对话框,该对话框允许对报表表格的单元格(tablix)进行多种属性设置。在图14-15中,我选择了"数字"节点,将数字显示设置为舍入至最接近的整数货币值,并使用千分符。

 
图14-14
 
(点击查看大图)图14-15

提示:

这项操作并没有询问使用何种符号作为千分符,也没有将它假设为逗号。千分符的使用将随报表服务器的区域配置不同而不同,可针对每一份报表进行覆盖。

接下来要进入最后也是最难的一项改变:将每个销售订单的所有类别进行汇总。首先右击含有[Sales]值的单元格,如图14-16所示。选择"行组",使用图14-17所示的对话框修改其属性。这限制了在更大的SalesOrderNumber组中,每一类别只返回一行(注意tablix最左边的括号,回忆一下,我们曾在报表向导中选择添加它)。到这里工作还没有完成。我们一直把重点放在类别上,但是还应该对类别进行排序使其更具有可读性。要实现这一点,可以在当前对话框中选择"排序"节点,如图14-18所示。

当以上操作都完成后,可以再次预览报表,发现虽然许多问题都有了显著改善,但还是存在几个问题(如图14-19所示)。

虽然报表逐渐开始变得"美观",但在数字方面仍有一些问题。如果将数字与先前返回的值(回到图14-13)比较一下,很快可以发现数字没有进行相加。没错,报表不会显示出每一类的总和,而是对每一类别返回第一行。这样是不行的。

 
(点击查看大图)图14-16
 
(点击查看大图)图14-17
 
图14-18
 
(点击查看大图)图14-19
为解决这个问题,需要显式指出对每个单元格所要进行的操作是什么。再次右击[Sales]单元格,这一次要单击"表达式",如图14-20所示。
 
(点击查看大图)图14-20
返回的对话框显示当前正在返回数据集中Sales字段的确切值:

  1. =Fields!Sales.Value 

但是我们需要的是组中该字段的一个总数--或总和。要实现这一点,可使用Reporting Services的一个内置函数。在本例中,使用Sum函数:

  1. =Sum(Fields!Sales.Value) 

要看到它在对话框中的样子,参见图14-21。

单击"确定",再次预览报表,现在得到了一份格式基本良好的报表(不要在格式上过度要求--目前只是刚刚开始报表的学习),如图14-22所示,并且已经可以准备运行,打印输出(或输出为另一格式)并送达经理处。

 
(点击查看大图)图14-21
 
(点击查看大图)图14-22

14.3.4  参数化报表

关于David Campbell的这份报表做得很好,但是有很大局限性。回想之前,经理曾经提醒过她将会在晚些时候查看其他销售人员在其他时间内的相关信息。这便要求报表实现这一功能。

对于大多数报表项目来说,参数化都是至关重要的一个部分。所幸让SQL Server对参数化的报表进行识别还相对容易些。一旦报表被参数化,SQL Server就会以某种方式提示用户提供一个参数值。本节将介绍许多使用户进行参数选择变得更为简单的选项。

第一步,要将最基本的参数化添加至报表中。要使报表依赖于参数,首先要将查询语句改为需要参数。然后只需通知报表在执行之前请求获取参数。下面先来编辑查询。进入项目中"视图"菜单下的"报表数据"项(在"解决方案资源管理器"面板中显示为一个选项卡形式)。"报表数据"选项卡如图14-23所示。双击报表中的数据集,弹出如图14-24所示的对话框,该对话框允许对查询进行编辑(有些报表有多个数据集。这里的报表只有一个)。

 
图14-23
 
(点击查看大图)图14-24

提示:

也可以右击数据集,选择"查询",在一个单独的查询编辑器窗口中编辑查询。

这里已经将Darren Campbell的BusinessEntityID、7月和2003年这些硬编码值改为参数值(分别为@BusinessEntityID、@Month和@Year)。完成之后,可以进入显示参数选项的对话框,如图14-25所示。

由于已在该对话框中添加了每一个参数,所以这里可以直接单击"确定",准备预览(或直接运行)报表。在图14-26中,通过"预览"选项卡运行了报表。请注意在面板顶部它是如何要求提供(这里已经提供)这三个参数的。

在浏览报表的过程中,可以发现虽然它是以和原始报表中完全一样的值而告终,但是现在却能够针对某一时间段或某一销售代表来运行报表。报表开始逐渐更趋灵活。

 
(点击查看大图)图14-25
 
(点击查看大图)图14-26

14.3.5  提供参数值并控制其使用(1)

目前生成的报表看起来相当不错。现在不能再像之前那样仅提供一份关于David Campbell的报表了,而是能在报表中输入不同参数,包括不同雇员的BusinessEntityID和完全不同的时间段。但是,在报表的使用方面,仍然还有一些问题,其中包括:

输入值的格式为任意形式,意味着用户可能输入非法值。

对于何种输入值为合适的这一问题没有任何提示,用户要么知道,要么凭借猜测。这对于日期和年份来说不是什么太大问题,但是对于获得正确的销售人员的BusinessEntityID来说就会造成困难。

无论输入哪一位销售人员,报表头都被硬编码为David Campbell。月份和年份也存在类似的问题。

下面看一下如何解决这些问题。

1. 创建预设的参数表

Reporting Services拥有为参数创建预定义值列表的能力。该功能运用已定义的参数,并对其添加附加属性。

要将固定列表添加至@Month和@Year参数中,需导航至"报表数据"选项卡下的"参数"节点,展开列表,双击需要赋值的参数(也可以右击参数,选择"参数属性")。对@Month参数进行上述操作,弹出如图14-27所示的对话框。

注意这里可以为参数设置一个自定义的提示(不一定为参数名)。还可以控制参数的初始可见性(有可能某一参数只有当另一参数设为一个特定值时才为有效)以及是否允许可空值或空白值。

这里保留了大部分的默认设置,但是将数据类型改成了整型(记住,我们将月份的数字作为了一项参数)。下面就可以进入如图14-28所示的显示"可用值"节点的对话框。

 
(点击查看大图)图14-27
 
(点击查看大图)图14-28

在这个对话框中,我作了许多修改--最明显的是提供了单独的标签和值。标签为用户显示出可供选择的项,值则是指报表在执行时将要传递给参数的内容。通过选择"指定值"单选按钮,可以创建这一列表。但是请注意,这一列表也可以是查询驱动的(稍后将作介绍)。

继续转到"默认值"节点,可以发现这里允许提供一个默认值(在图14-29中,选择的值是一直在使用的7)。

最后,切换到"高级"节点(如图14-30所示),如果用户改变参数值,这里给出了报表数据将选择在何时作出相应改变的选项。我们可以强制始终刷新,可以要求用户明确提出刷新,也可以让SQL Server来决定恰当的刷新时机。

 
(点击查看大图)图14-29
 
(点击查看大图)图14-30

接下来你可以自己尝试一下将参数@Year的数据类型设置为整数型,默认值为2003。然后就可以再次预览或运行报表,查看所做改动的效果,如图14-31所示。

虽然在BusinessEntityID和Year这两个参数中没有发现显著的不同,但可以很快注意到现在的Month已变成一张下拉列表,即使月份的参数实际使用的是整数值,该列表也可以为每个月份提供名称。还可以测试一下在year字段中输入文本。SQL Server会相对得体地指出类型不匹配的问题(虽然并不是以一种最完美的方式,但总比爆满屏幕的错误要好得多)。

 
(点击查看大图)图14-31

14.3.5  提供参数值并控制其使用(2)

2. 通过查询创建参数表

为参数@BusinessEntityID提供一个预先填充的列表要比其他两个参数难一些。虽然可以像@Month一样创建一个固定列表,但那意味着只要销售人员的列表发生变动,就必须随时编辑报表。月份比较稳定,但是销售人员的变动频率却很高。每时每刻地编辑报表是不现实的,尤其是当销售人员的信息已被输入到系统的其他地方时。

要启动上述任务,首先需要创建一个新的数据集。首先右击"报表数据"选项卡中的数据源,选择"添加数据集",如图14-32所示。

弹出如图14-33所示的对话框。

 
图14-32
 
(点击查看大图)图14-33
这里已经给出了一个列出所有销售人员的查询。它在对话框中是完全可见的,为使它更清楚,整理成如下所示:
  1. SELECT p.BusinessEntityID, p.LastName + ', ' + p.FirstName  
  2. FROM Person.Person p  
  3. JOIN Sales.SalesPerson sp  
  4. ON p.BusinessEntityID = sp.BusinessEntityID; 

继续进入"字段"节点,如图14-34所示。该对话框允许在使用该数据集的所有报表中选择返回字段的名称(以便进行访问)。这里选择默认名称,即使已经选择,也可以在结果中改变名称。单击"确定",数据集便创建成功。现在可以使用它对参数列表进行布局。

 
(点击查看大图)图14-34
再次双击参数BusinessEntityID,将其打开以备编辑,然后转到"可用值"节点,如图14-35所示。这里又一次预先填入了合适的值。如你所想,这里选择了"从查询中获取值"选项。同样还选择了使用什么数据集作为数据源以及哪些数据集的字段与值和标签字段相关(值和标签字段的功能将在手动为其赋值时体现出来)。在预览或执行报表之前(如图14-36所示),还要进入"默认节点"节点,设置一个默认值283(即David Campbell)。
 
(点击查看大图)图14-35
 
(点击查看大图)图14-36

这样一来,参数默认值和数据类型便被迅速设置恰当。剩下来要做的就是处理固定表头的问题。

3. 通过参数获取表头和其他字段

通过编辑文本框来使用参数值相对简单。首先选中拥有现有固定值的文本框,进入编辑模式。要使其变为动态的,需要结合多个项。首先,要为动态值提供一个前缀,这里使用"Summary for:"。然后再次右击,选择"创建占位符",进入如图14-37所示的对话框。占位符使得Reporting Services可以对文字文本和功能代码进行区分。注意,"值"字段有一个下拉框,将其展开可以在大量的动态值间进行选择。本例中为用户选择的某一个参数提供了一个参考值。继续并单击"确定",可预览或运行报表查看效果(如图14-38所示)。

 
(点击查看大图)图14-37
 
(点击查看大图)图14-38
要完成这一小节的内容,还需再添加一两个占位符,但这一次,使用的是表达式编辑器。在刚刚创建的占位符后面添加一个逗号和一个空格,然后右击再次选择"添加占位符"。但是这一次,单击"值"字段右边的Fx按钮,进入如图14-39所示的对话框。在这幅图中,我正在为用户运行报表时所选择的Month参数添加一个参考值,但请注意在编辑时,Visual Studio提供了IntelliSense。继续为Month和Year都添加占位符,报表外观将如图14-40所示。
 
(点击查看大图)图14-39
 
(点击查看大图)图14-40

14.3.6  添加图表

Reporting Services还支持图表对象。图表是一种功能较为强大的事物,因为它在很大程度上使得报表不仅仅是一份报告来源,而且还能够进行更真实的分析。下面要为报表添加一张图表,为本月各类产品的销售情况提供一个可视化表示形式。

首先打开Visual Studio的工具箱,将Chart对象拖入报表中(这里将它放在tablix的右边)。这将进入如图14-41所示的对话框,并允许在大量的图表类型中进行选择。

考虑到我们并没有太多类别可供选择,因此决定使用3D形式的饼型图表(如图14-41所示)。可将"报表数据"选项卡中的数据集内的字段直接拖入图表中的特殊接收区域(如图14-42所示)。我将Sales字段由Dataset1拖至"将数据字段拖至此处"区域,又将Categories字段拖入"将类别字段拖至此处"区域。

 
(点击查看大图)图14-41
 
(点击查看大图)图14-42
另外在图表属性中将标题区域改为Sales by Category,然后便可以再次运行或预览报表,如图14-43所示。
 
(点击查看大图)图14-43

这样,我们便迅速拥有了一张提供tablix数字的可视化表示的基本图表。

提示:

两个对象间不存在相互关联。它们只是碰巧使用了相同的数据集,而并不是被要求这样做的。事实上,在报表建立的大部分过程中,都没有使用图表,如果愿意,也可以删除tablix,而只保留图表。

 


14.3.7  链接报表

Reporting Services允许对多个报表进行链接,既可以向下钻取到更深层的细节,也可以钻取到完全不同的报表中。

链接过程由一系列"操作"支持。操作支持内部的(其他报表)和外部的(如一个网站)链接。

下面要为本章中所使用的报表添加最后一个要素。要利用这个链接,需要下载(你可能还没有下载)本书的代码,找到预先创建的SalesOrderDetail.rdl文件。可以通过右击"解决方案资源管理器"中的"报表",选择"添加">"现有项",将该文件添加到项目当中。

要使用这一新的Sales Order Detail报表,需要对报表中含有Sales Order Number的文本框属性进行编辑,然后访问"操作"设置,如图14-44所示。

一旦将SalesOrderDetail.rdl文件适当地添加到了项目中,并对图14-44所示的Sales OrderNumber操作进行了设置之后,就可以最后一次运行或预览摘要报表了。现在单击David Campbell在2003年7月的第一个Sales Order Number,就可以得到如图14-45所示的Sales Order Detail报表。

 
(点击查看大图)图14-44
 
(点击查看大图)图14-45

剩下来要做的事就是对报表进行部署。在"解决方案资源管理器"中右击报表,选择"部署"。但是这里还有个小问题要注意--需要在项目定义中对部署的目标进行定义。

(1) 右击报表服务器项目,选择"属性"。

(2) 在TargetReportFolder字段中,设置登录到报表管理器时想驻留报表的文件夹。

(3) 在TargetServerURL字段中,输入报表服务器的URL。在本例中,该URL很简单,为http://localhost/ReportServer,但服务器名可以是有权限对其进行部署的任一服务器(如果在安装时作了定义,那除Report Server外,还可用Virtual Directory)。

部署完成之后(通过右击项目选择"部署"),便可以查看报表。导航到报表服务器(如果是在本地主机上并使用默认目录,则地址为http://localhost/Reports)。单击报表文件夹,选择SalesOrderSummary报表。

首次加载报表可能需要一些时间,你所见到的报表和我们在项目中所定义的一样(如果回头再次导航一下,报表定义将被缓存,加载速度就会变得相当之快)。

14.4  有关RDL的简注

RDL全称为Report Definition Language--是一种基于XML的报表定义语言。在本章中我们对报表所做的所有改动都经由Visual Studio转换成了RDL。如果想查看报表项目的RDL,可右击报表选择"查看代码"。下面是我为本章所创建的一个示例报表的一段摘录。它定义了为销售人员的参数提供值的数据集。

  1. <DataSet Name="SalesStaff"> 
  2. <Fields> 
  3. <Field Name="BusinessEntityID"> 
  4. <DataField>BusinessEntityID</DataField> 
  5. <rd:TypeName>System.Int32</rd:TypeName> 
  6. </Field> 
  7. <Field Name="Name"> 
  8. <DataField>Name</DataField> 
  9. <rd:TypeName>System.String</rd:TypeName> 
  10. </Field> 
  11. </Fields> 
  12. <Query> 
  13. <DataSourceName>AdventureWorks2008</DataSourceName> 
  14. <CommandText>SELECT p.BusinessEntityID, 
    p.LastName + ', ' + p.FirstName AS Name  
  15. FROM Person.Person p  
  16. JOIN Sales.SalesPerson sp  
  17. ON p.BusinessEntityID = sp.BusinessEntityID;</CommandText> 
  18. <rd:UseGenericDesigner>true</rd:UseGenericDesigner> 
  19. </Query> 
  20. </DataSet> 

可以直接修改RDL (但是要小心。如果在直接编辑时引入了一个错误,那么要找出到底错在哪里将会十分困难)。

14.5  小结

Reporting Services对许多SQL Server的安装而言都有重要影响。对许多公司而言,在中央数据仓库中内置一个相对强大的报表服务器是一种解放,使得向数据使用者散布信息变得更为简单。对另一些组织而言,Reporting Services提供的解决方案足以替代长期以来所使用的报表包,如Crystal Reports。SQL Server 2008添加了一些新的功能和控件,使得报表更为精致和强大,引擎也经过了重新设计,可伸缩性更高。

尽管本章中所使用的报表较为可靠,但也只是我们初尝到的一点甜头。报表可以被参数化,可以嵌入图表,可以与其他产品整合(如Microsoft Sharepoint Services或Microsoft Office Sharepoint Services)、可以从一个报表钻取到另一个报表,甚至可以在报表中再嵌入其他报表。

要了解报表的更多内容,建议阅读有关Reporting Services的专门书籍。