Uma das ferramentas mais usadas atualmente para criação de relatórios é o famoso Crystal Reports, uma poderosa ferramenta que nos dá a possibilidade de usar vários tipos de fonte de dados, como Access, Datasets, XML, SqlServer, Oracle dentre outros.

Na maioria dos casos, tenho visto alguns projetos onde os relatórios se conectam diretamente com o Database propriamente dito, ou seja, sua fonte de dados é exatamente um objeto(table/view/procedure, etc) do banco de dados. Neste caso o report mantém informações fixas sobre a conexão, mas e quando essas informações mudarem? e no caso de quando fizermos o deploy em uma rede onde as credencias de conexão sejam diferentes? Muitas vezes nestes casos o Crystal não consegue se conectar a fonte de dados com as credencias que ele tem e exibe uma janela esperando que o usuário insira as novas informações, o que se torna um ponto vulnerável na aplicação.

A solução para este caso seria trabalhar com DataSets Tipados como fonte de dados para nosso relatório, ou seja, desvincular o Report do Database Server. Tenho percebido várias questões nas comunidades Microsoft em que participo, onde usuários só percebem esse problema no momento do deploy da aplicação, justamente na hora em que o tempo já se foi... com base nisso, pretendo falar neste artigo como alterar a fonte de dados de um relatório do crystal, ou seja, trabalhar com datasets tipados.

Vou partir do ponto em que já tenho um relatório no Crystal, conectado diretamente a uma fonte de dados no SqlServer. Para esse exemplo, fiz um relatório usando as tabelas Region e Territories do banco NorthWind, exibindo na sessão detalhes apenas os campos RegionDescription e TerritoryDescription, conforme mostra a figura 1 abaixo:

Relatório com a fonte de dados diretamente linkada ao database
Figura1. Relatório com a fonte de dados diretamente linkada ao database

Criando os Datasets tipados

A partir deste relatório base, vamos alterar sua fonte de dados para um dataset com duas tabelas exatamente iguais as que estamos usando do banco Northwind. Este fato é bastante importante, pois se as tabelas possuírem diferenças, na hora de fazer a conversão, o Crystal não conseguirá encontrar os campos que ele precisa e poderá perder a referencia aos campos existente no relatório.

O primeiro passo é criar o Dataset com as tabelas (exatamente iguais a fonte de dados atualmente existente no relatório) que precisamos.

O passo é simples, Botão direito no projeto > Add >> Add New Item... >> escolha DataSet. Dê o nome de

MeuDataset.xsd para este objeto e vamos criar as tebelas.

Na tela que se abre após a criação do Dataset (se não abrir, de um duplo clique no mesmo), botão direito >> Add >> New element. Um novo elemento será criado como mostra a Figura 2 abaixo:

Novo elemento criado
Figura 2. Novo elemento criado

Um novo elemento é criado em nosso Dataset, e vamos construi-lo conforme a tabela Region, inserindo os campos, e seus tipos como mostra a figura 3:

Elemento Region, com seus campos e tipos
Figura 3. Elemento Region, com seus campos e tipos

Seguindo os mesmos passos, vamos criar o próximo elemento, Territories.

Elemento Territories, com seus campos e tipos
Figura 4. Elemento Territories, com seus campos e tipos

Criando as Primary Keys

Perceba que os campos Region.RegionID e Territories.TerritoryID são PrimaryKeys de suas tabelas. É necessário definir isso também, ao passo que criaremos um DataRelation entre ambos.

Para setar o campo como PrimaryKey, no elemento Region, selecione o campo RegionID, botão direito >> Add >> New Key... apenas dê um clique em OK mantendo as informações padrão. Execute o mesmo procedimento para o campo TerritoryID da tabela Territories.

Criando DataRelation

Depois de criado os dois elementos, e suas devidas chaves, temos agora que fazer um relacionamento entre ambas, ou seja, um DataRelation. Siga os passos abaixo:

Botão direito na tabela Region >> Add >> New relation... a janela abaixo será aberta:

Janela de relacionamento entre os campos
Figura 5. Janela de relacionamento entre os campos

Automaticamente, os campos chaves das duas tabelas já são identificados no relacionamento, observe na área Fields o campo RegionID sendo exibido como Key e Foreign Key do relacionamento. Assim, apenas clique em OK para criar o relacionamento com as informações padrão.

Apontando o Report para o Dataset

Depois de tal estrutura montada, vamos agora apontar nosso report para este Dataset, fazendo-o entendelo como uma fonte de dados.

Abra o seu relatório do crystal, e no menu Database clique em Set Location... e com base na figura 6 vamos alterar a localização da nossa fonte de dados.

trocando a fonte de dados
Figura 6. trocando a fonte de dados

Veja que nessa janela temos duas sessões: Current Data Source e Replace With. A primeira refere-se a atual fonte de dados do relatório, perceba que ele exibe o nome do servidor no SqlServer. A segunda trata-se das opções disponíveis que podemos escolher para uma nova fonte de dados, veja os disponíveis na lista.

O passo agora é apontar para nosso Dataset tipado na aplicação, na sessão Replace With, expanda a opção Project Data >> ADO.NET Datasets. Repare na figura 7 que o nosso Dataset tipado é exibido aqui com ambas as tabelas que criamos anteriormente.

Apontando para uma nova fonte de dados
Figura 7. Apontando para uma nova fonte de dados

A sequência agora é simples, porém, crucial. Na sessão Current Data Source selecione a tabela Region no database, e na Replace With, marque a correspondente Region no nosso Dataset.

Com isso, dizemos que queremos trocar a tabela Region do database, no caso do exemplo SqlServer(Northwind) para a tabela Region do Dataset tipado MeuDataset. Para que isso ocorra com sucesso, o Crystal espera que ambas sejam idênticas, ao passo que já temos no report campos dessa tabela, e se esses campos forem diferentes na nova tabela, dos que estão inseridos no report, o crystal simplesmente os ignora e exclui do relatório, o que pode causar um grande retrabalho e frustração.

Concluindo o replace
Figura 8. Concluindo o replace

A opção “Apply this change to subreports” deve ficar marcada como true, caso exista algum subreport no relatório, o mesmo também será afetado pela alteração.

Feito isso, apenas um clique no botão Replace basta para concluir a alteração. Não se esqueça de repetir o processo também para a tabela Territories.

Pronto, espero que tudo tenha corrido perfeitamente bem, e nosso relatório já está associado ao Dataset que criamos na aplicação, e não mais ao banco Northwind, o que nos torna agora independente do banco de dados.

Populando o Dataset

Bom, o fato agora é que as tabelas do banco de dados eram populadas de dados por default, e agora com nosso Dataset? Para que o crystal exiba as informações, primeiramente temos que popular nosso Dataset com os dados que queremos que ele exiba. Essa é a tarefa menos difícil, popular o Dataset com dados da tabela e exibir o relatório.

O código abaixo cria os objetos necessários para resgatar os dados do database, populando o Dataset e exibindo-o no report.


 Dim cnn As SqlConnection = sqlCnn ''Objeto SqlConnection com credenciais do database
 Dim cmd As New SqlCommand
 Dim da As New SqlDataAdapter
 Dim ds As New _MeuDataset

 
 ''Populando Region
 cmd.CommandText = "Select * From Region"
 cmd.CommandType = CommandType.Text
 cmd.Connection = cnn
 
 da.SelectCommand = cmd
 da.Fill(ds.Tables("Region"))
 
 ''Populando Territories
 cmd.CommandText = "Select * From Territories"
 cmd.CommandType = CommandType.Text
 cmd.Connection = cnn
 
 da.SelectCommand = cmd
 da.Fill(ds.Tables("Territories"))
 
 ''Atribuindo o dataset ao crystal
 Dim rpt As New Report1
 rpt.Database.Tables(0).SetDataSource(ds.Tables(0))
 
 ''Passando o report para o objeto ReportViewer
 Me.RV.ReportSource = rpt
 
 ''Atualizando...
 Me.RV.RefreshReport()
Nota: Não estou levando em consideração tratamento de erros, boas práticas, etc no código acima. Apenas um exemplo.
Relatório sendo exibido
Figura 9. Relatório sendo exibido

Conclusão

Com a possibilidade de integrar Datasets tipados como fonte de dados de relatórios do Crystal conseguimos uma independência do Banco de Dados, e uma excelente portabilidade do mesmo. Para relatórios construídos usando outras fontes de dados ou linkados diretamente ao Database, também é possível mudar suas fontes de dados para Dataset, através da opção Set Location.