65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.95/5 (90投票s)

2011 年 5 月 12 日

CPOL

17分钟阅读

viewsIcon

514122

downloadIcon

28299

在本文中,我们将学习创建子报表、钻取报表、自定义代码和表达式、Web 服务和 WCF 服务从 SSRS 的消费、自定义分页和排序、使用实时示例处理数据条和指示器。

目录

  1. 引言
  2. 背景
  3. 数据源
  4. 在 SSRS 中创建子报表 (下载 Subreport.zip 文件)
  5. 在 SSRS 中创建钻取报表 (下载 DrilDownReport_Example.zip 文件)
  6. 使用表达式和自定义代码 (下载 WorkingWithExpression.zip 文件)
  7. 使用计算字段 (下载 CalculatedFields.zip 文件)
  8. 列排序 (下载 Sorting.zip 文件)
  9. SSRS 报表中的自定义分页 (下载 CustomPaging.zip 文件)
  10. SSRS 和 WCF 数据源 (下载 SSRS_WCF_Example.zip 文件)
  11. SSRS 和 Web 服务数据源 (下载 SSRS_WebService_Example.zip 文件)
  12. 使用数据条 (下载 DataBars&Indicators.zip 文件)
  13. 根据条件在数据条中显示颜色 (下载 DataBars&Indicators.zip 文件)
  14. 显示带有数据条的数据标签 (下载 DataBars&Indicators.zip 文件)
  15. 使用指示器 (下载 DataBars&Indicators.zip 文件)
  16. 结论

引言

在过去的几个月里,我一直在从事 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 
如下所示

1.jpg

我们还将在数据库中创建以下存储过程,其脚本如下

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 参数。因此,在运行时,根据传递的参数值,子报表将被生成。一旦报表创建完毕,我们将在我们的项目中拥有两个报表,如下所示。

2.jpg

单独测试 PlayerSubReport 会产生以下结果。

3.jpg

步骤 2:在主/主报表中添加 SubReport 控件。

4.jpg

步骤 3:右键单击子报表 -> 子报表属性。

5.jpg

步骤 4:在“子报表属性”窗口的“常规”部分,从下拉列表中选择子报表名称(此处为 PlayerSubReport),如下所示。

6.jpg

在“参数”选项卡中,单击“添加”按钮后,让我们输入参数名称为 **“CountryName”**,值为 **“ =First(Fields!BelongsTo.Value, "DataSet1")”**。完成后,单击“确定”按钮。

7.jpg

步骤 5:就是这样。现在让我们运行报表。

8.jpg

因此,我们的子报表已生成。

(B) 在 SSRS 中创建钻取报表

在 SSRS 中创建钻取/树状视图报表非常简单。让我们看以下步骤。

步骤 1:打开 BIDS 并创建一个新的共享数据源。

步骤 2:创建一个表类型报表,如下所示(执行此操作的步骤已在第一部分系列中描述)。

69.jpg

步骤 3:接下来为 **Belongss To** 字段添加 **父组**,如下所示。

70.jpg

步骤 4:在 **Tablix 组**窗口中,让我们从“按分组”下拉列表中选择 **[BelongsTo]**,然后 *选中“添加组标题”复选框*,然后单击“确定”。

71.jpg

此时,如果我们在设计视图中查看报表,它看起来如下。

72.jpg

运行报表时,预览选项卡中的显示如下。

73.jpg

步骤 5:从“行组”中,选择 **[Belongs To] 详细信息**,然后选择 **组属性**。

74.jpg

步骤 6:在打开的“组属性”窗口中,选择“可见性”选项卡。然后选择 **隐藏单选按钮** 并选中 **此报表项可以切换显示** 复选框。然后从将启用的下拉列表中,选择组的名称(此处为 BelongsTo1),然后单击“确定”。

75.jpg

步骤 7:删除 [Belongs To] 详细信息列。

76.jpg

步骤 8:现在一切都完成了。运行应用程序,结果如下。

77.jpg

(C) 使用表达式和自定义代码

在本节中,我们将通过一些示例了解如何在报表中使用的表达式和自定义代码。

目标

我们将要做的是,如果一名球员得分超过 500 分且获得了超过 10 个三振,那么我们将以绿色显示该行和特定列。

为此,让我们首先单击报表设计主体并选择报表属性。

9.jpg

“报表属性”窗口将打开,如下所示。

10.jpg

导航到 **代码选项卡** 以编写以下自定义代码。

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”。

11.jpg

接下来,让我们选择 RunsMade 列并右键单击以打开 TextBox 菜单,从中我们将选择 TextBox 属性。

12.jpg

在出现的“TextBox 属性”窗口中,单击“填充”选项,然后单击 fx 按钮。

13.jpg

在表达式窗口中输入以下表达式。

=Code.SetColor(Fields!RunsMade.Value,Fields!WicketsTaken.Value)

参数传递的代码片段也很简单。在第一个中,我们传递 RunsMade 值,而在第二个中,我们将 WicketsTaken 值传递给刚刚创建的 SetColor 函数。

14.jpg

单击“确定”按钮,然后对 Wickets Taken 列重复相同的操作。完成后,让我们运行应用程序,结果如下。

15.jpg

让我们为报表添加更多自定义。如果满足上述条件,我们将使 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

自定义代码区域现在将如下所示。

16.jpg

接下来,在 **PlayerName 列**中右键单击以显示 TextBox 属性,并在“字体”选项中,为粗体选择 fn。

17.jpg

在表达式编辑器中输入以下代码。

=Code.SetBoldFontWeight(Fields!RunsMade.Value,Fields!WicketsTaken.Value)

在 **Belongs To 列**中右键单击以显示 TextBox 属性,并在“字体”选项中,为斜体选择 fn。

18.jpg

在表达式编辑器中输入以下代码。

=Code.SetItalicFontWeight(Fields!RunsMade.Value,Fields!WicketsTaken.Value).

我们完成了。运行报表,结果如下。

19.jpg

我们将考虑另一种情况,即根据 **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)

结果如下。

20.jpg

同样,我们可以通过使用表达式和自定义代码来设置对齐方式、根据条件隐藏行等等。

(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:选择数据集。右键单击并选择添加计算字段。

21.jpg

“数据集属性”窗口将打开。输入计算字段名称,然后单击“表达式”按钮(fx)。

22.jpg

接下来,在表达式窗口中添加以下表达式。

=Code.DoubleMatchFee(Fields!RunsMade.Value,Fields!WicketsTaken.Value,Fields!FeePerMatch.Value)

23.jpg

点击“确定”。

步骤 3:将 DoubleMatchFee 列拖放到报表设计器中。

24.jpg

右键单击 **DoubleMatch Fee 列**,从文本框属性中选择“字体”,然后在粗体字重旁边输入以下表达式。

=Code.SetBoldFontWeight(Fields!RunsMade.Value,Fields!WicketsTaken.Value)

25.jpg

对于所有其他列,让我们在从“文本框属性”获得的“填充”颜色旁边输入以下表达式。

=Code.SetColor(Fields!RunsMade.Value,Fields!WicketsTaken.Value)

26.jpg

我们完成了。让我们运行报表,结果如下。

27.jpg

希望我们现在可以舒适地使用计算字段了。

(E) 列排序

在本节中,我们将探讨如何在报表中执行列排序。列排序是一项重要功能,也可以从数据库端进行。但是,如果相同的数据源被各种其他应用程序使用,并且每个应用程序都要求以不同的顺序显示结果,那么最好仅在客户端应用程序中进行排序,而不是在数据库中。

让我们看一下以下步骤,了解我们如何在报表中执行此操作。

步骤 1:右键单击列标题并选择文本框属性。

28.jpg

步骤 2:在“文本框属性”对话框中选择“交互式排序”,然后

  1. 选中“为此文本框启用交互式排序”复选框。
  2. 从“排序依据”下拉列表中选择 Player ID 字段。

29.jpg

我们完成了。让我们对 PlayerName 字段执行相同的操作。现在运行报表。

30.jpg

可以看到,已在两列中启用了排序,并且报表以 Player ID 降序显示。

(F) SSRS 报表中的自定义分页

本节将介绍在报表中生成自定义分页的方法。我们还将学习在此过程中使用全局变量。

步骤 1:在报表设计屏幕上,右键单击,然后从上下文菜单中选择“添加页脚”。

31.jpg

添加页脚后,我们可以向其中添加控件。

32.jpg

步骤 2:让我们从“报表项”工具箱将四个文本框添加到设计器中,如下所示。

33.jpg

步骤 3:选择第二个文本框并单击“表达式”。

34.jpg

步骤 4:在打开的表达式窗口中,让我们编写表达式。

=Globals!PageNumber

35.jpg

同样,对于第四个文本框,让我们编写表达式为 **=Globals!TotalPages.**。

步骤 5:运行报表,结果如下。

36.jpg

(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”**。

58.jpg

让我们在查询设计器中编写以下查询。

<Query>
  <Method Namespace="http://tempuri.org/" Name="GetAllPlayers" />
  <SoapAction>http://tempuri.org/IService1/GetAllPlayers</SoapAction>
</Query>

单击 **运行图标** 以获得以下结果。

59.jpg

接下来,按照第一部分系列中描述的步骤生成报表,最终结果将是。

60.jpg

注意:如果我们想为 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>

请注意,查询中的参数名称和方法必须相同。

61.jpg

在此,我们将 PlayerID 参数的值硬编码为 10。但是,我们可以在运行时传递它。为此,请按照以下步骤进行。

步骤 1:转到视图 -> 报表数据。或者按 CTRL + ALT + D。

步骤 2:出现“报表数据”窗口。从那里右键单击 **“参数”文件夹** 以添加参数。

62.jpg

步骤 3:在 **“报表参数属性”窗口**中,输入参数名称(此处为 PlayerID),输入提示(可选),并将数据类型输入为 **整数**。完成后,单击“确定”按钮。

63.jpg

步骤 4:右键单击数据集,然后单击“数据集属性”。

64.jpg

步骤 5:接下来,单击左侧的“参数”选项卡,然后添加 **参数名称** 为 **playerID**,**参数值** 为 **[@PlayerID]**。

65.jpg

就是这样。运行报表。在提示中输入 Player Id,然后单击“查看”按钮以查看结果报表。

66.jpg

(H) SSRS 和 Web 服务数据源

这与上面非常相似。让我们首先创建一个 Asp.net Web 服务项目。然后添加与上一个示例中的数据源相同的 Player Entity。Web 方法如下。

[WebMethod]
public List<Player> GetAllPlayers()
{
  return PlayerDataSource();
}

接下来,让我们打开 BIDS 并创建一个 **报表服务器项目**。在共享数据源中,让我们将 **类型指定为 XML**,并将 **连接字符串指定为“https://:49277/WebService/WebService.asmx”**。

67.jpg

让我们在查询设计器中编写以下查询。

<Query>
   <Method Namespace="http://tempuri.org/" Name="GetAllPlayers"> </Method>
   <SoapAction>http://tempuri.org/GetAllPlayers</SoapAction>
   <ElementPath IgnoreNamespaces="true">*</ElementPath>
</Query>

接下来,按照第一部分系列中描述的步骤生成报表,我们将获得所需的结果。

68.jpg

注意:要向报表添加参数,请遵循上述相同步骤,因此在本节中忽略。

(I) 使用数据条

数据条用于制作 **“龙卷风图”**,以便了解值的分布情况。

我们也将在此演示中使用相同的数据源 tbl_Players。

目标

在此实验中,我们将使用数据条查看玩家得分的分布情况。

数据条实操

在设计视图中,添加一个包含三列的表。在第一列中,让我们添加 [Player Name] 字段,在最后两列中,让我们添加 [Runs Made] 列。让我们将第三列的标题重命名为 [Runs Analysis]。

37.jpg

从“报表项”工具箱,让我们将一个数据条控件拖放到第三列中。将出现 **“数据条类型属性”** 窗口。从那里,让我们选择 **“堆积条形图”** 数据条类型。

38.jpg

然后单击“确定”。右键单击数据条,然后从上下文菜单中选择 **“图表属性”**。

39.jpg

在“图表属性”窗口的 **“常规”** 部分,从 **“调色板”** 下拉列表中选择 **“灰度”**。

40.jpg

在 **“填充”** 部分,在 **“填充样式”** 中选择 **“渐变”** 并提供一些合适的渐变。

41.jpg

单击“确定”并查看报表。

42.jpg

我们可以反转数据条的方向。右键单击数据条,然后从上下文菜单中选择 **“水平轴属性”**。从属性对话框中,在 **“刻度选项”** 的 **“反转方向”** 复选框中打勾。

43.jpg

报表如下。

44.jpg

(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

代码非常简单易懂。它将根据条件返回颜色,红色或绿色。

现在考虑我们已按如下方式设计了报表(我们之前已经看过。此后,我不再解释)。

45.jpg

让我们选择数据条以获取“图表数据”弹出窗口。然后右键单击条形图并选择 **“系列属性”**。

46.jpg

在 **“系列属性”** 窗口中,选择“填充”选项卡,然后单击“表达式”按钮(fx)。

47.jpg

并在表达式编辑器中输入以下表达式。

 =Code.SetColor(Fields!RunsMade.Value) 

48.jpg

就是这样。现在,如果我们运行报表,我们将获得所需的结果。

49.jpg

请注意,为了美化,我们为报表添加了一些渐变效果。

(K) 显示带有数据条的数据标签

让我们看看如何显示带有数据条的数据标签。

右键单击数据条并选择 **“显示数据标签”**。

50.jpg

数据标签显示如下。

51.jpg

右键单击数据标签并选择 **“系列标签属性”**。

52.jpg

在“系列标签属性”窗口中,转到“边框”选项卡,并将“线型”设置为“实线”。

53.jpg

运行报表。可以看出,我们现在同时拥有了数据条和数据标签。

54.jpg

(L) 使用指示器

当执行 KPI(关键绩效指标)分析时,指示器会发挥作用。

我们将执行与数据条相同的实验。

因此,我们将添加一个三列的表,其中第一列将包含 [Players Name],其余两列将包含 [Runs Made]。我们还将将最后一列的标题更改为 [Runs Analysis]。

从“报表项”工具箱,让我们将一个 **指示器控件** 拖放到第三列中。将出现 **“指示器类型属性”** 窗口。从那里,让我们选择“3 箭头(彩色)”方向指示器类型。

55.jpg

然后单击“确定”。我们可以从“指示器属性”中可用的“值和状态”选项中更改指示器的值和状态。我们甚至可以添加更多指示器状态。默认情况如下所示。

56.jpg

现在运行报表,结果如下。

57.jpg

现在让我们分析报表并理解箭头的意思。如果我们还记得,在值和状态中,范围设置如下。

Color 起始范围 结束范围
红色 0 33
黄色 33 66
绿色 66 100

现在让我们分析前三行。第一行的得分是 440,即 440/10 是 44,在黄色范围内。下一个是 50,即 50/5 = 5,在红色区域内。同样,第三个在绿色区域内。

希望这有所帮助。

结论

希望本文能帮助那些想开始学习 SSRS 的人,也同样帮助那些想刷新长期未接触过的报表主题的人。在 **SSRS 系列的第一部分**中,我们看到了不同的报表创建方式。在本部分中,我们通过更多实际示例,看到了子报表、树状视图/钻取报表、表达式和自定义代码、计算字段、数据条、指示器等的用法。我们还看到了如何使用 WCF 服务以及 Web 服务,并在运行时传递参数。在下一篇文章中,我们将通过实际示例,探讨 SSRS 的其他一些有趣方面,例如分层报表、图表、仪表、迷你图、地图、Sql Azure 作为数据源等。

感谢阅读本文。

© . All rights reserved.