12 10 2016
Definindo a estrutura de campos do Crystal Reports sem DataSet ou classe
“André, eu consigo criar relatórios do Crystal Reports sem DataSet nem classe?“. Resposta: consegue sim! Uns tempos atrás eu mostrei como imprimir dados de um DataGridView no Crystal Reports. Naquele artigo eu mostrei duas maneiras para definirmos a estrutura de dados do relatório: através de um DataSet e através de uma coleção de instâncias de uma classe. Mas, e se tivermos que desenhar o relatório antes mesmo que o DataSet ou classe tenham sido criados? Nesse caso, temos que recorrer aos arquivos TTX, que nada mais são que arquivos de texto contendo as definições dos campos de cada tabela do relatório. É justamente isso que eu vou mostrar para você no artigo de hoje. Vem comigo!
Criando um relatório com arquivo TTX
Primeiramente, vamos criar um novo relatório no nosso projeto. Só para simplificar as coisas, neste artigo eu vou utilizar um projeto do tipo “Windows Forms Application“. Você poderia utilizar exatamente a mesma sistemática com outros tipos de projetos, como WPF ou Web Forms.
Dentro desse projeto, adicione um novo relatório em branco, dando o nome de “RelatorioFuncionario“. Com o relatório criado, a primeira coisa que temos que fazer é definirmos a estrutura de dados do relatório. Normalmente, nessa etapa nós selecionaríamos um DataSet ou classe do nosso projeto que serviria como fonte de dados para o nosso relatório. Porém, como o objetivo desse artigo é justamente definir o relatório sem DataSet ou classe, nós teremos que criar a definição dos campos com um arquivo TTX.
Os arquivos TTX nada mais são que arquivos de texto que contém a definição de campos de uma tabela. Esse arquivo pode ser criado manualmente com um editor de texto, mas, essa não é a melhor maneira de fazermos isso. O próprio Crystal Reports tem um “gerador” de arquivos TTX. Para evitarmos problemas, vamos utilizar esse gerador do Crystal Reports.
Para acessarmos o gerador de arquivos TTX, nós temos que abrir a tela “Database Expert“:
Dentro da janela “Database Expert“, encontre o item “Field Definitions Only“, que está localizado dentro da categoria “Create New Connection” / “More Data Sources“. Clique no botão de expansão desse item:
Na janela “Field Definitions Only“, como ainda não temos nenhum arquivo TTX, vamos clicar na opção “Create File“:
Ao fazermos isso, a janela de “Database Definition Tool” será aberta. Nessa janela podemos adicionar os campos da nossa tabela, indicando os seus nomes, tipos de dados e até mesmo um dado de exemplo (opcional).
Neste artigo nós faremos um relatório bem simples de listagem de funcionários, portanto, vamos criar somente três campos. O campo FuncionarioID será do tipo numérico e os campos Nome e Sobrenome serão do tipo string. Note que para os campos do tipo string nós temos que definir a quantidade de caracteres. A quantidade máxima de caracteres dos campos string é 65534. Para qualquer campo que tenha um tamanho maior que esse, você terá que utilizar o tipo “Memo” ao invés de “String“:
Uma vez adicionados os campos, feche a janela. Ao fechar a janela o Crystal Reports perguntará o local onde você quer salvar esse novo arquivo TTX. Escolha o diretório desejado e clique em salvar. Atente-se para o fato que o nome do arquivo sempre corresponderá ao nome da tabela no relatório. Portanto, salve o arquivo com o nome de “Funcionario.ttx“, dessa forma o Crystal Reports utilizará o nome “Funcionario” para a tabela.
Com o arquivo criado e salvo, adicione a tabela “Funcionario” para a lista de tabelas do relatório:
Em seguida vamos arrastar os campos da tabela “Funcionario” para dentro do relatório e ele estará pronto para ser exibido na nossa aplicação:
E qual é a estrutura de um arquivo TTX?
Antes de prosseguirmos com a exibição do relatório, vamos dar uma olhada na estrutura do arquivo TTX. Se você abrir o arquivo que salvamos anteriormente em um editor de texto, você verá que o conteúdo dele será este:
FuncionarioID Number Nome String 65534 Sobrenome String 65534
Note que a estrutura é muito simples. Em cada linha do arquivo temos a definição de uma coluna. A definição é composta pelo nome da coluna, tipo de dados, tamanho do campo e um dado de exemplo, tudo separado por “tabs“. Se por algum motivo você não quiser utilizar o editor de TTX do Crystal Reports, você pode criar ou editar esse arquivo “na mão” em um editor de texto sem problema algum.
Carregando o relatório com entidade anônima via LINQ
Agora que já temos o nosso relatório criado, vamos exibi-lo. Uns tempos atrás eu escrevi um artigo demonstrando como imprimir o conteúdo de um DataGridView no Crystal Reports. Nesse artigo eu mostrei dois tipos de carregamentos de dados nos relatórios do Crystal Reports: via DataSet ou via coleção de uma determinada classe. Só que eu esqueci que nós podemos enviar uma coleção de tipos anônimos gerados através de uma consulta LINQ! Então, eu vou mostrar para você neste artigo essa terceira maneira de enviar dados para o Crystal Reports: sem DataSet nem classe concreta.
Primeiramente, vamos adicionar o controle do Crystal Reports no nosso formulário e vamos escolher o relatório que criamos anteriormente:
Em seguida, vamos para o code-behind do formulário e, no construtor (ou no evento “Load” no caso do VB.NET), vamos criar um array com algumas informações de funcionários e, logo em seguida, vamos construir uma consulta LINQ que transformará esse array em uma coleção de um tipo anônimo com as colunas que precisamos no nosso relatório (FuncionarioID, Nome e Sobrenome). Por fim, a única coisa que fica faltando é passar essa coleção para o relatório e chamar um “Refresh” para os dados serem carregados:
// C# public FormRelatorio() { InitializeComponent(); var funcionarios = new object[] { new object[] { 1, "André", "Lima" }, new object[] { 2, "Fulano", "de Tal" }, new object[] { 3, "Beltrano", "da Silva" }, }; var colecao = from object[] funcionario in funcionarios select new { FuncionarioID = funcionario[0], Nome = funcionario[1], Sobrenome = funcionario[2] }; RelatorioFuncionario1.SetDataSource(colecao); RelatorioFuncionario1.Refresh(); }
' VB.NET Private Sub FormRelatorio_Load(sender As Object, e As EventArgs) Handles MyBase.Load Dim Funcionarios As Object() = { New Object() {1, "André", "Lima"}, New Object() {2, "Fulano", "de Tal"}, New Object() {3, "Beltrano", "da Silva"} } Dim Colecao = From Funcionario In Funcionarios Select New With { .FuncionarioID = Funcionario(0), .Nome = Funcionario(1), .Sobrenome = Funcionario(2) } RelatorioFuncionario1.SetDataSource(Colecao) RelatorioFuncionario1.Refresh() End Sub
E com isso, ao executarmos a nossa aplicação, veremos que os dados serão exibidos no relatório com sucesso:
Concluindo
Em algumas situações, pode ser que tenhamos que desenhar um relatório antes que o DataSet ou classe de dados tenham sido gerados. Nesse caso, se não quisermos criar um DataSet ou classe “fake“, nós temos a opção de criarmos arquivos TTX. Cada arquivo desse tipo contém a definição de campos de uma tabela que será utilizada no relatório do Crystal Reports.
Nesse artigo você conferiu como gerar relatórios do Crystal Reports sem DataSet nem classe, através de um arquivo TTX. Além disso, eu mostrei também como enviar dados para o relatório sem utilizar DataSets ou classes! Esse tipo de carregamento não se aplica a muitos cenários, mas, fica como dica para caso você precise na sua aplicação.
Antes de me despedir, 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
Infelizmente, meu MVP não foi renovado neste ciclo :( Report Viewer foi descontinuado pela Microsoft? Não!
André,
Essa ieia pode ser aplicada no Report Viewer?
Obrigado.
Olá Paulo!
Infelizmente não.. Com o Report Viewer só conseguimos desenhar o relatório se tivermos um DataSet (jeito clássico de se desenvolver os relatórios) ou se tivermos pelo menos uma classe de domínio com as colunas a serem utilizadas no relatório (como mostrei neste artigo).. Porém, como as informações dos campos do relatório são armaznadas diretamente no RDLC (que na verdade é um arquivo XML), poderíamos alterar o conteúdo do RDLC informando as colunas do DataSet.. Eu tenho planos de desenvolver uma extensão ou até mesmo aplicação que consiga fazer essa alteração de forma mais fácil, mas, ainda não encontrei tempo na minha agenda.. Assim que eu conseguir eu te aviso..
Abraço!
André Lima
Olá Paulo, tudo tranquilo?
Lembra que eu falei que tinha planos de construir uma ferramenta que possibilitasse a edição dos campos dos relatórios no Report Viewer? Pois bem, eu comecei a desenvolver essa ferramenta.. Expliquei mais detalhes sobre ela no artigo dessa semana, veja só:
Definindo a estrutura de campos do Report Viewer sem DataSet ou classe
Abraço!
André Lima
[…] criar a estrutura de campos do Report Viewer sem DataSet ou classe? No Crystal Reports temos os arquivos TTX para nos ajudar com essa tarefa, mas e quanto ao Report Viewer? Ele tem algo […]
Olá André,
Tem como trabalhar com 02 arquivos TTX em um rpt? Importei os dois TTX para o rpt, fiz o link entre eles. Estou passando um dataset contendo dados das duas tabelas para o rpt mas somente consigo visualizar dados da primeira tabela “primeiro TTX”. Será que você já passou por algo assim?
Abraços
Olá Oduvaldo!
Era para funcionar normalmente sim.. Você tem certeza que o relacionamento entre as tabelas está correto na definição do seu relatório?
Abraço!
André Lima
André, boa noite!
Gostaria saber duas coisas, 1 como tirar suprimir enfim nao mostrar a tela pedindo valosre dos paremetros do crystal reports sendo que ja usei o initializecomponent() nao resolveu, tem como fazrr isso?
2 como faço para passar dados de um controle windowd forms para um campo do subrelatorio do crystal reports sem presisar utilizar paretros ou seka via textobject no bb, net?
Olá Dilson!
Quanto à primeira questão, vou repetir aqui o que eu já te disse em um outro comentário:
“Como é que está o código de exibição do seu relatório? Esse tipo de comportamento normalmente acontece quando o “refresh” (ou “RefreshReport”) do relatório é chamado mais de uma vez.. Tente comentar métodos de refresh que eventualmente possam estar compondo o seu código e veja se o prompt deixa de aparecer..”
Já quanto à sua segunda pergunta, você terpa que encontrar o campo manualmente no ReportDocument e setar o seu valor.. Algo como o que foi explicado nesta thread do StackOverflow:
How to set crystal report’s textbox value at run time?
Abraço!
André Lima
Como usar os Campos de Expressão SQL no Crystal Reports, qual a sintaxe, pode dar um exemplo?
Att.
Dilson
Olá Dilson!
Não entendi o que você está querendo fazer nesse caso.. Será que você poderia explicar melhor?
Abraço!
André Lima