Visual Basic em Português

Página pessoal de Jorge Paulino sobre o Visual Basic (VB.NET, ASP.NET, VB6, VBA) e algumas noticias de tecnologia

VB.NET: Microsoft Reporting Services

Os Microsoft Reports são baseados na definição do relatório, que é na realidade um ficheiro XML, que descreve a informação e o layout do relatório, com uma extensão diferente. Pode-se criar um relatório no cliente – Client-Side Report Definition Language (*.rldc) – usando o Visual Studio, e construir excelentes relatórios para a aplicação.

O objectivo deste artigo é mostrar os passos básicos para a criação de um relatório, definir a Data Source em modo runtime, trabalhar com Parameters, incluir imagens, usar o Expression Editor, e como alimentar um SubReport e um gráfico. Finalmente irá também mostrar algumas personalizações simples ao controlo ReportViewer.

Introdução

Para começar, foi criada uma tabela em SQL com alguma informação para este exemplo. É uma lista de equipamento electrónico como PDA, computadores, etc. Da tabela criada é necessário criar um DataSet, com duas DataTables. Chamar a este DataSet “dsReport.xsd”.

A primeira DataTable, “products”, contém a lista de todos os produtos na tabela SQL. A segunda DataTable, “groupTotal”, é uma vista agrupada (Group By) com os grupos e os somatórios das quantidades. que serão usados para o SubReport e para o gráfico.

Depois disto é necessário adicionar o relatório à aplicação. Seleccionar o relatório e indicar um nome apropriado. Para o exemplo podem utilizar “rptProducts”.

Com o novo relatório criado e aberto, existe uma nova opção na barra de ferramentas Report. Seleccionar o “Page Header” e “Page footer” para mostrar estas duas secções no relatório. Depois disto vamos arrastar da Toolbox para a secção “Body” (corpo) do relatório.

DataSource

Agora é altura para definir a Data Source. No menu Report, seleccionar Data Source. Irá aparecer uma nova janela onde se pode escolher as Data Sources (DataSets) disponíveis na nossa aplicação. Seleccionar a DataSet criada.

NOTA: O nome do “Report Data Sources” pode ser renomeado, e será usado no código mais tarde.

Depois de definir a Data Source para o relatório, as DataTables estarão disponíveis no Data Source Explorer (normalmente disponível na janela da Soluction Explorer). Da tabela Produtos arrastar as colunas para o objecto Table que foi inserido na secção “Body”


O objecto Table funciona como uma folha de Excel. Pode-se unir células, alterar a cor de fundo, fontes, etc. Este exemplo utiliza um campo do tipo Moeda. Para mostrar como é simples formatar as células, clicar com o botão direito do rato sobre o campo e seleccionar Propriedades. Na janela das propriedade ir à Tab Format e definir a célula com o formato Currency.

 

Alterar o formato dos restantes campos, como negrito, títulos, etc., para obter um aspecto profissional.

Imagens

Para incluir imagens na nossa aplicação, pode-se embeber e depois usar como um logótipo (por exemplo). Pode-se também ir buscar directamente as imagens à base de dados, se estiverem armazenados como binário (Binary).

Para embeber as imagens no relatório é apenas necessário ir ao menu Report e seleccionar Embedded Images. Na nova janela seleccionar o botão New Image e escolher a imagem pretendida.


Fechar a janela e depois, na Toolbox, adicionar um controlo Image ao relatório. Nas propriedades do controlo, seleccionar a imagem adicionada da Combobox disponível na propriedade Value.

Expression Editor

Uma das novidades do Visual Studio 2008 para o Microsoft Reporting Services Expression Editor é o intellissense disponível quando se precisa de criar alguma fórmula ou expressão.

Na secção Footer, pode-se adicionar duas TextBoxes. Numa delas, iremos colocar o número da pagina e o total de páginas. Para isso, já existem fórmulas criadas na categoria Global.


Como se pode ver na imagem seguinte, pode-se usar fórmulas de VB (a maioria delas) no Expression Editor. O intellissence ajuda bastante para prevenir erros e para lembrar o sintaxe das fórmulas . Na segunda Textbox vamos colocar simplesmente a data de impressão.

 

Parâmetros (Parameters)

Pode-se utilizar Parameters para diversas coisas. Neste exemplo será apenas usado para passar informação da aplicação para o relatório.

No menu Report, seleccionar Report Parameters. Definir dois parâmetros: “ApplicationUser” e “ApplicationLevel” do tipo String.

Depois, no relatório, pode-se usar o Expression Editor para definir os parâmetros (eles serão definidos no código) para as TextBoxes. Eles estarão disponíveis na categoria Parameters.

Gráficos (Chart)

Pode-se usar vários gráficos no relatório e eles são muito fáceis de usar e alimentar com informação.

Adicionar um controlo Chart da Toolbox para a secção Body do relatório. Efectuar um duplo-clique no gráfico e irá mostrar as áreas “Data Field” e “Category Field”.

Arrastar os campos “Group” e Totals” da janela DataSource Explorer.


Pode-se também fazer isto nas propriedades do gráfico. Nesta janela pode-se também personalizar as cores das séries, legendas, efeitos 3D, filtros, eixos, etc.

Usando o código

Nos passos anteriores, foram usadas diversas Data Sources no relatório. Agora, iram ser adicionadas novas Data Sources, filtradas ou não, e essa será a informação que será visível no relatório.

Imports System.Data.SqlClient
Imports Microsoft.Reporting.WinForms

Public Class Form1

    ' Connection string
  
Private connString As String = _ 
"DataSource=.\SQLEXPRESS;AttachDbFilename='|DataDirectory|\myDatabase.mdf'”_
";
Integrated Security=True;User Instance=True"

  
''' <summary>
  
''' Evento Form load
    '''
</summary>
  
Private Sub Form1_Load(ByVal sender As Object, _
                                   ByVal e As System.EventArgs) Handles Me.Load

        Try

          
' Chama a personalização
          
Call customizeReportViewer(Me.ReportViewer1)

            ' Adiciona um novo botão
          
Call AddReportViewerButton()

            With Me.ReportViewer1.LocalReport

                ' Caminho para o relatório
              
.ReportPath = Application.StartupPath & "\..\..\rptProducts.rdlc"
              
.DataSources.Clear()

                ' Define os parameters
              
Dim parameters(1) AsReportParameter
                parameters(0) = _
                         New ReportParameter("ApplicationUser", "jpaulino")
                parameters(1) = _
                         New ReportParameter("ApplicationLevel", "Administrator")

                .SetParameters(parameters) 
            End With

          
' ----------------------------------------------------
            ' Datasource para o relatório principal (where price > 200)
            ' ----------------------------------------------------
          
Dim SQL As String = "SELECT * FROM products WHERE price > @price"
          
Using da As New SqlDataAdapter(SQL, connString)
                da.SelectCommand.Parameters.Add("@price", SqlDbType.Int).Value = 200

                Using ds As New DataSet
                    da.Fill(ds, "products")

                    ' É preciso usar o mesmo nome como foi de definido 
                    ' no Data Source Definition
                  
Dim rptDataSource As New ReportDataSource _
                                          ("dsReport_products", ds.Tables("products"))
                    Me.ReportViewer1.LocalReport.DataSources.Add(rptDataSource)

                End Using

            End Using

          
' ----------------------------------------------------
            ' Datasource para o gráfico
            ' ----------------------------------------------------
          
Dim SQL_Chart As String = "SELECT [group], SUM(quantity) AS " _ 
                   “
Total FROM products GROUP BY [group]"
          
Using da As New SqlDataAdapter(SQL_Chart, connString)
                Using ds As New DataSet
                    da.Fill(ds, "groupTotal")

                    Dim rptDataSource As New ReportDataSource("dsReport_groupTotal", _
    ds.Tables("groupTotal"))
                    Me.ReportViewer1.LocalReport.DataSources.Add(rptDataSource)

                End Using
            End Using


          
' Refresh do relatório
          
ReportViewer1.RefreshReport()


        Catch ex As Exception
            MessageBox.Show(ex.Message, My.Application.Info.Title, _
                                              MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try

    End Sub

End Class

SubReports

Pode-se usar um ou vários subreports no relatório. Para fazer isso, é necessário preencher a Data Source para cada um deles. Uma vez que não se pode aceder directamente à Data Source do relatório, é preciso definir um evento (handler) ao SubreportProcessing, e depois quando o relatório está a ser carregado, recolhe-se a informação da base de dados e preenche-se a Data Source.

Pode parecer difícil de fazer, mas na verdade é bastante simples!

Definir a Data Source para o subreport e usar um objecto Table, como no relatório principal. Adicionar os campos ao objecto Table. No relatório principal, adicionar um objecto SubReport da Toolbox e escolher o subreport criado.

Depois, no evento Form Load onde está o relatório principal, adicionar o evento para o SubreportProcessing.


AddHandler
ReportViewer1.LocalReport.SubreportProcessing, _
                  AddressOf SubreportProcessingEvent

Finalmente, no evento SubreportProcessing, define-se a nova Data Source, da mesma maneira dos anteriores.


 ''' <summary>
''' Quando o subreport está a ser carregado/processado, preenche a DataSource
''' 
</summary>
Sub SubreportProcessingEvent(ByVal sender As Object, _
                                         ByVal e As SubreportProcessingEventArgs)

     Try

         Dim
SQL As String = "SELECT [group], SUM(quantity) AS " _
             “
Total FROM products GROUP BY [group]"
        
Using da As New SqlDataAdapter(SQL, connString)
             Using ds As New DataSet
                 da.Fill(ds, "groupTotal")
                 Dim rptDataSource As New ReportDataSource _
                                           ("dsReport_groupTotal", ds.Tables("groupTotal"))
                 e.DataSources.Add(rptDataSource)
             End Using
         End Using

     Catch
ex As Exception
         MessageBox.Show(ex.Message, My.Application.Info.Title, _ 
                                      MessageBoxButtons.OK, MessageBoxIcon.Error)
     End Try

End Sub

Personalização do ReportViewer

O ReportViewer é o controlo que mostra os Microsoft Reports num Form ou numa Webpage. Pode-se personalizar a maioria dos controlos deste, para melhorar ou personalizar como pretendido.

Neste artigo, será mostrado duas personalizações simples.

Primeiro, pode-se alterar os títulos dos controlos. Pode-se também fazer outras coisas, como desabilitar itens, renomear tooltips, etc. Isto é especialmente interessante para alterar a linguagem do controlo, uma vez que está disponível apenas em Inglês.

Para isto, será criado um método recursivo que irá fazer um ciclo em todos os controlo do ReportViewer e fazer algumas alterações.

'''  <summary>
''' Ciclo em todos os controlos do ReportViewer
'''
</summary>
''' <remarks></remarks>
Sub customizeReportViewer(ByVal ctrl AsControl)

    For Each c As Control In ctrl.Controls

        ' ----------------------------------------------------
        ' Verifica o texto das labels disponíveis 
        ' ----------------------------------------------------
      
If TypeOf c Is Label Then
            Dim
lbl As Label = DirectCast(c, Label)
            Select Case lbl.Name
                Case "LblGeneratingReport"
                  
lbl.Text = "My report is loading now ... "
              
Case Else
                  
' Podem ser adicionadas mais personalizações
          
End Select
        End If

      
' ----------------------------------------------------
        ' Altera os textos da ToolStrip para Português
        ' ----------------------------------------------------
      
If TypeOf c Is ToolStrip Then
            Dim
ts AsToolStrip = DirectCast(c, ToolStrip)
            For Each item AsToolStripItem In ts.Items

                Select Case item.Text
                    Case "Find"
                      
item.Text = "Pesquisar"
                  
Case "Next"
                      
item.Text = "Próximo"
                  
Case "of"
                       
item.Text = "de"
                    
Case Else
                       
' Podem ser adicionadas mais personalizações
              
End Select
            Next
        End If

      
' Se o controlo tiver child controls
       
If c.HasChildren Then
          
customizeReportViewer(c)
        End If

    Next

End Sub

Finalmente é apenas necessário chamar o método criado no evento Form Load, onde se encontra o ReportViewer.

   ' Chama o método criado
Call customizeReportViewer(Me.ReportViewer1)

A segunda personalização mostra como incluir um novo botão na Toolstrip. Irá encontrar a ToolStrip principal do relatório e adicionar um botão alinhado à direita.

'''  <summary>
'''  Encontra a ToolStrip principal e adiciona um novo botão alinhado à direita
'''
</summary>
Sub AddReportViewerButton()

    Dim ts() As Control = Me.ReportViewer1.Controls.Find("toolStrip1", True)
    If ts IsNot Nothing Then
        Dim
tsItem As ToolStrip = DirectCast(ts(0), ToolStrip)
        Dim item As New ToolStripButton
        item.Name = "newButton"
       
item.Text = "New Button"
       
item.BackColor = Color.Green
        item.ForeColor = Color.White
        item.Alignment = ToolStripItemAlignment.Right

        tsItem.Items.Add(item)

        AddHandler item.Click, AddressOf newButtonClick
   End If

End Sub

Quando o botão for pressionado:

'''  <summary>
''' Mostra uma mensagem quando o botão no ReportViewer for pressionado
''' 
</summary>
Sub newButtonClick()
    MessageBox.Show("This is my new button!")
End Sub


Este artigo mostra os primeiros passo, e os mais importantes, para usar os Microsoft Reports, e como utilizar o código. Espero que isto ajude a utiliza-los e mostrar como é simples trabalhar com eles.


Download do Exemplo

12 comentários:

Anónimo disse...

Nossa foi otimo, ajudo muito mesmo, e aprendi umas coisas que não sabia. vlwww.

Anónimo disse...

Parabens pelo optimo artigo.
Gostaria de saber como repetir em todas as páginas uma tabela com os parâmetros usados na elaboração do relatório.
Por exemplo: se gerar um relatório entre datas e para um dado cliente, o relatório gerado deve indicar em cada pagina estes parâmetros.
Diferentes relatórios usam o mesmo modelo, portanto deveria ter possibilidade de usar sempre a mesma tabela, com as colunas: parametro e valor.
Obrigado!

Jorge Paulino disse...

Olá,

Pelo que me está a dizer é só colocar um parametro no footer e passar uma string com a definição do filtro.

Estarei certo?

Anónimo disse...

estou a tentar fazer utilizando um dataset com duas views como datatables. é possível? e como é que tenho que definir o campo de ligação?

Jorge Paulino disse...

Olá,

Sim é possível, só tens de definir as duas views como DataSource do report e depois no código indicar no código as duas ReportDataSources que vais utilizar.

Podes utilizar várias datasources no mesmo relatório.

Anónimo disse...

Antes de mais gato pelo resposta rápida. o que pretendo então é tipo colocar o cabeçalho da factura e depois as linhas ligadas ao cabeçalho pelo número.

publisher disse...

Ola,

muito boa a explicação.

Gostaria de saber como fazer para fazer um relatorio tipo um extrato bancario. Ou seja, que inclua o valor a transportar quando é mais de uma folha e ainda o saldo inicial.

obrigado

Anónimo disse...

Boa tarde!


Eu testei no microsoft visual studio 2010 ultimate e, infelizmente, não funcionou! Você sabe se houve alguma mudança nos cimandos? Obrigado

Fabio.

Anónimo disse...

Agora consegui. Muito bom mesmo! Parabéns!

Cristiano Gossmann disse...

Bom Dia,... executei os passos conforme vc indicou, e sempre aparece falha ao recuperar dados do sub-report... o que pode ser isso????

Anónimo disse...

Cara este post me ajudou muito! Obrigado.

Anónimo disse...

Bom dia a todos.

Seria possível desenvolver alguma coisa parecida com o Report Builder 3.0 SQL?
- Desenhar o relatório RB e depois chamá-lo pelo VB.NET passando parâmetros de seleção e/ou critérios específicos.?
- Quando chamar o relat., fazer aparecer somente o relatório pronto, e não junto com o RB acionado.
Agradeço a colaboração.
Paulo.

Mensagens Recentes



Microsoft Office Especialist

Membro da Comunidade
Experts-Exchange


Administ. da Comunidade
Portugal-a-Programar



Twitter

Artigos no CodeProject

Artigos no CodeProject

Subscrever Novidades

Endereço de Email:

Delivered by FeedBurner

Seguidores

Histórico