André Alves de Lima

Talking about Software Development and more…

Utilizando expressões no Report Viewer

Em todo relatório que você desenvolver (ou tiver que dar manutenção) você provavelmente contará com alguma fórmula. No Report Viewer as fórmulas são chamadas de expressões (ou “expressions“). A documentação oficial sobre expressões no Report Viewer deixa um pouco a desejar, sem falar que não existe uma versão traduzida para o português. Pensando nisso, resolvi escrever esse artigo abordando as principais expressões que podemos utilizar em relatórios do Report Viewer.

Não tenho como comentar sobre todas as expressões disponíveis no Report Viewer, uma vez que elas são muitas. Porém, acredito que as expressões que listarei neste artigo são as mais comuns e com certeza algum dia você irá utilizá-las nos seus relatórios.

Inserindo expressões no relatório

Podemos utilizar expressões em praticamente todos os controles e propriedades dos relatórios no Report Viewer. Podemos inclusive utilizar expressões nas propriedades de visibilidade e cor de fundo para implementarmos formatação condicional.

Para adicionarmos expressões em células de uma tabela ou em um campo texto, basta clicarmos com o botão direito do mouse sobre o item desejado e escolhermos a opção “Expression“:

Já para utilizarmos expressões em propriedades, basta abrirmos a caixa de opções da propriedade e, caso ela suporte a utilização de expressões, você encontrará o item “Expression“. Por exemplo, a propriedade “Hidden” suporta expressões:

Agora vamos ver as principais expressões que podemos utilizar no Report Viewer.

Estruturas de decisão

Acredito que as expressões que implementam estruturas de decisão são as mais utilizadas no desenvolvimento de relatórios (em qualquer plataforma). Pense bem, quando desenvolvemos aplicativos, qual é a estrutura de controle mais utilizada? Muito provavelmente os “ifs“. Pois bem, o “if” é uma estrutura de decisão (ou controle de fluxo) que você pode utilizar também dentro dos seus relatórios do Report Viewer.

No Report Viewer, ao invés de simplesmente chamar-se “if“, essa estrutura de controle se chama “Iif” (vindo do Visual Basic, também presente no Excel, por exemplo). Sua utilização é muito simples. O primeiro parâmetro é uma condição, o segundo parâmetro é o valor que deve ser considerado caso a condição seja verdadeira e o terceiro parâmetro é o valor que deve ser considerado caso a condição seja falsa.

Por exemplo, para retornar 0 caso um valor seja negativo ou o próprio valor caso ele seja positivo, podemos utilizar a seguinte expressão:

=IIf(Fields!Valor.Value < 0, 0, Fields!Valor.Value)

A segunda estrutura de decisão é o “Switch“, que você provavelmente também já conhece da programação em C# ou VB.NET. Com ele conseguimos avaliar diversas condições e indicar o valor de retorno que deve ser utilizado para cada uma das opções. Por exemplo, se tivermos um campo chamado “IDCategoria” (com os itens “C“, “D“, “N“) e quisermos converter para um texto do tipo “Crédito“, “Débito” ou “Neutro“, podemos fazer da seguinte forma:

=Switch(Fields!Valor.IDCategoria = "C", "Crédito", Fields!Valor.IDCategoria = "D", "Débito", Fields!Valor.IDCategoria = "N", "Neutro")

Estruturas de decisão são muito utilizadas para fazer formatações condicionais, uma vez que podemos retornar uma cor baseada em uma condição (ou até mesmo verdadeiro/falso para mostrar/esconder um item do relatório). Não vou abordar esse assunto neste artigo pois quero escrever sobre isso em um artigo futuro.

Totalizadores

Existe uma categoria de expressões que servem para totalizar grupos de valores no Report Viewer. Não vou detalhá-las nesse artigo pois semanas atrás eu escrevi um post justamente sobre totalizadores no Report Viewer.

Datas

Quer mostrar a data atual no seu relatório? Basta utilizar a expressão “Today“. Ou, se quiser pegar uma parte específica de uma data, utilize as expressões “Day“, “Month” e “Year” passando a data desejada. Exemplo:

="Dia: " & Day(Today) & ", mês: " & Month(Today) & ", ano: " & Year(Today)

Já se quisermos adicionar dias a uma data específica, podemos utilizar a expressão “DateAdd“. Essa expressão recebe o intervalo a ser utilizado (“Hour” para adicionar horas, “Day” para adicionar dias, e por aí vai) o valor para o intervalo e a data original. Por exemplo, para retornarmos a data atual + 30 dias, poderíamos utilizar a seguinte expressão:

=DateAdd(DateInterval.Day, 30, Today)

Formatação de strings

Além de ser possível concatenarmos strings através do operador “&“, também podemos formata-las e ajusta-las com algumas outras expressões. Por exemplo, para formatar uma string utilizamos a expressão “Format“. O primeiro parâmetro dessa expressão é o valor a ser formatado e o segundo parâmetro é o formato. Para formatarmos um campo de valor no formato de moeda, utilizamos a seguinte expressão:

=Format(Fields!Valor.Value, "C")

Também é possível formatarmos datas com essa expressão. Para uma lista completa de formatos disponíveis, confira a documentação.

Além da expressão “Format“, temos à nossa disposição a expressão “Right” que utilizamos para pegarmos os valores de uma string de trás pra frente (por exemplo, os três últimos caracteres de uma string), a expressão “Left” para pegarmos os valores à esquerda da string (por exemplo, os três primeiros caracteres de uma string), a expressão “Len” que utilizamos para descobrir a quantidade de caracteres de uma string e a expressão “InStr” que serve para descobrirmos a primeira posição em que um caractere específico aparece dentro de uma string.

Informações do relatório

Outro tipo de expressão muito útil são as expressões que nos retornam informações gerais do relatório. Por exemplo, podemos utilizar a expressão “ReportName” para descobrirmos o nome do relatório e a expressão “ExecutionTime” para descobrirmos a hora em que o relatório foi gerado.

Duas expressões que são muito utilizadas e se enquadram nessa categoria são as expressões “PageNumber” e “TotalPages“. Elas retornam o número da página atual e o número total de páginas, respectivamente. Portanto, para colocarmos no rodapé a informação “Página X de Y“, utilizamos a seguinte expressão:

="Página " & Globals.PageNumber & " de " & Globals.TotalPages

Porém, é importante notar que essas expressões se encontram dentro do grupo de expressões globais (por isso elas começam com “Globals.“). Esse tipo de expressão só pode ser utilizado no cabeçalho e rodapé do relatório, e não na área de detalhes. Para uma lista completa das expressões do grupo global, confira a documentação.

Além dessas expressões, temos também duas outras muito úteis, que são as expressões “First” e “Last“. Como o próprio nome diz, elas servem para retornar o primeiro e o último registro da fonte de dados.

Códigos customizados

As expressões abordadas até agora muitas vezes são o suficiente para gerarmos um relatório de qualidade. Porém, algumas vezes precisamos de lógicas mais complexas. Pensando nisso, a Microsoft possibilita a utilização de métodos customizados (estáticos e implementados em .NET) nas expressões do Report Viewer. O processo para utilizar códigos customizados é um pouco extenso, portanto não vou abordá-lo nesse artigo. Pretendo escrever um artigo somente sobre esse tema mais pra frente. Por enquanto, caso você precise dessa funcionalidade, confira a documentação.

Entretanto, algo que eu posso mostrar nessa seção é a utilização de métodos do namespace
Microsoft.VisualBasic e a utilização das classes System.Convert e System.Math. Esse namespace e essas classes são referenciadas automaticamente pelo Report Viewer, portanto, é possível utilizá-las nas nossas expressões sem nenhum esforço. Por exemplo, suponha que você queira retornar o valor absoluto de um campo numérico (valor absoluto significa que sempre teremos um valor positivo, ou seja, se o valor original for negativo, ele perderá o sinal e virará positivo). Nesse caso, podemos utilizar o método Abs da classe Math:

=Math.Abs(Fields!Valor.Value)

Concluindo

A engine do Report Viewer provê várias expressões que fazem com que os nossos relatórios fiquem mais ricos. As expressões abordadas nesse artigo são as que eu mais utilizei nos relatórios que eu desenvolvi até hoje. Existem outras além dessas que você pode conferir na documentação (apesar da documentação do Report Viewer ser bem fraca, como eu mencionei anteriormente). É possível ainda criarmos código customizado em .NET e utilizarmos nas expressões do Report Viewer (isso não foi mostrado nesse artigo, mas, pretendo abordar no futuro). Com isso, espero que você consiga solucionar as demandas mais comuns para a geração de relatórios com o Report Viewer.

E você, já conhecia todas essas expressões? Tem alguma que você acha importante que eu deixei de fora? Dê a sua opinião nos comentários.

Finalmente, caso você ainda não tenha feito, convido para que você assine a minha newsletter. Ao inscrever-se, você sempre ficará por dentro de todos os novos artigos publicados aqui no site, além de ficar sabendo em primeira mão sobre o tema do próximo artigo e receber dicas extras que eu só compartilho por e-mail. Você pode assinar a minha newsletter através desse link ou utilizando o formulário logo abaixo.

Até a próxima!

André Lima

Image by Shaun Dunmall used under Creative Commons
https://www.flickr.com/photos/llamnuds/2815834628

Newsletter do André Lima

* indicates required



Powered by MailChimp

28 thoughts on “Utilizando expressões no Report Viewer

  • Fernando disse:

    Oi André, achei legal os seus tutoriais, mas preciso gerar um rel onde uma linha muda. Imagina que eu tenha algumas linhas com colunas normais, mas caso eu encontre um tipo diferente de registro no banco, a linha muda por completo, perdendo as colunas e passa a ser uma linha com conteúdo string corrido em toda linha sem demarcação das colunas. Impressa essa linha, voltam as linhas normais com demarcação de colunas como era antes da linha especial. Captou a idéia?
    Obrigado se puder me ajudar

    • andrealveslima disse:

      Olá Fernando, obrigado pelo comentário!

      O que eu faria na sua situação seria criar duas linhas no nível do detalhe (uma com a estrutura “normal” das colunas e outra com as linhas “mergeadas” em uma só celula).. Aí é só você criar uma expressão de visibilidade em cada uma dessas linhas de detalhe dependendo da lógica que você quiser.. Sacou?

      Se não ficou claro, me manda um e-mail com um screenshot do que exatamente você está querendo desenvolver que eu tento reproduzir.. Meu e-mail está disponível na página “Sobre“..

      Abraço!
      André Lima

  • Rodrigo Muniz disse:

    Muito bom seu artigo André!

    Porém fiquei com uma dúvida: no CrystalReport é possível criar uma fórmula em uma célula e utilizar o resultado dessa fórmula em outras células. Ex: @DobroValor = valor_do_campo * 2, e em outra célula posso chamar essa variável @DobroValor.

    Existe algo similar a isso no ReportViewer?

  • Rodrigo disse:

    André, bom dia. parabens pelo trabalho, tem ajudado muito.

    Por favor já executou algo parecido? tenho uma coluna (col 1) gerada por calculo de uma outra coluna (col 2) que vem da query. gostaria de fazer uma comparação de valores para mudar a cor da fonte ex( maior q col 2 vermelho, menor q col 2 verde) porem não consigo expressar col 1 na formula. Pode ajudar?

    • andrealveslima disse:

      Olá Rodrigo, obrigado pelo comentário!

      Nesse caso eu armazenaria a fórmula que gera o valor da “col 2” em uma variável (variável da table, você encontra nas propriedades dela).. Aí eu utilizaria essa variável como valor para a célula e também na expressão para definir a cor da fonte.. Sacou?

      Se você não entendeu, me manda um e-mail (contato arroba andrealveslima ponto com ponto br) com mais detalhes da expressão que você está utilizando que eu monto um exemplo e te mando..

      Abraço!
      André Lima

  • Rodrigo disse:

    André, boa tarde.
    Estou trabalhando montando uma tabela no Report. eiste alguma formula que compare e um dado e busque determinada informação? por exemplo pra fazer isso no excel sempre usei o iferror junto com o vlookup.
    Desde já agradeço

    • andrealveslima disse:

      Olá Rodrigo!

      O correspondente ao vlookup (ou procv) do Excel seria a expressão “Lookup”.. Coincidentemente eu estou escrevendo um artigo justamente sobre ela neste exato momento.. Porém, ele ainda não está pronto e só será publicado daqui há algumas semanas.. Enquanto o artigo não sai, você pode dar uma olhada neste vídeo que mostra mais ou menos o conceito dessa expressão (no vídeo autora mostra com o Reporting Services, mas, no Report Viewer a ideia é exatamente a mesma):

      Lookup formulas in SSRS 2008 (Reporting Services)

      Abraço!
      André Lima

      • Rodrigo disse:

        Obrigado! o video ajudou perfeitamente!

        • andrealveslima disse:

          Olá Rodrigo!

          Que bom que o vídeo te ajudou! Acabei de escrever hoje o artigo sobre a expressão “Lookup”.. Ele deverá ser publicado no final do mês.. Vou enviar no seu e-mail uma cópia adiantada do artigo em PDF, espero que ajude também..

          Abraço!
          André Lima

  • Jardel Oliveira disse:

    André,
    Bom Dia!
    Teria alguma expressão que pegue um valor (R$100,00) me retornasse ele por extenso (Cem Reais)?
    Abraços
    Jardel Oliveira

  • Wesley disse:

    Boa tarde, André!

    Tenho uma coluna do tipo “TIME” e queria formatar a saída para hh:mm (ex 12:00).
    Já tentei usar Format(Fields!horario.Value, “HH:mm”) / Format(Fields!horario.Value, “hh:mm”) e não funciona…

    Saberia me informar qual a maneira de formatar essa coluna para que sai hh:mm?

    • andrealveslima disse:

      Olá Wesley!

      Que estranho hein.. Você pode colocar o formato diretamente na propriedade “Format” do seu TextBox (sem precisar criar uma expressão para isso).. Mas, se não funcionou com a chamada explícita do método Format, provavelmente também não vai funcionar com a propriedade..

      Quel é o tipo que esse campo está recebendo no DataSet do relatório? Para ter certeza, entre nas propriedade do DataSet no relatório e, na lista de campos, veja o tipo que está sendo considerado para o campo em questão.. Campos data/hora devem ser definidos com o tipo System.DateTime ou System.TimeSpan..

      Abraço!
      André Lima

  • Mariana disse:

    Olá André, tudo bem? Adoro seus artigos!

    Tenho uma dúvida que é a seguinte, tenho um relatório que só pode mostrar determinadas linhas na primeira página, nas outras não pode mostrar. Eu percebi que não consigo usar a global PageNumber no corpo do relatório, existe alguma forma de fazer isso? Lembrando que é a propriedade Hidden da linha toda, não só da célula.
    Obrigada

    • andrealveslima disse:

      Olá Mariana!

      Muito obrigado, fico feliz por você gostar dos meus artigos.. :)

      Quanto à sua questão, eu não consegui entender muito bem.. O comportamento normal das linhas do Tablix é só imprimir uma vez.. Ou seja, uma vez que a linha foi impressa, ela não será impressa novamente na outra página.. Ou você está falando de linhas estáticas do cabeçalho da sua Tablix e/ou agrupamento? Você poderia explicar melhor a estrutura do seu relatório (se possível com screenshots) para eu conseguir entender direitinho?

      Abraço!
      André Lima

      • Mariana disse:

        Oi, André, desculpe não ter sido muito clara.
        Eu tenho um agrupamento principal de umas 15 linhas. A última linha antes do Detalhe é tipo um cabeçalho das colunas do Detalhe, assim:

        Linha
        Linha
        Linha
        Cabeçalho detalhe
        Detalhe

        Esse Cabeçalho Detalhe precisaria se repetir em todas as páginas, mas o ReportViewer não permite que eu marque RepeatOnNewPage=true só para essas linhas. Então eu pensei em criar uma linha dentro da Tablix, no topo dela, mas fora do agrupamento para poder setar essa propriedade para true. Beleza, eu consigo fazer isso, mas essa linha não pode aparecer na primeira página, só a partir da segunda.
        Eu já tentei colocar essa linha no cabeçalho do relatório, mas não posso porque o cabeçalho é um canhoto de assinatura de recebimento. Sem contar que, se eu coloco no cabeçalho, quando eu escondo o TextBox na primeira página, o espaço reservado para ele continua visível e os clientes reclamaram muito desse espaço em branco.
        Fazer o que, cliente é cliente rsrsrs
        Espero ter sido mais clara dessa vez :)

        • andrealveslima disse:

          Olá Mariana!

          Eu tentei montar um cenário simulando o seu relatório e eu consegui setar o RepeatOnNewPage somente no cabeçalho do agrupamento sem problema nenhum.. É só selecionar o item “(Static)” correspondente ao cabeçalho do agrupamento e setar a propriedade normalmente:

          Como é que você fez no seu relatório?

          Abraço!
          André Lima

          • Mariana disse:

            No meu relatório, todas as linhas estão dentro do agrupamento do tablix. Por exemplo:

            [Inicio do agrupamento principal]
            Linha
            Linha
            Linha
            Cabeçalho da linha Detalhe
            Linha Detalhe
            [Fim do agrupamento principal]

            Quando tento setar RepeatOnNewPage=true para uma linha que esteja no meio do agrupamento, me dá o seguinte erro:

            tablix possui um TablixMember inválido. TablixMember deve ter o mesmo valor definido para a propriedade RepeatOnNewPage que aqueles que seguem ou precedem TablixMember dinâmico. (Valor Esperado: “False”; Valor Real: “True”)

            Só que as linhas anteriores não podem repetir em todas as páginas, só a linha que eu determinei como cabeçalho da linha detalhe.

          • andrealveslima disse:

            Olá Mariana!

            Por mais confuso que pareça, configure as propriedades das linhas conforme descrito nesta thread do StackOverflow, aí vai funcionar:

            SSRS 2008: How to repeat on new page one row of table header

            Resumindo.. Para as linhas antes do cabeçalho (representadas como “Linha” na descrição que você me enviou no seu último comentário), configure as propriedades:

            KeepTogether = False, KeepWithGroup = None, RepeatOnNewPage = True

            Para a outra linha (“Cabeçalho da linha detalhe” – que deve sempre ser repetida), configure desta maneira:

            KeepTogether = True, KeepWithGroup = After, RepeatOnNewPage = True

            Abraço!
            André Lima

  • Valdir Dias disse:

    Boa tarde.
    Gostaria de uma ajuda, estou tentando contrauir uma expressão no reporting services e estou com difculdade em contruir corretamente.

    Tenho dois campos, um com valor(sum) e um campo de texto, estou tentando construir uma expressão para somar o campo com valor, somente quando o campo texto estiver preenchido. Contriu um IIF mas nao esta dando certo pode me ajudar por favor, veja como ficou a expressão.

    =IIf(Fields!tim_id_projeto_nro Is Nothing,”No Value”,Sum(fields!tim_quantidade_acesso))

    • andrealveslima disse:

      Olá Valdir!

      Não sei se você já conseguiu resolver esse problema, mas aparentemente a sua expressão está correta.. Quando você diz “não está dando certo”, o que acontece exatamente? Dá um erro? Ou o resultado não condiz com o que você estava querendo? Caso você esteja recebendo um erro, você já tentou dar uma olhada na janela de output do Visual Studio para ver se não tem uma mensagem de erro mais detalhada?

      Abraço!
      André Lima

  • josué disse:

    Muito bom André, estou precisando da sua ajuda, estou com um relatório que me dá um total bruto,um valor a ser descontado e o liquido a receber.Eu queria que quando o saldo fosse negativo aparecesse o – e a fonte em vermelho e também uma condição para que quando o valor fosse negativo a caixa de texto mudasse de “valor liquido a receber ” para “saldo devedor”

    • andrealveslima disse:

      Olá Josué!

      Cara, isso você consegue com expressões nas propriedades correspondentes mesmo.. A fonte em vermelho você configura no ForeColor, o texto você cria uma expressão para o TextBox.. Pelo que você disse, dá para fazer tudo com expressões “IIF” mesmo.. A ideia é “=IIF(Campo < 0, "Saldo devedor", "Valor líquido a receber")".. E por aí vai.. Você tentou construir as expressões? Em qual parte você ficou com dúvida exatamente? Abraço! André Lima

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *