André Alves de Lima

Talking about Software Development and more…

Somatório de horas no Report Viewer

Se você já precisou somar horas no Report Viewer, muito provavelmente você teve que fazer alguma gambiarra. Se tentarmos somar campos do tipo DateTime ou TimeStamp, o resultado não será o esperado. Dessa forma, temos que fazer esse tipo de somatório de horas no Report Viewer “na mão“.

No vídeo de hoje eu mostro para você o jeito menos “gambiarrado” de se implementar esse tipo de somatório, onde convertemos toda a informação em segundos, somamos e depois formatamos o resultado adequadamente. Veja só o resultado no vídeo de hoje:

Como armazenamos informações de horas?

Quando temos que armazenar informações relacionadas a horas, eu consigo visualizar três alternativas:

Campos DateTime: considerando somente a parte das horas, minutos e segundos, ignorando o conteúdo da data em si
Campos TimeSpan: na minha opinião é a melhor estrutura para armazenar um intervalo de tempo, afinal, é justamente para isso que essa classe foi criada
Campos decimais: o horário é convertido em horas decimais, onde, por exemplo, o valor 2.5 corresponderia a duas horas e meia

Tendo como base essa realidade, eu preparei um relatório extremamente simples com informações de horas nesses três formatos:

A estratégia de sumarização de horas

Para fazermos o somatório de horas no Report Viewer, nós seguiremos uma estratégia muito simples. Primeiro nós converteremos as informações de horas em segundos. Depois, nós adicionaremos esse total de segundos em um DateTime com base “zero horas“. Com isso nós teremos a quantidade de horas, minutos e segundos, porém, nós perderemos a informação de dias, caso o total passe de 24 horas.

O cálculo da quantidade de dias pode ser feito dividindo a mesma somatória de segundos que utilizamos no passo anterior pela quantidade de segundos presentes em um dia (86400 segundos). Se pegarmos a parte inteira dessa divisão, teremos a quantidade de dias!

Somando horas decimais

Vamos começar com o somatório de horas decimais. Nesse caso, como temos que converter a informação para segundos, nós multiplicaremos tudo por 3600 (que é a quantidade de segundos presentes em uma hora). Em seguida, nós adicionamos esse total de segundos em um DateTime “zero hora” através da função “DateAdd“. Por fim, nós calculamos a quantidade de dias dividindo a somatória de segundos por 86400 e considerando somente a parte inteira através da função “Floor“.

Veja só como é que fica a expressão:

=Floor(Sum(Fields!HorasDecimal.Value) * 3600 / 86400) & ":" & Format(DateAdd("s", Sum(Fields!HorasDecimal.Value * 3600), "00:00:00"), "HH:mm:ss")

Somando TimeStamps

Para somarmos horas que estejam armazenadas em TimeStamps, o processo é um pouco mais simples, uma vez que nós temos a propriedade “TotalSeconds” que já retorna a quantidade total de segundos do TimeStamp. Apesar dessa propriedade não aparecer no IntelliSense, ela está disponível em tempo de execução e conseguimos utilizá-la sem problema algum. Nesse caso, a expressão fica assim:

=Floor(Sum(Fields!HorasTimeSpan.Value.TotalSeconds) / 86400) & ":" & Format(DateAdd("s", Sum(Fields!HorasTimeSpan.Value.TotalSeconds), "00:00:00"), "HH:mm:ss")

Somando DateTimes

O somatório de informações do tipo DateTime é muito parecido com o somatório de TimeStamps, uma vez que a classe DateTime possui a propriedade “TimeOfDay” que é justamente um TimeStamp representando a parte das horas, minutos e segundos do DateTime:

=Floor(Sum(Fields!HorasDateTime.Value.TimeOfDay.TotalSeconds) / 86400) & ":" & Format(DateAdd("s", Sum(Fields!HorasDateTime.Value.TimeOfDay.TotalSeconds), "00:00:00"), "HH:mm:ss")

E com isso temos o somatório de horas no Report Viewer tanto com DateTime quanto TimeStamp e valores decimais:

Baixe o projeto de exemplo

Para baixar o projeto de exemplo desse artigo, assine a minha newsletter. Ao fazer isso, além de ter acesso ao projeto, você receberá um e-mail toda semana sobre o artigo publicado e ficará sabendo também em primeira mão sobre o artigo da próxima semana, além de receber dicas “bônus” que eu só compartilho por e-mail. Inscreva-se utilizando o formulário no final do artigo.

Concluindo

Apesar do Report Viewer não ter suporte nativo ao somatório de horas, você viu neste vídeo que esse tipo de sumarização é totalmente implementável utilizando algumas conversões e cálculos. Se convertermos todas as informações para segundos e depois adicionarmos o total em um DateTime “zero hora“, nós teremos o resultado esperado, independentemente da estrutura de dados que você estiver utilizando para armazenar as horas, seja DateTime, TimeStamp ou valores decimais.

E você, já precisou somar horas no Report Viewer? Como é que você acabou saindo dessa situação? Você utilizou exatamente essas fórmulas ou acabou fazendo de alguma outra maneira diferente? Conte-nos mais detalhes na caixa de comentários logo abaixo!

Até a próxima!

André Lima

Newsletter do André Lima

* indicates required



Powered by MailChimp

4 thoughts on “Somatório de horas no Report Viewer

  • André Bononi disse:

    Olá, André.

    Parabéns pelo post. Já desenvolvi alguns projetos de cartão de ponto e estou, justamente, neste momento, desenvolvendo um outro, onde utilizarei dicas de um outro artigo seu (Tirando fotos com a WebCam em C#) e estava justamente pensando qual seria a melhor maneira de guardar os dados das horas.

    Seu artigo, mais uma vez, veio bem a calhar! Acreito que utilizar o Timespan seja o melhor caminho.

    Vou analisar esta situação e encaixar suas dicas.

    Valeu! Abraços!!!

    • andrealveslima disse:

      Olá André! Mais uma vez, muito obrigado! :)

      Eu também acho que o TimeSpan é a melhor estrutura para armazenar horas.. Se não der para armazenar em TimeSpan, eu armazenaria em decimal.. Só utilizaria DateTime em último caso..

      Enfim, se ficar com alguma dúvida quando você for implementar essa funcionalidade, é só falar..

      Abraço!
      André Lima

  • Carlos Alberto disse:

    Olá André. Parabéns pelo vídeo. Muito bem explicado e esclarecedor como sempre!

Deixe uma resposta

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