Olá, pessoal! Nesse terceiro artigo da série vamos trabalhar com vários exemplos dos relatórios Local Mode – lembrando que todos os códigos aqui implementados estão disponíveis, só entrar em contato.
Parte 3 – local mode – demos
A seguir, criaremos alguns relatórios para exemplificar o que já vimos até então, bem como alguns recursos que veremos com os relatórios que vamos criar. Nossos exemplos são baseados no modelo de dados apresentado na parte dois do nosso artigo, que relaciona pedidos, itens de pedido, produtos e vendedores.
Relatório tabular
Nesse exemplo, criaremos um relatório que nos permite visualizar a relação de produtos, suas respectivas categorias, total em estoque e valor unitário. O usuário desse relatório pode selecionar uma ou mais categorias de produtos que deseja visualizar. O relatório faz uso de formatação condicional para destacar as quantidades em estoque se esse for inferior a 250, também faremos uso dos recursos de formatação de moeda e ordenação da coluna: “Nome do Produto”.
Criando o relatório
Esse relatório exibe as colunas com o nome, categoria, total em estoque e valor unitário de cada produto.

- Primeiro passo: construção do DataSet
Adicionar um objeto dataSet com o nome Tabular (vide sessão “Repositório de dados Local – DataSet”) à aplicação na pasta DataSources, e adicionar a ele um datatable com a estrutura da figura 1.
Esse datatable será preenchido com os dados provenientes do resultado da seguinte stored procedure: getProdutosinCategorias, que recebe como parametro uma string com as identificações das categorias separadas por vírgula.
- Segundo passo: criação e modelagem do relatório
Incluiremos um novo relatório chamado TBProdutosporCategoria, em nosso projeto. Ele estará localizado na pasta Reports (vide artigos anteriores). Usando um objeto Table da toolbox dos relatórios, criaremos a estrutura do relatório formatado, conforme a figura abaixo:

- Terceiro passo: formatar o relatório
Destacaremos os itens da coluna de estoque com valor inferior a 250; para tal, selecionamos a janela de propriedades da caixa de texto e no atributo Color, selecionamos Expressions. Então criamos uma instrução da seguinte forma:
=IIf(Fields!QT_ESTOQUE.Value<250,"Red","Blue")
Em seguida, adicionamos as funcionalidades de ordenação nas colunas; para tal, basta configurar a caixa de texto “Nome Produto”, na tab Interative Sort, como na figura abaixo:

Criando o cliente
Para configuração do cliente, adicionamos e configuramos um controle ReportViewer. Em seguida, adicionamos o código cliente para carga do dataTable e a configuração do reportViewer criado. A seguir, apresentamos um trecho do código para carga da datatable e configuração do reportViewer com destaque para passagem dos parâmetros na stored procedure, utilizada para carga do datatable, idscategoria.
SqlParameter[] parms = { new SqlParameter("@idCategorias", SqlDbType.VarChar,20) }; parms[0].Value = getIdCategorias(); //método auxiliar que recupera as categorias da interface do usuário. cmdReport.CommandType = CommandType.StoredProcedure; cmdReport.Connection = conReport; foreach (SqlParameter parm in parms) cmdReport.Parameters.Add(parm); cmdReport.CommandText = "getProdutosinCategorias"; drReport = cmdReport.ExecuteReader(); dsReport.Tables[0].Load(drReport); drReport.Close(); conReport.Close(); rptViewTable.LocalReport.ReportPath = "Reports//TBProdutosporCategoria.rdlc"; ReportDataSource rds = new ReportDataSource(); rds.Name = "Tabular_ProdutosEstoque"; rds.Value = dsReport.Tables[0]; rptViewTable.LocalReport.DataSources.Clear(); rptViewTable.LocalReport.DataSources.Add(rds); this.rptViewTable.RefreshReport();
Finalmente eis nosso relatório em ação:

Relatório master-detail
Nesse exemplo criaremos um relatório que nos permite visualizar pedidos e seus respectivos itens. Para criação do master-detail, faremos uso da funcionalidade de subreports com parâmetros para relacionar o relatório principal (lista de pedidos) e seus respectivos itens.
Criando o relatório Detail
Começaremos com a construção do relatório que será o “detail” da nossa implementação. Esse relatório exibe duas colunas com a descrição do produto do pedido, e sua respectiva quantidade vendida.
- Primeiro passo: construção do DataSet.
Adicionar um objeto dataSet com o nome MasterDetail (vide sessão “Repositório de dados Local – DataSet”) à aplicação na pasta DataSources, e adicionar a ele um datatable com a estrutura da figura abaixo.

Esse datatable será preenchido com os dados provenientes do resultado da seguinte instrução SQL: SELECT [ITE].ID_PEDIDO, [PRO].DS_PRODUTO, [ITE].QT_PRODUTO FROM TB_ITENS_PEDIDO [ITE] INNER JOIN TB_PRODUTO [PRO] ON [ITE].ID_PRODUTO = [PRO].ID_PRODUTO
- Segundo passo: criação e modelagem do relatório.
Incluiremos um novo relatório em nosso projeto chamado MDItensPedidona pasta Reports. Usando um objeto Table da toolbox dos relatórios, criaremos a estrutura do relatório formatado conforme a figura abaixo:

- Terceiro passo: criar o parâmetro para associar ao “Master”
Aqui criaremos o parâmetro (vide sessão “Parametrização”) que será o link com o relatório “Master”. Esse parâmetro chamaremos de idPedido do tipo Integer e “Hidden”.

- Quarto passo: criar um filtro
Através das propriedades da tabela criada no segundo passo, criaremos um filtro dos dados do relatório, onde a identificação do pedido será aquela correspondente ao parâmetro criado no terceiro passo. A figura abaixo ilustra a operação.
Criando o relatório Master
Na criação do relatório “master”, exibimos a identificação do pedido, o nome do vendedor, a data do pedido e o valor em reais da venda do pedido. O grande diferencial desse relatório é a inclusão do item Subreport como se fosse uma coluna de uma table e configurar o subreport para associar o campo de identificação do pedido ao seu parâmetro.
- Primeiro passo: construção do Datatable no DataSet.
Adicionar um datatable ao nosso Dataset com a estrutura da figura abaixo. Esse datatable será preenchido com os dados provenientes do resultado da seguinte instrução SQL: SELECT [ped].ID_PEDIDO, [VEN].NO_VENDEDOR, CONVERT(SMALLDATETIME, [PED].DT_PEDIDO, 103) as DT_PEDIDO, SUM([ITE].QT_PRODUTO*[PRO].VL_PRECO) as [Valor do Pedido] FROM TB_PEDIDO [PED] INNER JOIN TB_ITENS_PEDIDO [ITE] ON [PED].ID_PEDIDO = [ITE].ID_PEDIDO INNER JOIN TB_PRODUTO [PRO] ON [ITE].ID_PRODUTO = [PRO].ID_PRODUTO INNER JOIN TB_VENDEDOR [VEN] ON [PED].ID_VENDEDOR = [VEN].ID_VENDEDOR GROUP BY [ped].ID_pedido,[VEN].NO_VENDEDOR, [PED].DT_PEDIDO.

- Segundo passo: criação e modelagem do relatório
Incluiremos um novo relatório chamado MDPedido, que estará na pasta Reports. Usando um objeto Table da toolbox dos relatórios, criaremos a estrutura do relatório formatado conforme a figura abaixo:

- Terceiro passo: configurar o subreport
Aqui configuraremos o item subreport de modo a estabelecer o vínculo entre o relatório master e o detail através do parâmetro, idPedido, criado no relatório Detail. Essa configuração é feita nas propriedades do subreport, a tab Parameters, como ilustra a figura:

Criando o cliente
Para configuração do cliente, adicionamos e configuramos um controle ReportViewer. Em seguida, adicionamos o código cliente para carga dos dataTables e configuração do reportViewer criado. A seguir, apresentamos um trecho do código para carga das duas datatables e configuração do reportViewer. A primeira instrução (em vermelho) carrega a tabela Pedido e a segunda a ItensPedido. Vemos também que só configuramos o datasource do relatório “master”, e o relatório “detail” a seguir:
cmdReport.CommandType = CommandType.Text; cmdReport.Connection = conReport; cmdReport.CommandText = "SELECT [ped].ID_PEDIDO, [VEN].NO_VENDEDOR, CONVERT(SMALLDATETIME, [PED].DT_PEDIDO, 103) as DT_PEDIDO, SUM([ITE].QT_PRODUTO*[PRO].VL_PRECO) as [Valor do Pedido] FROM TB_PEDIDO [PED] INNER JOIN TB_ITENS_PEDIDO [ITE] ON [PED].ID_PEDIDO = [ITE].ID_PEDIDO INNER JOIN TB_PRODUTO [PRO] ON [ITE].ID_PRODUTO = [PRO].ID_PRODUTO INNER JOIN TB_VENDEDOR [VEN] ON [PED].ID_VENDEDOR = [VEN].ID_VENDEDOR GROUP BY [ped].ID_pedido,[VEN].NO_VENDEDOR, [PED].DT_PEDIDO ; SELECT [ITE].ID_PEDIDO, [PRO].DS_PRODUTO, [ITE].QT_PRODUTO FROM TB_ITENS_PEDIDO [ITE] INNER JOIN TB_PRODUTO [PRO] ON [ITE].ID_PRODUTO = [PRO].ID_PRODUTO"; drReport = cmdReport.ExecuteReader(); dsReport.Load(drReport,LoadOption.OverwriteChanges,dsReport.Tables[0],dsReport.Tables[1]); drReport.Close(); conReport.Close(); rptViewMasterDetail.LocalReport.ReportPath = "..//..//Reports//MDPedido.rdlc"; ReportDataSource rds = new ReportDataSource(); rds.Name = "MasterDetail_Pedido"; rds.Value = dsReport.Tables[0]; rptViewMasterDetail.LocalReport.DataSources.Clear(); rptViewMasterDetail.LocalReport.DataSources.Add(rds); rptViewMasterDetail.RefreshReport();
Finalmente eis nosso relatório em ação:

Relatório gráfico
Nesse exemplo, criaremos um relatório que nos permite visualizar graficamente as vendas, em reais, dos nossos vendedores por período. Nesse relatório, faremos uso da funcionalidade Chart da toolbox dos relatórios. O período das vendas a serem consultadas será passado como parâmetro para instrução SQL, que fará a busca no banco de dados, o que é uma alternativa mais prudente que o uso de filtros no relatório, já que não necessitamos recuperar todos os registros das vendas.
Criando o relatório
Esse relatório correlaciona duas informações para gerar nosso gráfico: nome do vendedor e o total de sua venda.
- Primeiro passo: construção do DataSet.
Adicionar um objeto dataSet com o nome Gráfico (vide sessão “Repositório de dados Local – DataSet”) à aplicação na pasta DataSources, e adicionar à ele um datatable com a estrutura da figura abaixo.

Esse datatable será preenchido com os dados provenientes do resultado da seguinte instrução SQL: SELECT [VEN].NO_VENDEDOR, SUM([ITE].QT_PRODUTO*[PRO].VL_PRECO) as [Valor do Pedido] FROM TB_PEDIDO [PED] INNER JOIN TB_ITENS_PEDIDO [ITE] ON [PED].ID_PEDIDO = [ITE].ID_PEDIDO INNER JOIN TB_PRODUTO [PRO] ON [ITE].ID_PRODUTO = [PRO].ID_PRODUTO INNER JOIN TB_VENDEDOR [VEN] ON [PED].ID_VENDEDOR = [VEN].ID_VENDEDOR WHERE CONVERT(SMALLDATETIME, [PED].DT_PEDIDO, 103) BETWEEN ’99/99/9999′ AND ’99/99/9999′ GROUP BY [VEN].NO_VENDEDOR
- Segundo passo: criação e modelagem do relatório.
Incluiremos um novo relatório chamado GrVendas, na pasta Reports. Usando um objeto Chart da toolbox dos relatórios, criaremos a estrutura do relatório formatado conforme a figura abaixo:

- Terceiro passo: configurar o relatório
Aqui configuraremos o item Chart de modo a torná-lo parecido ao exibido na imagem acima.
- Quarto passo: criar os parâmetros do período
Nosso relatório também exibe o período da consulta que é exibido na sessão header do relatório. Para recuperar essas informações fornecidas pelo cliente, recorremos aos parâmetros, dtInicio e dtFim – esta configuração é feita nas propriedade do relatório, na tab Parameters.
Criando o cliente
Para a configuração do cliente, adicionamos e configuramos um controle ReportViewer. Em seguida, adicionamos o código cliente para carga do dataTable e configuração do reportViewer criado. A seguir, apresentamos um trecho do código para carga da datatable e configuração do reportViewer com destaque para passagem dos parâmetros dtInicio e dtFim.
cmdReport.CommandType = CommandType.Text; cmdReport.Connection = conReport; cmdReport.CommandText = "SELECT [VEN].NO_VENDEDOR, SUM([ITE].QT_PRODUTO*[PRO].VL_PRECO) as [Valor do Pedido] FROM TB_PEDIDO [PED] INNER JOIN TB_ITENS_PEDIDO [ITE] ON [PED].ID_PEDIDO = [ITE].ID_PEDIDO INNER JOIN TB_PRODUTO [PRO] ON [ITE].ID_PRODUTO = [PRO].ID_PRODUTO INNER JOIN TB_VENDEDOR [VEN] ON [PED].ID_VENDEDOR = [VEN].ID_VENDEDOR WHERE CONVERT(SMALLDATETIME, [PED].DT_PEDIDO, 103) BETWEEN CONVERT(SMALLDATETIME,'" + txtDtInicio.Text + "',103) AND CONVERT(SMALLDATETIME,'" + txtDtFim.Text + "',103) GROUP BY [VEN].NO_VENDEDOR"; drReport = cmdReport.ExecuteReader(); dsReport.Tables[0].Load(drReport); drReport.Close(); conReport.Close(); rptViewGrafico.LocalReport.ReportPath = "..//..//Reports//GrVendas.rdlc"; ReportParameter[] parPeriodo = { new ReportParameter("dtInicio",txtDtInicio.Text), new ReportParameter("dtFim",txtDtFim.Text)}; rptViewGrafico.LocalReport.SetParameters(parPeriodo); ReportDataSource rds = new ReportDataSource(); rds.Name = "Grafico_Vendas"; rds.Value = dsReport.Tables[0]; rptViewGrafico.LocalReport.DataSources.Clear(); rptViewGrafico.LocalReport.DataSources.Add(rds); rptViewGrafico.RefreshReport();
Finalmente eis nosso relatório em ação:

Relatório document map
Nesse exemplo, criaremos um relatório que nos permite visualizar pedidos, seus respectivos itens e o valor total do pedido dentro de um período informado pelo usuário. Utilizaremos um recurso chamado DocumentMap, onde listamos os vendedores e seus respectivos pedidos com recurso de um link para os detalhes do vendedor ou do pedido.
Criando o relatório
Esse relatório lista os vendedores, seus pedidos e detalhes do pedido, com recurso de navegação via Document Map.
Primeiro passo: construção do DataSet.
Adicionar um objeto dataSet com o nome DocumentMap (vide sessão “Repositório de dados Local – DataSet”) à aplicação na pasta DataSources, e adicionar à ele um datatable com a estrutura da figura abaixo.

Esse datatable será preenchido com os dados provenientes do resultado da seguinte instrução SQL: SELECT [PED].ID_PEDIDO, [PED].ID_VENDEDOR,[VEN].NO_VENDEDOR, [PED].DT_PEDIDO ,[pro].DS_PRODUTO, [ite].QT_PRODUTO, [pro].VL_PRECO FROM TB_PEDIDO [PED] INNER JOIN TB_VENDEDOR [VEN] ON [PED].ID_VENDEDOR = [VEN].ID_VENDEDOR INNER JOIN TB_ITENS_PEDIDO [ITE] ON [PED].ID_PEDIDO= ITE.ID_PEDIDO INNER JOIN TB_PRODUTO [PRO] ON ITE.ID_PRODUTO = PRO.ID_PRODUTO
- Segundo passo: criação e modelagem do relatório.
Incluiremos um novo relatório chamado DMapPedido, na pasta Reports. Usando um objeto Table da toolbox dos relatórios, criaremos a estrutura do relatório formatado conforme a figura abaixo:

- Terceiro passo: configurar o relatório
Aqui configuraremos o item Table, de modo a torná-lo parecido ao exibido na imagem acima. Para tal, faremos uso de uma das propriedades mais poderosas das tabelas, que é a tab Groups. Essa propriedade nos permite, como o nome diz, agrupar os registros por um ou mais campos, similar à cláusula GROUP BY do T-SQL. Na figura 16 percebe-se que fizemos dois agrupamentos, 1 e 2, respectivamente, pelos campos NO_VENDEDOR e ID_PEDIDO.
Começamos nossa configuração criando um relatório com os atributos acima, configurando-o como um relatório tabular. Em seguida, nas propriedades da tabela, criamos os agrupamentos nomeados table1_grpVendedor e table1_grpPedido, necessariamente nessa ordem, conforme a imagem abaixo (Figura 17).

Em seguida, na mesma caixa de edição do grupo, configuramos o recurso de Document Map, que corresponde a um dos recursos de navegação dos relatórios do Reporting Services. Essa configuração é feita simplesmente especificando o Document Map Label de cada grupo. Para o primeiro grupo, utilizamos o campo correspondente ao nome do vendedor. No segundo, sofisticamos com a criação de uma expressão que concatena uma string com o campo de identificação do pedido. Finalmente movemos os campos nome do vendedor e identificação do pedido para as linhas de cabeçalho dos seus respectivos grupos.
Outro elemento interessante em nosso relatório, e muito comum em relatórios com agrupamento, são os totalizadores. No nosso relatório, sumarizamos o total do pedido em uma caixa de texto posicionada na área de rodapé do agrupamento de pedidos, com uma expressão que soma os valores individuais de cada produto multiplicado pela quantidade vendida, codificado da seguinte forma:
=Sum(Fields!QT_PRODUTO.Value*Fields!VL_PRECO.Value)
Finalmente, formatamos as caixas de texto com data e moeda, bem como as cores de fundo das linhas.
- Quarto passo: criar os parâmetros do período
Nosso relatório também exibe o período da consulta, que é exibido na sessão header do relatório. Para recuperar essas informações fornecidas pelo cliente, recorremos aos parâmetros, dtInicio e dtFim. E essa configuração é feita nas propriedades do relatório – tab Parameters.
Criando o cliente
Para configuração do cliente, adicionamos e configuramos um controle ReportViewer. Em seguida, adicionamos o código cliente para carga do DataTable e configuração do reportViewer criado. A seguir apresentamos um trecho do código para carga da datatable e configuração do reportViewer com destaque para passagem dos parâmetros dtInicio e dtFim.
cmdReport.CommandType = CommandType.Text; cmdReport.Connection = conReport; cmdReport.CommandText = "SELECT [PED].ID_PEDIDO, [PED].ID_VENDEDOR,[VEN].NO_VENDEDOR, [PED].DT_PEDIDO,[pro].DS_PRODUTO, [ite].QT_PRODUTO, [pro].VL_PRECO FROM TB_PEDIDO [PED] INNER JOIN TB_VENDEDOR [VEN] ON [PED].ID_VENDEDOR = [VEN].ID_VENDEDOR INNER JOIN TB_ITENS_PEDIDO[ITE] ON [PED].ID_PEDIDO = [ITE].ID_PEDIDO INNER JOIN TB_PRODUTO [PRO] ”; cmdReport.CommandText += " ON [ITE].ID_PRODUTO = [PRO].ID_PRODUTO WHERE CONVERT(SMALLDATETIME,[ped].DT_PEDIDO,103) BETWEEN CONVERT(SMALLDATETIME,'" + txtDMdtInicio.Text + "',103) AND CONVERT(SMALLDATETIME,'" + txtDMdtFim.Text + "',103)"; drReport = cmdReport.ExecuteReader(); dsReport.Tables[0].Load(drReport); drReport.Close(); conReport.Close(); rptViewGrafico.LocalReport.ReportPath = "..//..//Reports//DMapPedido.rdlc"; ReportParameter[] parPeriodo = { new ReportParameter("dtInicio",txtDMdtInicio.Text), new ReportParameter("dtFim",txtDMdtFim.Text)}; rptViewGrafico.LocalReport.SetParameters(parPeriodo); ReportDataSource rds = new ReportDataSource(); rds.Name = "DocumentMap_Pedido"; rds.Value = dsReport.Tables[0]; rptViewGrafico.LocalReport.DataSources.Clear(); rptViewGrafico.LocalReport.DataSources.Add(rds); rptViewGrafico.RefreshReport();
Finalmente eis nosso relatório em ação:

Limitações
Os relatórios Local-mode são uma excelente alternativa para pequenas e médias aplicações onde os relatórios podem compartilhar recursos dos sistemas e não dispomos de uma infra-estrutura mais elaborada. Abaixo, relacionamos alguns dos itens que apontamos como limitações desse modelo de relatórios:
- Só exporta para os formatos Excel e PDF;
- Não suporta interface customizada;
- Não disponibiliza interface aos usuários para os parâmetros;
- Document map não suportado em FireFox;
- Compartilha os recursos da aplicação cliente.
É isso ai, pessoal! No próximoartigo, uma verdadeira revolução: os relatórios remote mode. Simplesmente imperdível! Até lá.