3 08 2016
Atualizando um relatório do Report Viewer de tempos em tempos
Imagine que você tenha um relatório de dashboard no seu sistema e que você queira que esse relatório seja automaticamente atualizado de tempos em tempos. Pode ser que esse relatório fique 100% do tempo aberto em uma tela separada e que ele seja crucial para detectar irregularidades no processo. E aí, será que é possível atualizarmos um relatório do Report Viewer de tempos em tempos? É sim! Só precisamos utilizar um Timer. E isso é o que eu vou mostrar para você no artigo de hoje.
Criando o projeto de exemplo
Primeiramente, vamos criar um projeto para demonstrarmos essa funcionalidade. Para facilitar, criaremos um projeto do tipo “Windows Forms Application“, porém, saiba que podemos utilizar o Report Viewer no WPF, no WebForms e até mesmo no MVC. A mesma ideia que eu vou apresentar neste artigo para o Windows Forms se aplicaria para qualquer plataforma que você escolher.
Uma vez criado o projeto, vamos adicionar um novo DataSet tipado que servirá de fonte de dados para o relatório que iremos criar. Dê o nome de “DataSetDashboard” para esse novo DataSet e, dentro dele, adicione uma DataTable chamada “Dashboard“, contendo duas colunas (“NomeProduto” e “ValorVendido” – sendo que a coluna “ValorVendido” deve ser do tipo “Decimal“):
Em seguida, vamos criar um relatório muito simples com um gráfico de vendas por produto. Dê o nome de “RelatorioDashboard” para o novo relatório, adicione um gráfico e configure-o de forma que ele fique parecido com a imagem abaixo:
Nota: não vou entrar em detalhes sobre a criação de gráficos neste artigo. Se você tiver dúvidas, confira o artigo super-detalhado que eu escrevi uns tempos atrás sobre a criação de gráficos nos relatórios do Report Viewer.
Com o relatório criado, agora chegou a hora de exibi-lo no formulário. Para isso, arraste um controle do Report Viewer para dentro do formulário e configure-o para que ele exiba o relatório que acabamos de criar. Em seguida, no code-behind, vamos criar um método para adicionarmos informações aleatórias no DataSet do relatório:
// C# Random _rnd = new Random(); private void AdicionarInformacaoAleatoria() { var produtos = new string[] { "Produto 1", "Produto 2", "Produto 3" }; var produto = produtos[_rnd.Next(3)]; var valor = (decimal)_rnd.Next(10000) / (decimal)10; DataSetDashboard.Dashboard.AddDashboardRow(produto, valor); }
' VB.NET Private Rnd As New Random Private Sub AdicionarInformacaoAleatoria() Dim Produtos = New String() {"Produto 1", "Produto 2", "Produto 3"} Dim Produto = Produtos(Rnd.Next(3)) Dim Valor = CDec(Rnd.Next(10000)) / CDec(10) DataSetDashboard.Dashboard.AddDashboardRow(Produto, Valor) End Sub
Obviamente, esse método não seria necessário em um sistema “de verdade“. Nesse caso, você teria que carregar os dados do banco para dentro do DataSet. De qualquer forma, vamos utilizar esse método de geração de dados aleatórios para termos um conjunto de dados de exemplo neste artigo.
Em seguida, vamos chamar esse método quatro vezes no construtor do formulário para gerarmos alguns dados que serão exibidos pelo relatório:
// C# public FormDashboard() { InitializeComponent(); AdicionarInformacaoAleatoria(); AdicionarInformacaoAleatoria(); AdicionarInformacaoAleatoria(); AdicionarInformacaoAleatoria(); }
' VB.NET Public Sub New() ' This call is required by the designer. InitializeComponent() ' Add any initialization after the InitializeComponent() call. AdicionarInformacaoAleatoria() AdicionarInformacaoAleatoria() AdicionarInformacaoAleatoria() AdicionarInformacaoAleatoria() End Sub
Execute o projeto e veja que um gráfico com dados aleatórios será exibido:
Atualizando o relatório de tempos em tempos
Agora que já temos o nosso relatório criado e sendo exibido no formulário, vamos conferir como podemos atualizá-lo de tempos em tempos. Por questões didáticas, vamos fazer uma atualização a cada um segundo. Pelos testes que eu fiz, o controle do Report Viewer não apresenta problemas de memória mesmo se atualizado em intervalos muito pequenos. Porém, eu recomendo que você evite utilizar intervalos muito baixos para não prejudicar a experiência do usuário (afinal de contas, uma tela piscando a cada segundo para atualizar os dados do relatório não é nem um pouco amigável.
Para atualizarmos o relatório de tempos em tempos, temos que utilizar um timer. Vamos declarar o timer no nível do formulário e vamos configurá-lo diretamente no construtor, setando o intervalo desejado (mil milisegundos, ou seja, um segundo) e ajustando o hook para o evento “Tick“:
// C# Timer _timer = new Timer(); public FormDashboard() { InitializeComponent(); AdicionarInformacaoAleatoria(); AdicionarInformacaoAleatoria(); AdicionarInformacaoAleatoria(); AdicionarInformacaoAleatoria(); _timer.Interval = 1000; _timer.Tick += Timer_Tick; } private void Timer_Tick(object sender, EventArgs e) { }
' VB.NET Private Timer As Timer Public Sub New() ' This call is required by the designer. InitializeComponent() ' Add any initialization after the InitializeComponent() call. AdicionarInformacaoAleatoria() AdicionarInformacaoAleatoria() AdicionarInformacaoAleatoria() AdicionarInformacaoAleatoria() Timer.Interval = 1000 AddHandler Timer.Tick, AddressOf Timer_Tick End Sub Private Sub Timer_Tick(sender As Object, e As EventArgs) End Sub
Dentro do handler do evento “Tick“, teríamos que colocar o código para recarregar o DataSet e atualizar o relatório. No nosso exemplo, para conseguirmos sentir que os dados estão realmente sendo alterados, nós vamos adicionar mais um dado aleatório no DataSet a cada tick do Timer:
// C# private void Timer_Tick(object sender, EventArgs e) { AdicionarInformacaoAleatoria(); this.reportViewer1.RefreshReport(); }
' VB.NET Private Sub Timer_Tick(sender As Object, e As EventArgs) AdicionarInformacaoAleatoria() Me.ReportViewer1.RefreshReport() End Sub
Feito isso, a única coisa que está faltando fazer é iniciarmos o Timer através do seu método “Start“. Faremos isso no evento “Load” do formulário, logo após o primeiro “Refresh” do relatório:
// C# private void FormDashboard_Load(object sender, EventArgs e) { this.reportViewer1.RefreshReport(); _timer.Start(); }
' VB.NET Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load Me.ReportViewer1.RefreshReport() Timer.Start() End Sub
Execute o projeto e veja só que legal fica o relatórios sendo atualizado a cada segundo:
Escondendo a barra de ferramentas
Muito provavelmente esse tipo de atualização automática só será útil para relatórios de dashboard, que serão exibidos em uma tela o tempo todo. Nesses casos, não faz muito sentido que a barra de ferramentas do Report Viewer fique visível. Para ocultá-la, basta configurarmos a propriedade “ShowToolBar” como “False“:
Finalizando o temporizador quando o formulário é fechado
Uma coisa importante que não devemos esquecer é finalizarmos o Timer no momento do fechamento do formulário. Caso contrário, pode ser que o Timer dispare quando o formulário já está destruído, causando uma exception na aplicação. Para isso, vamos fazer um “override” do método “OnClosing” do formulário e vamos finalizar o Timer através do seu método “Stop“:
// C# protected override void OnClosing(CancelEventArgs e) { _timer.Stop(); base.OnClosing(e); }
' VB.NET Protected Overrides Sub OnClosing(e As CancelEventArgs) Timer.Stop() MyBase.OnClosing(e) End Sub
Concluindo
A atualização automática de relatórios do Report Viewer de tempos em tempos pode ser útil em diversos cenários. O mais comum deles é quando queremos deixar um relatório de dashboard rodando em uma tela separada. No artigo de hoje você viu como utilizar um Timer para implementar essa atualização automática.
Você já precisou deixar um relatório rodando em uma tela dedicada? Caso positivo, você implementou algum mecanismo de atualização automática? Como você fez para atualizar o relatório de tempos em tempos? Deixe os detalhes na caixa de comentários abaixo.
Por fim, convido você a inscrever-se na minha newsletter. Ao fazer isso, 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 logo abaixo.
Até a próxima!
André Lima
Image by Pixabay used under Creative Commons
https://pixabay.com/en/stopwatch-time-clock-1082661/
Windows Forms ou WPF? Qual utilizar? Imprimindo conteúdo do DataGridView no Crystal Reports