Adicionar cor de linha alternada ao relatório do SQL Server Reporting Services

142

Como você sombreia linhas alternadas em um relatório do SQL Server Reporting Services?


Edit: Existem várias respostas boas listadas abaixo - de rápidas e simples a complexas e abrangentes . Infelizmente, eu posso escolher apenas um ...

Michael Haren
fonte
2
= IIf (RowNumber (Nothing) Mod 2 = 0, "No Color", "# DDEBF7")
Stefan Steiger
Se você selecionar várias células, não poderá editar as propriedades da caixa de texto, mas poderá acessar a cor de preenchimento no painel de propriedades e definir uma expressão lá!
Kitsu.eb 03/02

Respostas:

213

Vá para a propriedade BackgroundColor da linha da tabela e escolha "Expressão ..."

Use esta expressão:

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

Esse truque pode ser aplicado a muitas áreas do relatório.

E no .NET 3.5+ você pode usar:

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

Não estou procurando representante - acabei de pesquisar essa pergunta e pensei em compartilhar.

Michael Haren
fonte
10
Isso falha em determinadas circunstâncias, principalmente em tabelas e objetos de matriz com muitos subtotais. A resposta de Catch22 não tem as mesmas limitações. Além disso, o método de Catch22 pode ser usado para forçar as colunas em uma matriz a terem cores de coluna alternadas, o que é útil uma vez na lua azul.
Usuário registrado
16
Eu sempre faço questão de votar em alguém que responde à sua própria pergunta. Muitas vezes, o solicitante encontra uma resposta por conta própria e nunca mais volta para publicá-la, deixando o resto de nós que pode ter a mesma pergunta no escuro. Um solavanco para você, senhor.
Matt DiTrolio
4
Quando uso o código acima, recebo uma mensagem de aviso como [rsInvalidColor] The value of the BackgroundColor property for the textbox ‘active’ is “Transparent”, which is not a valid BackgroundColor. Parece que a expressão correta seria =IIf(RowNumber(Nothing) Mod 2 = 0, "Silver", Nothing). Obrigado pela dica, no entanto.
Russell B
2
Isto dá o problema em caso de agrupamento e exibição de detalhes
3
alguns navegadores não conseguem lidar com "Transparente" ou "Nada". A melhor aposta seria usar "White"
Nate S.
89

O uso de IIF (RowNumber ...) pode causar alguns problemas quando as linhas estão sendo agrupadas e outra alternativa é usar uma função simples do VBScript para determinar a cor.

É um pouco mais de esforço, mas quando a solução básica não é suficiente, é uma boa alternativa.

Basicamente, você adiciona código ao relatório da seguinte maneira ...

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

Em cada célula, defina o BackgroundColor da seguinte maneira:

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

Detalhes completos estão neste artigo da Wrox

Catch22
fonte
O código acima é adicionado à seção Código do relatório ou a uma página de code-behind em um projeto VB.NET, compilado e implantado como uma DLL que é referência como um assembly. Eu recomendo fazer um esforço extra para implantar isso como uma dll, pois você geralmente faz referência a isso em vários relatórios.
Usuário registrado
Esta é a minha maneira preferida de lidar com o problema de agrupamento, depois de tentar alguns outros hacks. Não é interrompido quando a classificação interativa é aplicada a uma coluna. +1 e muito obrigado.
Rex Miller
As cores são deslocadas quando você tem um número ímpar de linhas.
K Richard
20
Não se esqueça de alterar "Verdadeiro" para "Falso" para todas as colunas na linha após a primeira, caso contrário, você verá um efeito quadriculado! Obrigado pela solução - funciona muito bem!
Peter Mularien 13/03/11
Peter Mularien: Estou tendo esse problema, você pode explicar como corrigi-lo?
Engenheiro Bill Software
65

Tive o efeito do xadrez quando usei a solução da Catch22, acho que porque minha matriz possui mais de uma coluna no design. essa expressão funcionou bem para mim:

=iif(RunningValue(Fields![rowgroupfield].Value.ToString,CountDistinct,Nothing) Mod 2,"Gainsboro", "White")
ahmad
fonte
13
Essa resposta merece muito mais atenção - é uma solução limpa que funciona perfeitamente em uma matriz com grupos de linhas e colunas e não requer código personalizado para funcionar. Lindo!
Stefan Mohr
9
Na verdade, isso funciona bem mesmo para várias colunas - mas não se você tiver dados "ausentes" em um agrupamento. Portanto, se você tiver dados com 12 meses de dados em 2007, mas sem dados de janeiro de 2006, e agrupar por mês em linhas e ano em colunas, a coloração de 2006 será desativada em um porque o RunningValue fica offsync porque, embora exista ainda uma caixa na matriz para "Janeiro de 2006" não há dados no conjunto de dados eo RunningValue permanece o mesmo, nenhuma mudança de cor, etc.
Kyle Hale
2
@ ahmad isso é tão perto. Estou tendo o problema de caixas vazias usarem a cor oposta. como garantir que as caixas vazias sejam coloridas corretamente?
FistOfFury
@KyleHale você tem uma correção para a coloração da caixa que falta?
FistOfFury
2
@FistOfFury A única solução que eu conheço é garantir que um valor seja definido (geralmente 0) para os dados ausentes.
Kyle Hale #
20

Alterei a solução do @ Catch22 Um pouco porque não gosto da ideia de entrar em cada campo se decidir mudar uma das cores. Isso é especialmente importante nos relatórios em que existem vários campos que precisam ter a variável de cor alterada.

'*************************************************************************
' -- 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

Notei que alterei a função de uma que aceita as cores para uma que contém as cores a serem usadas.

Em cada campo, adicione:

=Code.AlternateColor(rownumber(nothing))

Isso é muito mais robusto do que alterar manualmente a cor na cor de fundo de cada campo.

Michael Eakins
fonte
1
Boa adição a esta discussão! Eu gosto de não ter que definir "Verdadeiro" ou "Falso" em cada coluna. Eu também gosto da opção "mod 3" para poder sombrear apenas a cada 3ª linha.
Baodad 25/11
Eu também gosto desta solução. No entanto, isso não funciona para mim quando eu uso o agrupamento de linhas. A solução da @ ahmad acima funcionou para mim.
Baodad 22/03/16
Esta é uma ótima solução para um tablix se você não deseja adicionar campos adicionais ao seu DataSet!
clamchoda
16

Uma coisa que notei é que nenhum dos dois métodos principais tem noção de que cor a primeira linha deve ter em um grupo; o grupo começará apenas com a cor oposta à última linha do grupo anterior. Eu queria que meus grupos sempre começassem com a mesma cor ... a primeira linha de cada grupo sempre deve ser branca e a próxima linha colorida.

O conceito básico era redefinir a alternância quando cada grupo inicia, então adicionei um pouco de código:

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

Então, eu tenho três tipos diferentes de fundos de células agora:

  1. A primeira coluna da linha de dados possui = Code.AlternateColor ("AliceBlue", "White", True) (é igual à resposta anterior.)
  2. As colunas restantes da linha de dados têm = Code.AlternateColor ("AliceBlue", "White", False) (também é a mesma que a resposta anterior).
  3. A primeira coluna da linha de agrupamento possui = Code.RestartColor ("AliceBlue") (isso é novo.)
  4. As colunas restantes da linha de agrupamento têm = Code.AlternateColor ("AliceBlue", "White", False) (Isso foi usado antes, mas nenhuma menção a ele para o agrupamento de linhas.)

Isso funciona para mim. Se você deseja que a linha de agrupamento seja sem cor ou com uma cor diferente, deve ser bastante óbvio, como alterá-la.

Por favor, sinta-se à vontade para adicionar comentários sobre o que poderia ser feito para melhorar esse código: sou novato no SSRS e no VB, então suspeito fortemente que há muito espaço para melhorias, mas a idéia básica parece sólida (e foi útil para mim) então eu queria jogá-lo aqui.

Beska
fonte
Você também pode redefinir a numeração das linhas de cada grupo, conforme descrito nesta resposta .
StackOverthrow
10

para cabeçalhos / rodapés de grupo:

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

Você também pode usar isso para "redefinir" a contagem de cores da linha em cada grupo. Eu queria que a primeira linha de detalhes de cada subgrupo iniciasse com White e essa solução (quando usada na linha de detalhes) permitiu que isso acontecesse:

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

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

John Saunders
fonte
8

A solução de Michael Haren funciona bem para mim. No entanto, recebi um aviso dizendo que "Transparente" não é um BackgroundColor válido ao visualizar. Foi encontrada uma correção rápida em Configurando elementos BackgroundColor of Report no SSRS . Use Nothing em vez de "Transparente"

= IIf(RowNumber(Nothing) Mod 2 = 0, "Silver", Nothing)
nonetaku
fonte
Branco seria melhor que Nada.
Nate S.
6

A única maneira eficaz de resolver isso sem usar o VB é "armazenar" o valor do módulo de agrupamento de linhas dentro do agrupamento de linhas (e fora do agrupamento de colunas) e referenciá-lo explicitamente no seu agrupamento de colunas. Encontrei esta solução em

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

Mas Ankeet não explica melhor o que está acontecendo, e sua solução recomenda a etapa desnecessária de criar um agrupamento em um valor constante, então aqui está o meu processo passo a passo para uma matriz com um único grupo de linhas RowGroup1:

  1. Crie uma nova coluna dentro do RowGroup1. Renomeie a caixa de texto para algo como RowGroupColor.
  2. Defina o valor da caixa de texto do RowGroupColor como

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

  3. Defina a propriedade BackgroundColor de todas as suas células de linha como

    "=ReportItems!RowGroupColor.Value"

  4. Defina a largura da coluna RowGroupColor como 0pt e defina CanGrow como false para ocultá-lo dos clientes.

Voila! Isso também resolve muitos dos problemas mencionados neste segmento:

  • Redefinições automáticas para subgrupos: basta adicionar uma nova coluna para esse grupo de linhas, executando um RunningValue em seus valores de grupo.
  • Não há necessidade de se preocupar com as opções True / False.
  • As cores são mantidas apenas em um local para facilitar a modificação.
  • Pode ser usado alternadamente em grupos de linhas ou colunas (basta definir a altura como 0 em vez da largura)

Seria incrível se o SSRS expusesse propriedades além de Valor em caixas de texto. Você pode simplesmente preencher esse tipo de cálculo em uma propriedade BackgroundColor das caixas de texto do grupo de linhas e referenciá-lo como ReportItems! RowGroup.BackgroundColor em todas as outras células.

Ahh bem, podemos sonhar ...

Kyle Hale
fonte
5

Meu problema era que eu queria que todas as colunas seguidas tivessem o mesmo plano de fundo. Agrupei por linha e por coluna e, com as duas principais soluções, obtive todas as linhas da coluna 1 com fundo colorido, todas as linhas da coluna 2 com fundo branco, todas as linhas da coluna 3 com fundo colorido , e assim por diante. É como se RowNumbere bOddRow(da solução de Catch22) prestasse atenção ao meu grupo de colunas em vez de ignorá-lo e alternando apenas com uma nova linha.

O que eu queria era que todas as colunas da linha 1 tivessem um plano de fundo branco, depois todas as colunas da linha 2 tivessem um plano de fundo colorido, depois todas as colunas da linha 3 tivessem um plano de fundo branco e assim por diante. Eu obtive esse efeito usando a resposta selecionada, mas em vez de passar Nothingpara RowNumber, passei o nome do meu grupo de colunas, por exemplo

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

Achei que isso poderia ser útil para outra pessoa.

Sarah Vessels
fonte
4

Eu acho que esse truque não é discutido aqui. Então aqui está,

Em qualquer tipo de matriz complexa, quando você deseja cores de célula alternativas, em linhas ou em colunas, a solução de trabalho é:

Se você quiser uma cor alternativa de células, então,

  1. No canto inferior direito de uma exibição de design de relatório, em "Grupos de colunas", crie um grupo pai falso em 1 (usando a expressão), chamado "FakeParentGroup".
  2. Em seguida, no design do relatório, para células que devem ser coloridas como alternativa, use a seguinte expressão de cor de plano de fundo

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

Isso é tudo.

O mesmo para as linhas de cores alternativas, basta editar a solução de acordo.

NOTA: Aqui, às vezes você precisa definir a borda das células adequadamente, geralmente ela desaparece.

Também não se esqueça de excluir o valor 1 no relatório que entrou na foto quando você criou um grupo pai falso.

Aditya
fonte
1
Esta resposta é definitivamente um ótimo achado para quem precisa criar faixas em tablixes complexos! Se houver um grupo pai existente, use-o. Caso contrário, crie FakeParentGroup. Valores ausentes em tablixes que possuem grupos de colunas e linhas geralmente descartam a formatação. Veja minha resposta que se baseia em @ Aditya para explicar os valores ausentes na primeira célula.
rpyzh
2

Se, para todo o relatório, você precisar de uma cor alternada, poderá usar o DataSet ao qual o Tablix está vinculado a um número de referência de identidade de todo o relatório no relatório e usá-lo na função RowNumber ...

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

@ A resposta de Aditya é ótima, mas há casos em que a formatação será iniciada se a primeira célula da linha (para formatação de plano de fundo da linha) tiver um valor ausente (em tablixes complexos com grupos de colunas / linhas e valores ausentes).

A solução da @ Aditya aproveita inteligentemente o countDistinctresultado da runningValuefunção para identificar números de linhas em um grupo tablix (linha). Se você tiver linhas tablix com valor ausente na primeira célula, runningValuenão aumentará o countDistinctresultado e retornará o número da linha anterior (e, portanto, afetará a formatação dessa célula). Para explicar isso, você precisará adicionar um termo adicional para compensar o countDistinctvalor. Minha opinião foi verificar o primeiro valor em execução no próprio grupo de linhas (consulte a linha 3 do snippet abaixo):

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

Espero que isto ajude.

rpyzh
fonte
Obrigado @rpyzh, esta foi a solução que funcionou para o meu grupo de várias linhas com um relatório de grupo de linhas pai comum!
Niallty
1

Alguém poderia explicar a lógica por trás de transformar o restante dos campos em false no código abaixo (da postagem acima)

Uma coisa que notei é que nenhum dos dois métodos principais tem noção da cor da primeira linha de um grupo; o grupo começará apenas com a cor oposta à última linha do grupo anterior. Eu queria que meus grupos sempre começassem com a mesma cor ... a primeira linha de cada grupo sempre deve ser branca e a próxima linha colorida.

O conceito básico era redefinir a alternância quando cada grupo inicia, então adicionei um pouco de código:

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

Então, eu tenho três tipos diferentes de fundos de células agora:

  1. A primeira coluna da linha de dados possui = Code.AlternateColor ("AliceBlue", "White", True) (é igual à resposta anterior.)
  2. As colunas restantes da linha de dados têm = Code.AlternateColor ("AliceBlue", "White", False) (também é a mesma que a resposta anterior).
  3. A primeira coluna da linha de agrupamento possui = Code.RestartColor ("AliceBlue") (isso é novo.)
  4. As colunas restantes da linha de agrupamento têm = Code.AlternateColor ("AliceBlue", "White", False) (Isso foi usado antes, mas nenhuma menção a ele para o agrupamento de linhas.)

Isso funciona para mim. Se você deseja que a linha de agrupamento seja sem cor ou com uma cor diferente, deve ser bastante óbvio, como alterá-la.

Por favor, sinta-se à vontade para adicionar comentários sobre o que poderia ser feito para melhorar esse código: sou novato no SSRS e no VB, então suspeito fortemente que há muito espaço para melhorias, mas a idéia básica parece sólida (e foi útil para mim) então eu queria jogá-lo aqui.

misha
fonte
1

Tentei todas essas soluções em um Tablix agrupado com espaços de linha e nenhum funcionou em todo o relatório. O resultado foram linhas coloridas duplicadas e outras soluções resultaram em colunas alternadas!

Aqui está a função que escrevi que funcionou para mim usando uma Contagem de colunas:

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

Para um Tablix de 7 colunas, uso esta expressão para o Backcolour Row (of Cells):

=Code.AlternateColorByColumnCount("LightGrey","White", 7)
Jeremy Thompson
fonte
0

Meus dados matriciais tinham valores ausentes, então não consegui fazer a solução do ahmad funcionar, mas essa solução funcionou para mim

A idéia básica é criar um grupo filho e um campo no seu grupo mais interno que contenha a cor. Em seguida, defina a cor para cada célula na linha com base no valor desse campo.

FistOfFury
fonte
Confira @ Aditya e minha resposta para lidar com os valores ausentes na matriz. Útil se você já possui (ou deseja criar um grupo falso) de pais. Você não precisará criar um campo separado dessa maneira.
Rpyzh
0

Ligeira modificação de outras respostas daqui que funcionaram para mim. Meu grupo tem dois valores para agrupar, então pude colocar os dois no primeiro argumento com um + para alternar corretamente

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

Ao usar os dois grupos de linhas e colunas, tive um problema em que as cores alternavam entre as colunas, mesmo que fosse a mesma linha. Eu resolvi isso usando uma variável global que alterna apenas quando a linha é alterada:

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

Agora, na primeira coluna da linha que você deseja alternar, defina a expressão de cor para:

= Code.AlternateColor ()

-

Nas colunas restantes, defina todos eles para:

= Code.BGColor

Isso deve alternar as cores somente depois que a primeira coluna for desenhada.

Isso pode (inverificável) melhorar o desempenho também, uma vez que não é necessário fazer um cálculo matemático para cada coluna.

Eneerge
fonte