向 SQL Server Reporting Services 报表添加交替行颜色

Posted

技术标签:

【中文标题】向 SQL Server Reporting Services 报表添加交替行颜色【英文标题】:Add alternating row color to SQL Server Reporting services report 【发布时间】:2010-09-07 20:18:45 【问题描述】:

如何在 SQL Server Reporting Services 报表中对交替行进行着色?


编辑:下面列出了很多好的答案——从quick 和simple 到complex and comprehensive。唉,我只能选择一个……

【问题讨论】:

= IIf(RowNumber(Nothing) Mod 2 = 0, "No Color", "#DDEBF7") 如果您选择多个单元格,则无法编辑文本框属性,但您可以在属性面板中访问填充颜色并在那里设置表达式! 【参考方案1】:

转到表格行的 BackgroundColor 属性并选择“Expression...”

使用这个表达式:

= IIf(RowNumber(Nothing) Mod 2 = 0, "Silver", "Transparent")

这个技巧可以应用于报告的许多领域。

在 .NET 3.5+ 中,您可以使用:

= If(RowNumber(Nothing) Mod 2 = 0, "Silver", "Transparent")

不寻找代表——我只是自己研究了这个问题,并认为我会分享。

【讨论】:

这在某些情况下会失败,尤其是在具有大量小计的表格和矩阵对象中。 Catch22 的响应没有相同的限制。此外,Catch22 的方法可用于强制矩阵中的列具有交替的列颜色,这在蓝月亮中非常有用。 我总是确保为回答自己问题的人投票。很多时候,提问者自己找到了答案,然后就再也没有回来发布它,而让我们其他可能有同样问题的人一头雾水。先生,给你一个惊喜。 当我使用上面的代码时,我收到一条警告消息,如[rsInvalidColor] The value of the BackgroundColor property for the textbox ‘active’ is “Transparent”, which is not a valid BackgroundColor. 看起来正确的表达式应该是=IIf(RowNumber(Nothing) Mod 2 = 0, "Silver", Nothing)。不过,感谢您的提示。 这会在分组和详细信息视图的情况下出现问题 某些浏览器无法处理“透明”或“无”。最好的选择是使用“白色”【参考方案2】:

在对行进行分组时,使用 IIF(RowNumber...) 可能会导致一些问题,而另一种选择是使用简单的 VBScript 函数来确定颜色。

这需要更多的努力,但是当基本解决方案不够用时,这是一个不错的选择。

基本上,您将代码添加到报告中,如下所示...

Private bOddRow As Boolean
'*************************************************************************
' -- Display green-bar type color banding in detail rows
' -- Call from BackGroundColor property of all detail row textboxes
' -- Set Toggle True for first item, False for others.
'*************************************************************************
Function AlternateColor(ByVal OddColor As String, _
         ByVal EvenColor As String, ByVal Toggle As Boolean) As String
    If Toggle Then bOddRow = Not bOddRow
    If bOddRow Then
        Return OddColor
    Else
        Return EvenColor
    End If
End Function

然后在每个单元格上,设置 BackgroundColor 如下:

=Code.AlternateColor("AliceBlue", "White", True)

详情请见Wrox article

【讨论】:

上述代码要么添加到报告的代码部分,要么添加到 VB.NET 项目中的代码隐藏页面,编译和部署为作为程序集引用的 DLL。我建议您付出额外的努力将其部署为 dll,因为您通常会在许多报告中引用它。 这是我在尝试了一些其他技巧之后处理分组问题的首选方式。将交互式排序应用于列时,它不会崩溃。 +1 非常感谢。 当行数为奇数时,颜色会发生偏移。 不要忘记将第一行之后的所有列的“True”更改为“False”,否则会看到棋盘效果!感谢您的解决方案 - 效果很好! Peter Mularien:我遇到了这个问题,您能解释一下如何解决吗?【参考方案3】:

对于组页眉/页脚:

=iif(RunningValue(*group on field*,CountDistinct,"*parent group name*") Mod 2,"White","AliceBlue")

您还可以使用它来“重置”每个组中的行颜色计数。我希望每个子组中的第一个详细信息行以 White 开头,并且此解决方案(在详细信息行上使用时)允许这种情况发生:

=IIF(RunningValue(Fields![Name].Value, CountDistinct, "NameOfPartnetGroup") Mod 2, "White", "Wheat")

见:http://msdn.microsoft.com/en-us/library/ms159136(v=sql.100).aspx

【讨论】:

【参考方案4】:

我注意到的一件事是,前两种方法都没有关于组中第一行应该是什么颜色的概念。该组将以与前一组的最后一行相反的颜色开始。我希望我的组总是以相同的颜色开始...每组的第一行应该始终是白色的,下一行应该是彩色的。

基本概念是在每个组开始时重置切换,所以我添加了一些代码:

Private bOddRow As Boolean
'*************************************************************************
' -- Display green-bar type color banding in detail rows
' -- Call from BackGroundColor property of all detail row textboxes
' -- Set Toggle True for first item, False for others.
'*************************************************************************
Function AlternateColor(ByVal OddColor As String, _
         ByVal EvenColor As String, ByVal Toggle As Boolean) As String
    If Toggle Then bOddRow = Not bOddRow
    If bOddRow Then
        Return OddColor
    Else
        Return EvenColor
    End If
End Function
'
Function RestartColor(ByVal OddColor As String) As String
    bOddRow = True
    Return OddColor
End Function

所以我现在有三种不同的单元格背景:

    数据行第一列有 =Code.AlternateColor("AliceBlue", "White", True) (这与上一个答案相同。) 数据行的其余列有 =Code.AlternateColor("AliceBlue", "White", False) (这也与上一个答案相同。) 分组行的第一列有 =Code.RestartColor("AliceBlue")(这是新的。) 分组行的剩余列有 =Code.AlternateColor("AliceBlue", "White", False) (这个以前用过,但没有提到分组行。)

这对我有用。如果您希望分组行是非彩色的或不同的颜色,那么如何更改它应该是相当明显的。

请随时向 cmets 添加有关改进此代码的方法:我对 s-s-rS 和 VB 都是全新的,所以我强烈怀疑还有很大的改进空间,但基本想法似乎是合理的(并且它对我很有用)所以我想把它扔在这里。

【讨论】:

您还可以按照this answer 中的说明重置每个组的行编号。【参考方案5】:

我的问题是我希望一行中的所有列都具有相同的背景。我按行和按列分组,这里使用前两个解决方案,我得到 all 第 1 列中的行带有彩色背景,第 2 列中的所有行都带有白色背景,所有行在带有彩色背景的第 3 列中,依此类推。就好像RowNumberbOddRow(Catch22 的解决方案)关注我的列组,而不是忽略它,只与新行交替。

我想要的是第 1 行中的所有 具有白色背景,然后第 2 行中的所有列具有彩色背景,然后第 3 行中的所有列具有白色背景等等。我通过使用选定的答案获得了这种效果,但我没有将Nothing 传递给RowNumber,而是传递了我的列组的名称,例如

=IIf(RowNumber("MyColumnGroupName") Mod 2 = 0, "AliceBlue", "Transparent")

认为这可能对其他人有用。

【讨论】:

【参考方案6】:

如果整个报表需要交替颜色,则可以使用 Tablix 绑定的 DataSet 来获取报表上的报表范围标识行号,并在 RowNumber 函数中使用它...

=IIf(RowNumber("DataSet1")  Mod 2 = 1, "White","Blue")

【讨论】:

【参考方案7】:

Michael Haren 的解决方案对我来说效果很好。但是我收到警告说“透明”在预览时不是有效的背景颜色。找到了一个快速修复 Setting BackgroundColor of Report elements in s-s-rS。使用 Nothing 代替“透明”

= IIf(RowNumber(Nothing) Mod 2 = 0, "Silver", Nothing)

【讨论】:

白色会比什么都好。【参考方案8】:

当我使用 Catch22 的解决方案时,我得到了象棋效果,我认为是因为我的矩阵在设计中不止一列。 这个表达对我来说很好:

=iif(RunningValue(Fields![rowgroupfield].Value.ToString,CountDistinct,Nothing) Mod 2,"Gainsboro", "White")

【讨论】:

这个答案值得更多关注——它是一个干净的解决方案,可以在具有行组和列组的矩阵中完美运行,并且不需要自定义代码即可工作。漂亮! 实际上,即使对于多列,这也可以正常工作 - 但如果您在分组中有“缺失”数据,则不会。因此,如果您的数据在 2007 年有 12 个月的数据数据,但在 2006 年没有 1 月的数据,并且按月对行分组,对列按年分组,则 2006 年的颜色将减一,因为 RunningValue 变得不同步,因为即使有仍然是“2006 年 1 月”矩阵中的一个框,数据集中没有数据,并且 RunningValue 保持不变,没有颜色变化等。 @ahmad 这太接近了。我遇到了空框使用相反颜色的问题。如何确保空框正确着色? @KyleHale 你有修复缺失框着色的方法吗? @FistOfFury 我知道的唯一解决方案是确保为丢失的数据设置一个值(通常为 0)。【参考方案9】:

我已经更改了@Catch22 的解决方案,因为如果我决定要更改其中一种颜色,我不喜欢必须进入每个字段的想法。这在需要更改颜色变量的字段众多的报表中尤其重要。

'*************************************************************************
' -- Display alternate color banding (defined below) in detail rows
' -- Call from BackgroundColor property of all detail row textboxes
'*************************************************************************
Function AlternateColor(Byval rowNumber as integer) As String
    Dim OddColor As String = "Green"
    Dim EvenColor As String = "White"

    If rowNumber mod 2 = 0 then 
        Return EvenColor
    Else
        Return OddColor
    End If
End Function

注意到我已将函数从接受颜色的函数更改为包含要使用的颜色的函数。

然后在每个字段中添加:

=Code.AlternateColor(rownumber(nothing))

这比手动更改每个字段的背景颜色要强大得多。

【讨论】:

很好地加入了这个线程!我喜欢不必在每一列中设置“True”或“False”。我也喜欢“mod 3”的选项,所以我只能每隔 3 行着色。 我也喜欢这个解决方案。但是,当我使用行分组时,它对我不起作用。 @ahmad 上面的 solution 对我有用。 如果您不希望向数据集添加其他字段,这对于 tablix 来说是一个很好的解决方案!【参考方案10】:

有人可以在下面的代码中解释将其余字段变为 false 背后的逻辑(来自上面的帖子)

我注意到的一件事是,前两种方法都没有关于组中第一行应该是什么颜色的概念。该组将以与前一组的最后一行相反的颜色开始。我希望我的组总是以相同的颜色开始...每个组的第一行应该始终是白色的,下一行应该是彩色的。

基本概念是在每个组开始时重置切换,所以我添加了一些代码:

Private bOddRow As Boolean
'*************************************************************************
'-- Display green-bar type color banding in detail rows
'-- Call from BackGroundColor property of all detail row textboxes
'-- Set Toggle True for first item, False for others.
'*************************************************************************
'
Function AlternateColor(ByVal OddColor As String, _
                  ByVal EvenColor As String, ByVal Toggle As Boolean) As String
         If Toggle Then bOddRow = Not bOddRow
         If bOddRow Then 
                Return OddColor
         Else
                 Return EvenColor
         End If
 End Function
 '
 Function RestartColor(ByVal OddColor As String) As String
         bOddRow = True
         Return OddColor
 End Function

所以我现在有三种不同的单元格背景:

    数据行第一列有 =Code.AlternateColor("AliceBlue", "White", True) (这与上一个答案相同。) 数据行的剩余列有 =Code.AlternateColor("AliceBlue", "White", False) (这也与上一个答案相同。) 分组行的第一列有 =Code.RestartColor("AliceBlue")(这是新的。) 分组行的剩余列有 =Code.AlternateColor("AliceBlue", "White", False) (这个以前用过,但没有提到分组行。)

这对我有用。如果您希望分组行是非彩色的或不同的颜色,那么如何更改它应该是相当明显的。

请随时向 cmets 添加有关改进此代码的方法:我对 s-s-rS 和 VB 都是全新的,所以我强烈怀疑还有很大的改进空间,但基本想法似乎是合理的(并且它对我很有用)所以我想把它扔在这里。

【讨论】:

【参考方案11】:

在不使用 VB 的情况下解决此问题的唯一有效方法是将行分组模值“存储”在行分组内(和列分组外),并在列分组内显式引用它。我在

找到了这个解决方案

http://ankeet1.blogspot.com/2009/02/alternating-row-background-color-for.html

但是 Ankeet 并不能很好地解释正在发生的事情,他的解决方案建议在一个常数值上创建分组这一不必要的步骤,所以这是我对具有单行组 RowGroup1 的矩阵的分步过程:

    在 RowGroup1 中创建一个新列。将此文本框重命名为 RowGroupColor 之类的名称。

    将RowGroupColor的文本框的值设置为

    =iif(RunningValue(Fields![RowGroupField].Value ,CountDistinct,Nothing) Mod 2, "LightSteelBlue", "White")

    将所有行单元格的 BackgroundColor 属性设置为

    "=ReportItems!RowGroupColor.Value"

    将 RowGroupColor 列的宽度设置为 0pt 并设置 CanGrow 为 false 以向客户隐藏它。

瞧!这也解决了本帖提到的很多问题:

子组的自动重置:只需为此添加一个新列 行组,对组值执行RunningValue。 无需担心真/假切换。 颜色只保存在一个位置,便于修改。 可以在行组或列组上互换使用(只需将高度设置为 0 而不是宽度)

如果 s-s-rS 能够在 Textboxes 上公开除 Value 之外的属性,那就太棒了。您可以将此类计算填充到行组文本框的 BackgroundColor 属性中,然后在所有其他单元格中将其作为 ReportItems!RowGroup.BackgroundColor 引用。

啊,好吧,我们可以做梦......

【讨论】:

【参考方案12】:

只是因为上面的答案似乎都不适用于我的矩阵,所以我在这里发布:

http://reportingservicestnt.blogspot.com/2011/09/alternate-colors-in-matrixpivot-table.html

【讨论】:

【参考方案13】:

我的矩阵数据中有缺失值,所以我无法让 ahmad 的解决方案起作用,但是 this solution worked for me

基本思想是在包含颜色的最里面的组上创建一个子组和字段。然后根据该字段的值设置行中每个单元格的颜色。

【讨论】:

查看@Aditya 和我处理矩阵中缺失值的答案。如果您已经拥有(或愿意创建假的)父组,则很有用。您不必以这种方式创建单独的字段。【参考方案14】:

我认为这里不讨论这个技巧。就是这样,

在任何类型的复杂矩阵中,当您需要交替的单元格颜色时,无论是逐行还是逐列, 可行的解决方案是,

如果你想要一个不同颜色的单元格,那么

    在报表设计视图的右下角,在“列 Groups”,在 1 上创建一个假的父组(使用表达式),命名为 “FakeParentGroup”。 然后,在报表设计中,为要着色的单元格 或者,使用以下背景颜色表达式

=IIF(RunningValue( Fields![ColumnGroupField].Value, countDistinct, "FakeParentGroup" ) MOD 2, "White", "LightGrey")

就是这样。

交替颜色行也是如此,只是您必须相应地编辑解决方案。

注意:这里,有时你需要相应地设置单元格的边框,通常它会消失。

当你创建假父组时,不要忘记删除进入图片的报告中的值 1。

【讨论】:

对于那些必须在复杂的 tablixes 中创建行带的人来说,这个答案绝对是一个很好的发现!如果有现有的父组,请使用它。否则,创建 FakeParentGroup。具有列组和行组的 tablix 中的缺失值通常会导致格式失效。请参阅基于@Aditya 的答案,以解决第一个单元格中的缺失值。【参考方案15】:

@Aditya 的回答很好,但在某些情况下,如果行的第一个单元格(用于行背景格式)有缺失值(在具有列/行组和缺失值的复杂 tablixes 中),格式将被丢弃.

@Aditya 的解决方案巧妙地利用countDistinct 函数的结果runningValue 来识别tablix(行)组中的行号。如果您在第一个单元格中有缺少值的 tablix 行,runningValue 将不会增加 countDistinct 结果,它将返回前一行的编号(因此,会影响该单元格的格式)。考虑到这一点,您必须添加一个附加项来抵消countDistinct 的值。我的做法是检查行组本身的第一个运行值(参见下面 sn-p 的第 3 行):

=iif(
    (RunningValue(Fields![RowGroupField].Value, countDistinct, "FakeOrRealImmediateParentGroup")
    + iif(IsNothing(RunningValue(Fields![RowGroupField].Value, First, "GroupForRowGroupField")), 1, 0)
    ) mod 2, "White", "LightGrey")

希望这会有所帮助。

【讨论】:

感谢@rpyzh,这是适用于我的多行组的解决方案,具有共同的父行组报告!【参考方案16】:

我在带有行空间的 Grouped Tablix 上尝试了所有这些解决方案,但没有一个适用于整个报表。结果是重复的彩色行和其他解决方案导致交替列!

这是我编写的使用列数为我工作的函数:

Private bOddRow As Boolean
Private cellCount as Integer

Function AlternateColorByColumnCount(ByVal OddColor As String, ByVal EvenColor As String, ByVal ColCount As Integer) As String

if cellCount = ColCount Then 
bOddRow = Not bOddRow
cellCount = 0
End if 

cellCount  = cellCount  + 1

if bOddRow Then
 Return OddColor
Else
 Return EvenColor
End If

End Function

对于 7 列 Tablix,我将此表达式用于(单元格)行背景色:

=Code.AlternateColorByColumnCount("LightGrey","White", 7)

【讨论】:

【参考方案17】:

从这里对我有用的其他答案稍作修改。我的组有两个要分组的值,所以我可以将它们都放在第一个 arg 中,并带有 + 以使其正确交替

= Iif ( RunningValue (Fields!description.Value + Fields!name.Value, CountDistinct, Nothing) Mod 2 = 0,"#e6eed5", "Transparent")

【讨论】:

【参考方案18】:

同时使用行组和列组时,我遇到了一个问题,即颜色会在列之间交替,即使它是同一行。我通过使用仅在行更改时交替的全局变量来解决此问题:

Public Dim BGColor As String = "#ffffff"

Function AlternateColor() As String
  If BGColor = "#cccccc" Then
    BGColor = "#ffffff"
    Return "#cccccc"
  Else
    BGColor = "#cccccc"
    Return "#ffffff"
  End  If
End Function

现在,在要替换的行的第一列中,将颜色表达式设置为:

=Code.AlternateColor()

-

在其余列中,将它们全部设置为:

=代码.BGColor

这应该使颜色仅在绘制第一列后才交替。

这也可能(无法验证)提高性能,因为它不需要对每一列进行数学计算。

【讨论】:

以上是关于向 SQL Server Reporting Services 报表添加交替行颜色的主要内容,如果未能解决你的问题,请参考以下文章