SSRS 系列第二部分:使用子报表、钻取报表、表达式和自定义代码、数据条、指示器、自定义排序和分页等






4.95/5 (90投票s)
在本文中,我们将学习创建子报表、钻取报表、自定义代码和表达式、Web 服务和 WCF 服务从 SSRS 的消费、自定义分页和排序、使用实时示例处理数据条和指示器。
- 下载子报表 - 21.41 KB
- 下载钻取报表示例 - 11.94 KB
- 下载表达式处理 - 15.34 KB
- 下载计算字段 - 15.86 KB
- 下载排序 - 13.44 KB
- 下载自定义分页 - 14.34 KB
- 下载 SSRS_WCF_示例 - 48.01 KB
- 下载 SSRS_WebService_示例 - 16.55 KB
- 下载数据条指示器 - 35.07 KB
目录
- 引言
- 背景
- 数据源
- 在 SSRS 中创建子报表 (下载 Subreport.zip 文件)
- 在 SSRS 中创建钻取报表 (下载 DrilDownReport_Example.zip 文件)
- 使用表达式和自定义代码 (下载 WorkingWithExpression.zip 文件)
- 使用计算字段 (下载 CalculatedFields.zip 文件)
- 列排序 (下载 Sorting.zip 文件)
- SSRS 报表中的自定义分页 (下载 CustomPaging.zip 文件)
- SSRS 和 WCF 数据源 (下载 SSRS_WCF_Example.zip 文件)
- SSRS 和 Web 服务数据源 (下载 SSRS_WebService_Example.zip 文件)
- 使用数据条 (下载 DataBars&Indicators.zip 文件)
- 根据条件在数据条中显示颜色 (下载 DataBars&Indicators.zip 文件)
- 显示带有数据条的数据标签 (下载 DataBars&Indicators.zip 文件)
- 使用指示器 (下载 DataBars&Indicators.zip 文件)
- 结论
引言
在过去的几个月里,我一直在从事 SSRS 的工作并积累了一些知识,我想在这里分享,特别是对于那些即将从循序渐进的方法开始学习 SSRS 的人,以及那些已经生成了一些基本的 SSRS 报表但没有太多接触并想学更多的人。我们已经从这里开始了报表生成的基本旅程。在本系列中,我们将探讨报表服务的更多有趣内容。这将是第 N 系列文章,因此在每一部分中我都会讨论一些新功能。请注意,我正在为此文章使用 Sql Server Denali CTP 1。
背景
SSRS 已成为事实上的报表工具,熟悉它已成为必需品而非奢侈品。我发现许多对 BI 领域感兴趣的人,但由于各种原因(可能是他们在工作领域没有机会接触,没有时间投入到该主题,项目频繁变动等)而没有机会与之合作。因此,我想写这一系列文章(SSRS/SSIS/SSAS),其中我主要谈论我在实际项目中接触过的一些功能。我将尝试以循序渐进的实践方法来编写这一系列文章,以便人们可以从中学习/回顾。毕竟,一张图片胜过千言万语。
数据源
为了进行此实验,我们将使用以下脚本生成并填充名为 (tbl_Players) 的 Players 表。
-- Drop the table if it exists IF EXISTS (SELECT * FROM sys.objects WHERE name = N'tbl_Players' AND type = 'U') DROP TABLE tbl_Players GO SET ANSI_NULLS ON GO --Create the table CREATE TABLE tbl_Players ( PlayerID INT IDENTITY, PlayerName VARCHAR(15), BelongsTo VARCHAR(15), MatchPlayed INT, RunsMade INT, WicketsTaken INT, FeePerMatch NUMERIC(16,2) ) --Insert the records INSERT INTO tbl_Players(PlayerName, BelongsTo, MatchPlayed,RunsMade,WicketsTaken,FeePerMatch) VALUES('A. Won','India',10,440,10, 1000000) INSERT INTO tbl_Players(PlayerName, BelongsTo, MatchPlayed,RunsMade,WicketsTaken,FeePerMatch) VALUES('A. Cricket','India',10,50,17, 400000) INSERT INTO tbl_Players(PlayerName, BelongsTo, MatchPlayed,RunsMade,WicketsTaken,FeePerMatch) VALUES('B. Dhanman','India',10,650,0,3600000) INSERT INTO tbl_Players(PlayerName, BelongsTo, MatchPlayed,RunsMade,WicketsTaken,FeePerMatch) VALUES('C. Barsat','India',10,950,0,5000000) INSERT INTO tbl_Players(PlayerName, BelongsTo, MatchPlayed,RunsMade,WicketsTaken,FeePerMatch) VALUES('A. Mirza','India',2,3,38, 3600000) INSERT INTO tbl_Players(PlayerName, BelongsTo, MatchPlayed,RunsMade,WicketsTaken,FeePerMatch) VALUES('M. Karol','US',15,44,4, 2000000) INSERT INTO tbl_Players(PlayerName, BelongsTo, MatchPlayed,RunsMade,WicketsTaken,FeePerMatch) VALUES('Z. Hamsa','US',3,580,0, 400) INSERT INTO tbl_Players(PlayerName, BelongsTo, MatchPlayed,RunsMade,WicketsTaken,FeePerMatch) VALUES('K. Loly','US',6,500,12,800000) INSERT INTO tbl_Players(PlayerName, BelongsTo, MatchPlayed,RunsMade,WicketsTaken,FeePerMatch) VALUES('S. Summer','US',87,50,8,1230000) INSERT INTO tbl_Players(PlayerName, BelongsTo, MatchPlayed,RunsMade,WicketsTaken,FeePerMatch) VALUES('J.June','US',12,510,9, 4988000) INSERT INTO tbl_Players(PlayerName, BelongsTo, MatchPlayed,RunsMade,WicketsTaken,FeePerMatch) VALUES('A.Namaki','Australia',1,4,180, 999999) INSERT INTO tbl_Players(PlayerName, BelongsTo, MatchPlayed,RunsMade,WicketsTaken,FeePerMatch) VALUES('Z. Samaki','Australia',2,6,147, 888888) INSERT INTO tbl_Players(PlayerName, BelongsTo, MatchPlayed,RunsMade,WicketsTaken,FeePerMatch) VALUES('MS. Kaki','Australia',40,66,0,1234) INSERT INTO tbl_Players(PlayerName, BelongsTo, MatchPlayed,RunsMade,WicketsTaken,FeePerMatch) VALUES('S. Boon','Australia',170,888,10,890) INSERT INTO tbl_Players(PlayerName, BelongsTo, MatchPlayed,RunsMade,WicketsTaken,FeePerMatch) VALUES('DC. Shane','Australia',28,39,338, 4444499) INSERT INTO tbl_Players(PlayerName, BelongsTo, MatchPlayed,RunsMade,WicketsTaken,FeePerMatch) VALUES('S. Noami','Singapore',165,484,45, 5678) INSERT INTO tbl_Players(PlayerName, BelongsTo, MatchPlayed,RunsMade,WicketsTaken,FeePerMatch) VALUES('Z. Biswas','Singapore',73,51,50, 22222) INSERT INTO tbl_Players(PlayerName, BelongsTo, MatchPlayed,RunsMade,WicketsTaken,FeePerMatch) VALUES('K. Dolly','Singapore',65,59,1,99999) INSERT INTO tbl_Players(PlayerName, BelongsTo, MatchPlayed,RunsMade,WicketsTaken,FeePerMatch) VALUES('S. Winter','Singapore',7,50,8,12) INSERT INTO tbl_Players(PlayerName, BelongsTo, MatchPlayed,RunsMade,WicketsTaken,FeePerMatch) VALUES('J.August','Singapore',9,99,98, 890)
运行简单 Select 查询后的部分输出
Select * from tbl_Players如下所示
我们还将在数据库中创建以下存储过程,其脚本如下
If Exists (Select * from sys.objects where name = 'usp_SelectRecordsByPlayerName' and type = 'P') Drop Procedure usp_SelectRecordsByPlayerName Go -- Create the stored procedure Create Procedure [dbo].[usp_SelectRecordsByPlayerName] ( @PlayerID int ) As Begin Select PlayerID ,PlayerName , BelongsTo , MatchPlayed ,RunsMade ,WicketsTaken ,FeePerMatch From tbl_Players Where PlayerId = @PlayerID End
(A) 在 SSRS 中创建子报表
报表中的报表是子报表。也就是说,将有两个报表,一个是主报表,另一个是子报表,主报表会调用子报表。子报表或子报表可以接受主报表的参数并执行其工作。此外,它可以独立执行。让我们开始行动。
步骤 1:我们将有两个报表。两个报表遵循相同的步骤,只有在主报表的情况下,我们将执行以下查询。
SELECT [PlayerID] ,[PlayerName] ,[BelongsTo] FROM [SSRSExperiment].[dbo].[tbl_Players]
对于子报表,我们将执行以下查询。
SELECT [PlayerName] ,[MatchPlayed] ,[RunsMade] ,[WicketsTaken] ,[FeePerMatch] FROM [SSRSExperiment].[dbo].[tbl_Players] WHERE [BelongsTo]= @CountryName
请注意,我们正在传递 @CountryName 参数。因此,在运行时,根据传递的参数值,子报表将被生成。一旦报表创建完毕,我们将在我们的项目中拥有两个报表,如下所示。
单独测试 PlayerSubReport 会产生以下结果。
步骤 2:在主/主报表中添加 SubReport 控件。
步骤 3:右键单击子报表 -> 子报表属性。
步骤 4:在“子报表属性”窗口的“常规”部分,从下拉列表中选择子报表名称(此处为 PlayerSubReport),如下所示。
在“参数”选项卡中,单击“添加”按钮后,让我们输入参数名称为 **“CountryName”**,值为 **“ =First(Fields!BelongsTo.Value, "DataSet1")”**。完成后,单击“确定”按钮。
步骤 5:就是这样。现在让我们运行报表。
因此,我们的子报表已生成。
(B) 在 SSRS 中创建钻取报表
在 SSRS 中创建钻取/树状视图报表非常简单。让我们看以下步骤。
步骤 1:打开 BIDS 并创建一个新的共享数据源。
步骤 2:创建一个表类型报表,如下所示(执行此操作的步骤已在第一部分系列中描述)。
步骤 3:接下来为 **Belongss To** 字段添加 **父组**,如下所示。
步骤 4:在 **Tablix 组**窗口中,让我们从“按分组”下拉列表中选择 **[BelongsTo]**,然后 *选中“添加组标题”复选框*,然后单击“确定”。
此时,如果我们在设计视图中查看报表,它看起来如下。
运行报表时,预览选项卡中的显示如下。
步骤 5:从“行组”中,选择 **[Belongs To] 详细信息**,然后选择 **组属性**。
步骤 6:在打开的“组属性”窗口中,选择“可见性”选项卡。然后选择 **隐藏单选按钮** 并选中 **此报表项可以切换显示** 复选框。然后从将启用的下拉列表中,选择组的名称(此处为 BelongsTo1),然后单击“确定”。
步骤 7:删除 [Belongs To] 详细信息列。
步骤 8:现在一切都完成了。运行应用程序,结果如下。
(C) 使用表达式和自定义代码
在本节中,我们将通过一些示例了解如何在报表中使用的表达式和自定义代码。
目标
我们将要做的是,如果一名球员得分超过 500 分且获得了超过 10 个三振,那么我们将以绿色显示该行和特定列。
为此,让我们首先单击报表设计主体并选择报表属性。
“报表属性”窗口将打开,如下所示。
导航到 **代码选项卡** 以编写以下自定义代码。
Public Shared Function SetColor(ByVal RunsMade As Integer,ByVal WicketsTaken As Integer) As String SetColor= "Transparent" If RunsMade >= 500 AND WicketsTaken >= 10 Then SetColor= "Green" End IF End Function
代码非常简单易懂。我们声明了一个名为 SetColor 的函数,该函数接受两个整数变量,第一个用于得分,第二个用于获得的三振数。我们将 Setcolor 的初始值设置为“Transparent”。现在,如果条件满足,我们将 SetColor 设置为“Green”。
接下来,让我们选择 RunsMade 列并右键单击以打开 TextBox 菜单,从中我们将选择 TextBox 属性。
在出现的“TextBox 属性”窗口中,单击“填充”选项,然后单击 fx 按钮。
在表达式窗口中输入以下表达式。
=Code.SetColor(Fields!RunsMade.Value,Fields!WicketsTaken.Value)
参数传递的代码片段也很简单。在第一个中,我们传递 RunsMade 值,而在第二个中,我们将 WicketsTaken 值传递给刚刚创建的 SetColor 函数。
单击“确定”按钮,然后对 Wickets Taken 列重复相同的操作。完成后,让我们运行应用程序,结果如下。
让我们为报表添加更多自定义。如果满足上述条件,我们将使 Player Name 值变粗,Belongs To 变斜体。
因此,让我们在自定义代码中添加两个函数,如下所示。
函数:SetBoldFontWeight
' Function to set the font weight as bold Public Shared Function SetBoldFontWeight(ByVal RunsMade As Integer,ByVal WicketsTaken As Integer) As String SetBoldFontWeight= "Default" If RunsMade >= 500 AND WicketsTaken >= 10 Then SetBoldFontWeight= "Bold" End IF End Function
函数:SetItalicFontWeight
'Function to set the font weight as italic Public Shared Function SetItalicFontWeight(ByVal RunsMade As Integer,ByVal WicketsTaken As Integer) As String SetItalicFontWeight= "Default" If RunsMade >= 500 AND WicketsTaken >= 10 Then SetItalicFontWeight= "Italic" End IF End Function
自定义代码区域现在将如下所示。
接下来,在 **PlayerName 列**中右键单击以显示 TextBox 属性,并在“字体”选项中,为粗体选择 fn。
在表达式编辑器中输入以下代码。
=Code.SetBoldFontWeight(Fields!RunsMade.Value,Fields!WicketsTaken.Value)
在 **Belongs To 列**中右键单击以显示 TextBox 属性,并在“字体”选项中,为斜体选择 fn。
在表达式编辑器中输入以下代码。
=Code.SetItalicFontWeight(Fields!RunsMade.Value,Fields!WicketsTaken.Value).
我们完成了。运行报表,结果如下。
我们将考虑另一种情况,即根据 **Player ID 列**生成交替的行颜色。
为此,请将以下函数添加到自定义代码窗口。
Public Shared Function SetAlternateRowColor(ByVal PlayerID As Integer) As String SetAlternateRowColor= "Yellow" If PlayerID Mod 2 = 0 Then SetAlternateRowColor= "Green" End IF End Function
在此代码中,我们为偶数行设置颜色为绿色。对于所有列,让我们为 BackgroundColor 编写以下表达式。
=Code.SetAlternateRowColor(Fields!PlayerID.Value)
结果如下。
同样,我们可以通过使用表达式和自定义代码来设置对齐方式、根据条件隐藏行等等。
(D) 使用计算字段
计算字段是从另一个字段派生的字段。
目标
假设我们想将每位获得超过 10 个三振并得分超过 500 分的球员的比赛费加倍。在这种情况下,该行将显示为绿色,计算出的列值将显示为粗体。
解决方案
步骤 1:作为第一步,让我们编写自定义代码。
函数: SetColor
目的:如果得分大于或等于 500 且三振数大于或等于 10,此函数会将整行颜色设置为绿色。
'Function to set the color Public Shared Function SetColor(ByVal RunsMade As Integer,ByVal WicketsTaken As Integer) As String SetColor= "Transparent" If RunsMade >= 500 AND WicketsTaken >= 10 Then SetColor= "Green" End IF End Function
函数: SetBoldFontWeight
目的:如果球员得分大于或等于 500 且三振数大于或等于 10,此函数会将计算字段中的行数据设置为粗体。
' Function to set the font weight as bold Public Shared Function SetBoldFontWeight(ByVal RunsMade As Integer,ByVal WicketsTaken As Integer) As String SetBoldFontWeight= "Default" If RunsMade >= 500 AND WicketsTaken >= 10 Then SetBoldFontWeight= "Bold" End IF End Function
函数: DoubleMatchFee
目的:如果球员得分大于或等于 500 且三振数大于或等于 10,则将球员比赛费加倍。
'Function to double the match fee Public Shared Function DoubleMatchFee(ByVal RunsMade As Integer,ByVal WicketsTaken As Integer,ByVal OriginalMatchFee As Integer) As Integer DoubleMatchFee= OriginalMatchFee If RunsMade >= 500 AND WicketsTaken >= 10 Then DoubleMatchFee= OriginalMatchFee * 2 End IF End Function
步骤 2:选择数据集。右键单击并选择添加计算字段。
“数据集属性”窗口将打开。输入计算字段名称,然后单击“表达式”按钮(fx)。
接下来,在表达式窗口中添加以下表达式。
=Code.DoubleMatchFee(Fields!RunsMade.Value,Fields!WicketsTaken.Value,Fields!FeePerMatch.Value)
点击“确定”。
步骤 3:将 DoubleMatchFee 列拖放到报表设计器中。
右键单击 **DoubleMatch Fee 列**,从文本框属性中选择“字体”,然后在粗体字重旁边输入以下表达式。
=Code.SetBoldFontWeight(Fields!RunsMade.Value,Fields!WicketsTaken.Value)
对于所有其他列,让我们在从“文本框属性”获得的“填充”颜色旁边输入以下表达式。
=Code.SetColor(Fields!RunsMade.Value,Fields!WicketsTaken.Value)
我们完成了。让我们运行报表,结果如下。
希望我们现在可以舒适地使用计算字段了。
(E) 列排序
在本节中,我们将探讨如何在报表中执行列排序。列排序是一项重要功能,也可以从数据库端进行。但是,如果相同的数据源被各种其他应用程序使用,并且每个应用程序都要求以不同的顺序显示结果,那么最好仅在客户端应用程序中进行排序,而不是在数据库中。
让我们看一下以下步骤,了解我们如何在报表中执行此操作。
步骤 1:右键单击列标题并选择文本框属性。
步骤 2:在“文本框属性”对话框中选择“交互式排序”,然后
- 选中“为此文本框启用交互式排序”复选框。
- 从“排序依据”下拉列表中选择 Player ID 字段。
我们完成了。让我们对 PlayerName 字段执行相同的操作。现在运行报表。
可以看到,已在两列中启用了排序,并且报表以 Player ID 降序显示。
(F) SSRS 报表中的自定义分页
本节将介绍在报表中生成自定义分页的方法。我们还将学习在此过程中使用全局变量。
步骤 1:在报表设计屏幕上,右键单击,然后从上下文菜单中选择“添加页脚”。
添加页脚后,我们可以向其中添加控件。
步骤 2:让我们从“报表项”工具箱将四个文本框添加到设计器中,如下所示。
步骤 3:选择第二个文本框并单击“表达式”。
步骤 4:在打开的表达式窗口中,让我们编写表达式。
=Globals!PageNumber
同样,对于第四个文本框,让我们编写表达式为 **=Globals!TotalPages.**。
步骤 5:运行报表,结果如下。
(G) SSRS 和 WCF 数据源
在本节中,我们将探讨如何从 SSRS 使用 WCF 服务。
为此,首先让我们创建一个“WCF 服务应用程序”类型的项目。让我们添加一个名为 **Player** 的类,并用 **DataContract** 属性装饰该类。该类的属性被用 **DataMember** 属性装饰。
using System.Runtime.Serialization; namespace WcfServiceApps { [DataContract] public class Player { [DataMember] public int PlayerID { get; set; } [DataMember] public string PlayerName { get; set; } [DataMember] public string BelongsTo { get; set; } [DataMember] public int MatchPlayed { get; set; } [DataMember] public int RunsMade { get; set; } [DataMember] public int WicketsTaken { get; set; } [DataMember] public double FeePerMatch { get; set; } } }
现在,从服务合同接口(此处为 IService1)公开两个操作合同。
- GetAllPlayers() // 获取所有玩家的列表
- GetByPlayerId(int playerID) // 按 PlayerID 获取玩家
using System.Collections.Generic; using System.ServiceModel; namespace WcfServiceApps { [ServiceContract] public interface IService1 { [OperationContract] List<Player> GetAllPlayers(); [OperationContract] List<Player> GetByPlayerId(int playerID); } }
实现接口的类是这里的 Service1 类。实现如下。
using System; using System.Collections.Generic; using System.Linq; namespace WcfServiceApps { public class Service1 : IService1 { public List<Player> GetAllPlayers() { return PlayerDataSource(); } public List<Player> GetByPlayerId(int playerID) { return PlayerDataSource().Where(i=>i.PlayerID == playerID ).ToList(); } #region PlayerData source private List<Player> PlayerDataSource() { List<Player> playerList = new List<Player>(); Random r = new Random(); for (int i = 1; i <= 20; i++) { if (i <= 5) playerList.Add(new Player { PlayerID = i, PlayerName = string.Concat("PlayerName", i), BelongsTo = "India", RunsMade = i * 10, WicketsTaken = i + 5, MatchPlayed = i + 10, FeePerMatch = r.NextDouble() }); if (i > 5 && i <= 10) playerList.Add(new Player { PlayerID = i, PlayerName = string.Concat("PlayerName", i), BelongsTo = "Australia", RunsMade = i * 10, WicketsTaken = i + 5, MatchPlayed = i + 10, FeePerMatch = r.NextDouble() }); if (i > 10 && i <= 15) playerList.Add(new Player { PlayerID = i, PlayerName = string.Concat("PlayerName", i), BelongsTo = "US", RunsMade = i * 10, WicketsTaken = i + 5, MatchPlayed = i + 10, FeePerMatch = r.NextDouble() }); if (i > 15) playerList.Add(new Player { PlayerID = i, PlayerName = string.Concat("PlayerName", i), BelongsTo = "Singapore", RunsMade = i * 10, WicketsTaken = i + 5, MatchPlayed = i + 10, FeePerMatch = r.NextDouble() }); } return playerList; } #endregion } }
代码非常简单易懂。我们最后需要做的一件事是,我们需要将绑定指定为 **BasicHttpBinding**。
<bindings> <basicHttpBinding> <binding name="PlayerBinding" /> </basicHttpBinding> </bindings>
完整的配置文件如下。
<?xml version="1.0" encoding="utf-8"?> <configuration> <system.serviceModel> <bindings> <basicHttpBinding> <binding name="BasicHttpBinding_IService1" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true"> <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" /> <security mode="None"> <transport clientCredentialType="None" proxyCredentialType="None" realm="" /> <message clientCredentialType="UserName" algorithmSuite="Default" /> </security> </binding> </basicHttpBinding> </bindings> <client> <endpoint address="https://:49158/Service1.svc" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IService1" contract="IService1" name="BasicHttpBinding_IService1" /> </client> </system.serviceModel> </configuration>
接下来,让我们打开 BIDS 并创建一个 **报表服务器项目**。在共享数据源中,让我们将 **类型指定为 XML**,并将 **连接字符串指定为“https://:49158/Service1.svc”**。
让我们在查询设计器中编写以下查询。
<Query> <Method Namespace="http://tempuri.org/" Name="GetAllPlayers" /> <SoapAction>http://tempuri.org/IService1/GetAllPlayers</SoapAction> </Query>
单击 **运行图标** 以获得以下结果。
接下来,按照第一部分系列中描述的步骤生成报表,最终结果将是。
注意:如果我们想为 GetByPlayerId(int playerID) 操作合同传递参数,查询将更改为。
<Query> <Method Namespace="http://tempuri.org/" Name="GetByPlayerId"> <Parameters> <Parameter Name="playerID"><DefaultValue>10</DefaultValue></Parameter> </Parameters> </Method> <SoapAction>http://tempuri.org/IService1/GetByPlayerId</SoapAction> </Query>
请注意,查询中的参数名称和方法必须相同。
在此,我们将 PlayerID 参数的值硬编码为 10。但是,我们可以在运行时传递它。为此,请按照以下步骤进行。
步骤 1:转到视图 -> 报表数据。或者按 CTRL + ALT + D。
步骤 2:出现“报表数据”窗口。从那里右键单击 **“参数”文件夹** 以添加参数。
步骤 3:在 **“报表参数属性”窗口**中,输入参数名称(此处为 PlayerID),输入提示(可选),并将数据类型输入为 **整数**。完成后,单击“确定”按钮。
步骤 4:右键单击数据集,然后单击“数据集属性”。
步骤 5:接下来,单击左侧的“参数”选项卡,然后添加 **参数名称** 为 **playerID**,**参数值** 为 **[@PlayerID]**。
就是这样。运行报表。在提示中输入 Player Id,然后单击“查看”按钮以查看结果报表。
(H) SSRS 和 Web 服务数据源
这与上面非常相似。让我们首先创建一个 Asp.net Web 服务项目。然后添加与上一个示例中的数据源相同的 Player Entity。Web 方法如下。
[WebMethod] public List<Player> GetAllPlayers() { return PlayerDataSource(); }
接下来,让我们打开 BIDS 并创建一个 **报表服务器项目**。在共享数据源中,让我们将 **类型指定为 XML**,并将 **连接字符串指定为“https://:49277/WebService/WebService.asmx”**。
让我们在查询设计器中编写以下查询。
<Query> <Method Namespace="http://tempuri.org/" Name="GetAllPlayers"> </Method> <SoapAction>http://tempuri.org/GetAllPlayers</SoapAction> <ElementPath IgnoreNamespaces="true">*</ElementPath> </Query>
接下来,按照第一部分系列中描述的步骤生成报表,我们将获得所需的结果。
注意:要向报表添加参数,请遵循上述相同步骤,因此在本节中忽略。
(I) 使用数据条
数据条用于制作 **“龙卷风图”**,以便了解值的分布情况。
我们也将在此演示中使用相同的数据源 tbl_Players。
目标
在此实验中,我们将使用数据条查看玩家得分的分布情况。
数据条实操
在设计视图中,添加一个包含三列的表。在第一列中,让我们添加 [Player Name] 字段,在最后两列中,让我们添加 [Runs Made] 列。让我们将第三列的标题重命名为 [Runs Analysis]。
从“报表项”工具箱,让我们将一个数据条控件拖放到第三列中。将出现 **“数据条类型属性”** 窗口。从那里,让我们选择 **“堆积条形图”** 数据条类型。
然后单击“确定”。右键单击数据条,然后从上下文菜单中选择 **“图表属性”**。
在“图表属性”窗口的 **“常规”** 部分,从 **“调色板”** 下拉列表中选择 **“灰度”**。
在 **“填充”** 部分,在 **“填充样式”** 中选择 **“渐变”** 并提供一些合适的渐变。
单击“确定”并查看报表。
我们可以反转数据条的方向。右键单击数据条,然后从上下文菜单中选择 **“水平轴属性”**。从属性对话框中,在 **“刻度选项”** 的 **“反转方向”** 复选框中打勾。
报表如下。
(J) 根据条件在数据条中显示颜色
此时我们已经看到了数据条的工作原理。现在让我们对其进行一些自定义,以便根据条件显示自定义颜色。我们将要做的是,如果得分大于或等于 100,我们将显示绿色条形图,否则显示红色条形图。
让我们将以下自定义代码添加到我们的报表中(请参考“使用表达式”部分,了解如何将自定义代码添加到报表中)。
'Function to set the color Public Shared Function SetColor(ByVal RunsMade As Integer) As String SetColor= "Red" If RunsMade > 100 Then SetColor= "Green" End IF End Function
代码非常简单易懂。它将根据条件返回颜色,红色或绿色。
现在考虑我们已按如下方式设计了报表(我们之前已经看过。此后,我不再解释)。
让我们选择数据条以获取“图表数据”弹出窗口。然后右键单击条形图并选择 **“系列属性”**。
在 **“系列属性”** 窗口中,选择“填充”选项卡,然后单击“表达式”按钮(fx)。
并在表达式编辑器中输入以下表达式。
=Code.SetColor(Fields!RunsMade.Value)
就是这样。现在,如果我们运行报表,我们将获得所需的结果。
请注意,为了美化,我们为报表添加了一些渐变效果。
(K) 显示带有数据条的数据标签
让我们看看如何显示带有数据条的数据标签。
右键单击数据条并选择 **“显示数据标签”**。
数据标签显示如下。
右键单击数据标签并选择 **“系列标签属性”**。
在“系列标签属性”窗口中,转到“边框”选项卡,并将“线型”设置为“实线”。
运行报表。可以看出,我们现在同时拥有了数据条和数据标签。
(L) 使用指示器
当执行 KPI(关键绩效指标)分析时,指示器会发挥作用。
我们将执行与数据条相同的实验。
因此,我们将添加一个三列的表,其中第一列将包含 [Players Name],其余两列将包含 [Runs Made]。我们还将将最后一列的标题更改为 [Runs Analysis]。
从“报表项”工具箱,让我们将一个 **指示器控件** 拖放到第三列中。将出现 **“指示器类型属性”** 窗口。从那里,让我们选择“3 箭头(彩色)”方向指示器类型。
然后单击“确定”。我们可以从“指示器属性”中可用的“值和状态”选项中更改指示器的值和状态。我们甚至可以添加更多指示器状态。默认情况如下所示。
现在运行报表,结果如下。
现在让我们分析报表并理解箭头的意思。如果我们还记得,在值和状态中,范围设置如下。
Color | 起始范围 | 结束范围 |
红色 | 0 | 33 |
黄色 | 33 | 66 |
绿色 | 66 | 100 |
现在让我们分析前三行。第一行的得分是 440,即 440/10 是 44,在黄色范围内。下一个是 50,即 50/5 = 5,在红色区域内。同样,第三个在绿色区域内。
希望这有所帮助。
结论
希望本文能帮助那些想开始学习 SSRS 的人,也同样帮助那些想刷新长期未接触过的报表主题的人。在 **SSRS 系列的第一部分**中,我们看到了不同的报表创建方式。在本部分中,我们通过更多实际示例,看到了子报表、树状视图/钻取报表、表达式和自定义代码、计算字段、数据条、指示器等的用法。我们还看到了如何使用 WCF 服务以及 Web 服务,并在运行时传递参数。在下一篇文章中,我们将通过实际示例,探讨 SSRS 的其他一些有趣方面,例如分层报表、图表、仪表、迷你图、地图、Sql Azure 作为数据源等。
感谢阅读本文。