Asp.Net - Relatório Mestre-Detalhe com ReportViewer


Este é um assunto muito requisitado em nosso suporte técnico, não apenas em se tratando de relatórios e sim exemplos envolvendo cadastros e consultas utilizando esta técnica.

Para quem não sabe, Mestre-Detalhe é a Típica Entidade Relacionamento “Um para Muitos”. Mestre é o registro que existe por si só, já o detalhe necessita de um “Mestre” para poder existir.

Podemos realizar esta tarefa sem muitos esforços utilizando o gerador de Relatórios ReportViewer junto com o Microsoft Visual Studio 2010. O intuito deste artigo será de descrever  todas as etapas envolvendo um exemplo básico de Pedido de Venda utilizando como Banco de Dados o Microsoft SQL Server 2008 com a base de dados padrão “NorthWind”.

 

Tabelas Utilizadas


Para exemplificar melhor, nos próximos passos montarei um Modelo (Entidade Relacinamento –ER) utilizando a ferramenta SQL Server Management Studio do próprio SQL Server 2008.
Usamos como base uma Tabela de Pedido (Orders) se relacionando com outra de itens (OrderDetail), fechando um relacionamento Mestre-Detalhe. Relacionamos também com a tabela de Clientes (Customers) e de Produtos (Products). Iremos recuperar os dados através de uma Instrução SQL envolvendo todas estas tabelas citadas.
Ver Imagem 01 para maiores detalhes.


Figura 01: Modelo Entidade Relacionamento (ER) das tabelas envolvidas.

 

 

Montando um exemplo


Para Isto abra o Microsoft Visual Studio clicando em “File/New/Web Site...” para assim criarmos uma página web do zero.

1-) Definindo a fonte de Dados

A fonte de dados nada mais é do que a origem e a forma como os dados serão coletados para podermos trabalhar com eles. Clique com o botão direito sobre a solução e escolha “Add New Item...”. Localize o item “Dataset” e defina um nome para este objeto, por exemplo: “dsMestreDetalhe”. Notem que foi criada uma pasta “App_Code” e dentro dela um arquivo do tipo “.xsd”. Geralmente dentro desta pasta é onde armazenamos estes ou outros tipos de arquivos, como por exemplo do tipo classe (.cs). Dê um duplo clique para podermos definir a fonte de dados.

Importante salientar que na região esquerda da tela aparecerá uma ToolBox.

Ver Imagem 02.


Figura 02: ToolBox.

Para trabalhar com relatórios existem diversos tipos de componentes, eu recomendo a utilização do “TableAdapter”, nele conseguimos configurar tudo o que precisamos no quesito de instruções SQL. Arraste-o na tela e seguiremos os passos adiante. Na tela “Choose your data Connection” é o local onde escolhemos a conexão, Ver Imagem 03.

Figura 03: Tipo de Conexão.

Já na próxima etapa denominada “Choose a Command Type”, é o local onde definimos o modo como o tableAdapter irá acessar a Base de Dados. Possuímos três opções, sendo:

- Uso de Instruções SQL;
- Criar Stored Procedures;
- Usar Stored Procedures.

Escolha a primeira opção e clique em “Next”. Ver Imagem 04.

Figura 04: Acesso a Base de Dados.

Faremos uma Instrução SQL baseada no diagrama disposto logo no início do artigo (Figura 01). Parametrizamos pelo “OrderID” (Número do Pedido) utilizando a cláusula “Between” (intervalo de valores) .

SELECT
Customers.CompanyName, Orders.OrderID, Orders.RequiredDate, Products.ProductName, OrderDetails.ProductID, OrderDetails.UnitPrice,
OrderDetails.Quantity
FROM Orders
INNER JOIN Customers ON Customers.CustomerID = Orders.CustomerID
INNER JOIN OrderDetails ON OrderDetails.OrderID = Orders.OrderID
INNER JOIN Products ON Products.ProductID = OrderDetails.ProductID
WHERE (Orders.OrderID BETWEEN @COD_INI AND @COD_FIM)

A tabela a seguir nos mostra o significado dos campos utilizados.

Campos

Significado

CompanyName

Nome do Cliente

OrderID

Número do Pedido Venda

RequiredDate

Data Requisição

ProductName

Nome do Produto

ProductID

Código do Produto

UnitPrice

Preço Unitário

Quantity

Quantidade

 

Podemos também montar instruções SQL com o auxílio do “Query Builder”, sem nenhuma codificação.  Ver Image 05.

 

 

Figura 05: Instrução SQL.

O “TableAdapter” deverá ficar idêntico ao da Figura 06.


Figura 06: TableAdapter “DsMestreDetalhe”.

2-) Definindo o Lay-out do Relatório

- Criando Parâmetros

Crie um arquivo do tipo “.rdlc” e o nomeie como “RptMestreDetalhe”. O passo inicial da nossa tarefa é definir alguns parâmetros como por exemplo: o Título e o SubTítulo, para isto clique no menu “View/Report Data”. Na pasta “Parameters” clique como o botão direito e escolha “Add Parameter...”. Na aba “General” defina em “Name” como “ParamTitulo” e em “Data type” como “text”. O restante deixaremos como padrão, clique em OK para concluir este processo. Os mesmos passos descritos deverão ser realizados para o parâmetro “SubTítulo”. Ver Imagem 07.

Figura 07: Criando Parâmetros.

No Cabeçalho do relatório adicione dois componentes “textBox” contendo os seguintes valores:

Título:

=Parameters!ParamTitulo.Value

Subtítulo:

=Parameters!ParamSubtitulo.Value

 

Esta é a referência dos parâmetros que iremos passar mais adiante através do Preview do relatório.

- Criando o agrupamento

No corpo insira um “Table” e na propriedade “DataSetname” deixe como DsMEstreDetalhe. Para adicionar um grupo clique com o botão direito sobre a linha “Data” e escolha “Add Group/Parent Group”. Ver Imagem 08.

 
Figura 08: Adicionando o Agrupamento.

Na Janela “Tablix group” escolha “Group by: [OrderID]” para agrupar por “orderID” e cheque os valores “Add group header” e “Add group footer”, significando respectivamente para adicionar cabeçalho e rodapé para o grupo. Ver Imagem 09.

Figura 09: Tablix Group.

Um detalhe importante é que a linha que contém os dados a serem agrupados possui um leve tracejado. (=) . Montaremos um lay-out contendo no cabeçalho os dados: “RequiredDate” e “CompanyName”. No corpo inserimos o “ProductID”, “ProductName”, “UnitPrice”, “Quantity” e um campo calculado com o “Total”, já no rodapé a soma total dos Produtos. Ver Lay-out proposto na Figura 10.


Figura 10: Relatório em desenvolvimento.

- Formatação de Valores

Em se tratando de relatórios, sempre utilizamos a formatação de campos a fim de dar um visual mais atraente ao usuário, como por exemplo uma máscara numérica ou de Data. Veja exemplos a seguir:

Máscara Numérica:

=format(Fields!UnitPrice.Value,"###,###,##0.00").tostring()


Máscara Data:

=format(Fields!RequiredDate.Value,"dd/MM/yyyy").tostring()

A Função “Format()” tem como primeiro parâmetro o campo e o segundo o tipo de formatação desejada.

Estes valores são inseridos clicando com o botão direito sobre o campo escolhendo a opção “Expression...”. A expressão deverá ser inserida no campo “Set Expression for: Value”. Ver Imagem 11.


Figura 11: Formatando campos.

Faremos este procedimento para os campos “RequiredDate” (Data), “UnitPrice” (Valor Unitário), “Quantity” (Quantidade), “Total” e “Total Geral”.

- Campos Calculados

Os campos calculados são utilizados para obter valores sem a utilização de campos específicos em Banco de Dados. Podemos realizar operações de subtração, adição, multiplicação, divisão e funções específicas do relatório. Segue exemplo a seguir utilizando o campo “Total” e “Total Geral” respectivamente.

Campo “Total”:

=format(Fields!UnitPrice.Value*Fields!Quantity.Value, "###,###,##0.00")

 

Campo “Total Geral”:

=format(SUM(Fields!UnitPrice.Value*Fields!Quantity.Value), "###,###,##0.00")

 

3-) Definindo o Preview do relatório

Adicionaremos alguns componentes na tela para efetuar a parametrização e a execução do relatório. Primeiramente adicione uma tabela para organização e em seu interior 2 Labels, 2 TextBoxes e um Button, para podermos filtrar por “OrderID”, que seria o número do pedido de venda. Já o componente ReportViewer é responsável pela visualização do relatório, junto com o Scriptmanager (componente necessário para execução de scripts) e o ObjectDataSource para inserção de alguns parâmetros. Ver Imagem 12.

Figura 12: Preview do Relatório.

Clique sobre o componente “ReportViewer” e na região superior direita clique na setinha (>) escolha “Choose Report” para vincular o relatório “RptMestreDetalhe.rdlc” ao preview.

Configurando o ObjectDataSource

O “ObjectDataSource” serve para configurar diretamente com classes de acesso a dados, ou seja, neste caso apontaremos para a fonte de dados citado anteriormente. Para isto clique sobre o mesmo e escolha a opção “Configure Data Source”. A Figura 13 é onde definimos o objeto “DsMestreDetalhe”. Clique em “Next” para configuração da próxima etapa.

Figura 13: Definindo o objeto.


Esta tela é muito importante, pois é nela onde são situados os métodos de Seleção, Atualização, Inserção e Exclusão. Em se tratando de relatórios apenas utilizaremos o primeiro método, o de Seleção de Dados. Neste caso estamos retornando um objeto do tipo “DsMestreDetalhe” e inserindo dois parâmetros do tipo inteiro, o “COD_INI” e o “COD_FIM”, ambos responsáveis pela parametrização dos dados ali obtidos. Ver Imagem 14.

 
Figura 14: Definindo o método de Seleção de Dados.

Já na próxima etapa, na região esquerda, estão situados os “Parameters” (parâmetros Nome e Valor) junto com algumas configurações como: “Source” (fonte, a origem do parâmetro), “QueryStringField” (nome do parâmetro) e “DefaultValue” (valor padrão). Clique em “Finish” para terminar este processo. Ver Imagem 15 para maiores detalhes das configurações.

Figura 15: Definindo os Parâmetros.

 

Codificando o botão “Imprimir”

Antes de iniciarmos a codificação no evento “Click()” do botão importe a seguinte biblioteca:
using Microsoft.Reporting.WebForms;

Esta biblioteca é responsável por alguns métodos utilizados ao decorrer do artigo.

 

protected void Button1_Click(object sender, EventArgs e)
{
    ObjectDataSource1.SelectParameters[0].DefaultValue = TextBox2.Text;
    ObjectDataSource1.SelectParameters[1].DefaultValue = TextBox3.Text;
    ReportParameter[] parametros =
    {
new ReportParameter("ParamTitulo","The Club - O Maior Clube de Programadores do Brasil"),
new ReportParameter("ParamSubtitulo","Relatório de Venda - Mestre/Detalhe")
    };

    ReportViewer1.LocalReport.SetParameters(parametros);
    ReportViewer1.LocalReport.Refresh();
}

 

Utilizamos o método “SelectedParameters” para filtrar os dados na instrução SQL. Faremos referência respectivamente com o primeiro e segundo TextBox. Já com a classe “ReportParameter” inserimos algumas informações que mais adiante serão recuperadas dentro do próprio arquivo “.rdlc”. Temos um par chave/valor sendo o nome do Parâmetro seguido do valor. Para finalizar passamos os dados utilizando a função “SetParameters”.
Para atualizar os dados na tela usamos o “refresh()”. Para testar o exemplo pressione o botão F5 e teremos um resultado parecido com a Imagem 16.


Figura 16: Relatório.


Conclusão

O desenvolvimento de relatórios do Tipo “Mestre/Detalhe” é muito habitual para nós programadores, usando para diversas tarefas como: Pedidos de Venda, Orçamentos de Produtos, entre outros tipos. A minha intenção neste artigo foi de proporcionar um exemplo prático para a utilização do ReportViewer em uma página Asp.Net. Podemos também aplicar estes conhecimentos, sem muitos esforços, na plataforma Desktop por exemplo. O ReportViewer, na minha opinião, é uma das melhores ferramentas em se tratando de Desenvolvimento de relatórios na plataforma “.Net”, tanto pela sua facilidade quanto pela grandiosidade de recursos encontrados. Vou procurar abranger em artigos futuros outros tipos de exemplos envolvendo esta ferramenta.

Um forte abraço e até o mês que vem!


Sobre o Autor

Thiago Cavalheiro Montebugnoli adora aprender novas tecnologias. É tecnólogo, formado pela Faculdade de Tecnologia de Botucatu - SP (FATEC) foi consultor técnico do The Club, já desenvolveu softwares utilizando a plataforma .NET, Delphi junto com Banco de Dados SQL Server e Firebird. Atualmente trabalha no Centro de Processamento de Dados da Prefeitura Municipal de Itaí-SP e é colunista mensal da Revista The Club Megazine. Possui as seguintes certificações: MCP - Microsoft Certified Professional, MCTS - Microsoft Certified Technology Specialist, MCAD - Microsoft Certified Application Developer e MCSD - Microsoft Certified Solution Developer.

E-mail: thiago@theclub.com.br

The Club - O Maior Clube de programadores do Brasil