Por que eu devo ler este artigo:

O artigo pode servir como base introdutória para o desenvolvimento de relatórios em aplicações Java usando o framework JasperReports, podendo ser aplicado tanto em ambientes Web (Java EE) como Desktop (Java SE). Este framework permite extrair informações de várias fontes de dados, como: arquivos XML, banco de dados, arquivos CSV, dentre outros. Além disso, possibilita a geração de relatórios nos formatos PDF, HTML, Excel, Word e OpenOffice, por exemplo.

Neste artigo, será apresentado o uso do framework JasperReports, passando pelas fases de criação do arquivo de template, sua compilação, a invocação deste relatório via aplicação web, a geração do relatório com as informações vindas de uma fonte dados, e a exportação deste para outros tipos de arquivos, como PDF.

Neste processo iremos utilizar o iReport, no qual realizaremos um overview apresentando as principais características da ferramenta. O iReport irá simplificar a criação do arquivo de template e sua compilação.


Guia do artigo:

A grande maioria dos sistemas computacionais é criada para que dados sejam inseridos, possibilitando que estes sejam transformados em informações úteis. Com estas informações em mãos, é possível realizar análises e tomada de decisões estratégicas para uma empresa, por exemplo.

Uma das formas mais utilizadas para obtermos tais informações é o bom e velho relatório. Um relatório pode conter grandes quantidades de informações de forma detalhada e organizada, facilitando a leitura das mesmas.

Neste contexto, o JasperReports nos fornece funcionalidades que permitem criar relatórios complexos de forma estruturada, a partir da elaboração de um template. Este template é um arquivo XML com a extensão .jrxml. É neste arquivo que é especificada a estrutura do relatório, ou seja, é nele onde informamos os dados que irão compor o relatório, em que posição e de que forma serão exibidos, formando assim um layout.

A partir da definição do template e com o auxílio do framework JasperReports, conseguimos gerar nossos relatórios e exportá-los para diversos formatos, como: HTML, PDF e DOC.

JasperReports

O JasperReports é um framework open source inteiramente escrito em Java, tendo sido criado e mantido pela organização JasperForge. Ele é um dos mecanismos mais populares para a geração de relatórios na plataforma Java.

Através do JasperReports e sua poderosa API, é possível gerar e exportar relatórios altamente dinâmicos para aplicações Java. Tudo isso é feito de forma descomplicada, intuitiva e escrevendo poucas linhas de código.

Adicionando a biblioteca do JasperReports ao projeto

A biblioteca do JasperReports pode ser obtida diretamente do site, realizando o download do arquivo, ou através de uma ferramenta de gerenciamento e automação de projetos, como o Apache Maven. Até a elaboração deste artigo, a versão mais recente do framework era a 4.5.1, versão esta que iremos adotar em nosso exemplo.

Se a escolha for realizar manualmente o download, o pacote contendo as bibliotecas do JasperReports pode ser obtido através do site oficial do projeto (veja a seção Links). Logo após o download, os JARs devem ser extraídos e incluídos no CLASSPATH da aplicação.

Caso opte pelo Maven, a biblioteca deve ser declarada na seção de dependências do pom.xml do projeto, como mostrado a seguir:

<dependency>
    <groupId>net.sf.jasperreports</groupId>
    <artifactId>jasperreports</artifactId>
    <version>4.5.1</version>
  </dependency>

Etapas do processo de desenvolvimento de um relatório JasperReports

Antes de um relatório ficar pronto para ser visualizado ou impresso, este deve passar por algumas etapas de desenvolvimento.

A primeira etapa é a criação do template. Ela consiste basicamente em criar um arquivo do tipo XML, fazendo uso das tags e atributos definidos no arquivo jasperreports.dtd. O arquivo criado deve possuir a extensão .jrxml, e nele incluímos os campos a serem preenchidos dinamicamente por uma fonte de dados. Além disso, também podemos definir no template outros componentes, como textos fixos, imagens, cálculos, parâmetros, totalizadores, etc.

Na sequência, é preciso realizar a compilação do arquivo de template, criado anteriormente. Este passo é realizado pela API do JasperReports, sendo possível ser feito automaticamente via ferramenta, como iReport, ou pela própria aplicação (veremos ambas as formas de compilação mais adiante).

Após a compilação, um arquivo com a extensão .jasper é gerado. Este arquivo é um arquivo de classe Java, que representa um objeto da classe JasperReport, que será utilizado em conjunto com uma fonte de dados.

A fonte de dados, também conhecida como datasource, é usada para popular o relatório, compondo, assim, as informações que irão constituí-lo. Estas informações podem ser importadas através de fontes de dados distintas, como é o caso de arquivos XML, CSV, de forma programática através de coleções ou arrays de JavaBeans, ou até mesmo de uma conexão com o banco de dados. Ao preencher o relatório, criamos então um novo arquivo, agora com a extensão .jrprint. Este também é um arquivo Java, que implementa a interface JarperPrint.

Por fim, com um objeto do tipo JasperPrint, conseguimos exportar o relatório para diversos formatos, como HTML, PDF, TXT, RTF, entre outros, obtendo um relatório final que pode ser visualizado, impresso ou armazenado em disco.

Exemplo de arquivo de template

O arquivo de template, conforme já comentado, nada mais é do que um arquivo XML que define toda a estrutura do relatório, assim como também é definido o local onde cada informação será exibida. O código referente à Listagem 1 é um exemplo de template que gera, como saída, uma página de relatório conforme pode ser visto na Figura 1.

Note que no exemplo temos a declaração da tag . Este é o elemento principal do template. Esta tag, além de definir os namespaces, define também algumas características gerais do relatório, como por exemplo: margens, tamanho e orientação da página.

Logo abaixo, na sequência, podemos ver as declarações de três bandas: title, detail e pageFooter. Bandas são trechos da página onde são organizados os elementos do relatório. Cada uma destas bandas define os textos exibidos no relatório da Figura 1, juntamente com sua formatação, ou seja, o texto referente ao título (linha 18), o texto do detalhe (linha 29) e o texto do rodapé (linha 38).

Apesar de ser válido saber como é o arquivo XML para compreender melhor o funcionamento do framework, não é necessário decorarmos as tags para a criação de um relatório JasperReports. Isto porque temos ferramentas disponíveis que fazem esse trabalho de geração de código XML através de uma interface gráfica amigável, como é o caso do iReport.

  1.  <?xml version="1.0" encoding="UTF-8"?>
  2.  <jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports"
  3.  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"si:
      schemaLocation="http://jasperreports.sourceforge.net/jasperreports 
  4.  http://jasperreports.sourceforge.net/xsd/jasperreport.xsd"
  5.  name="exemplojm" language="java" pageWidth="595" pageHeight="842"
  6.  columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20"
  7.  bottomMargin="20">
  8.    <property name="ireport.zoom" value="1.0" />
  9.    <property name="ireport.x" value="0" />
  10.   <property name="ireport.y" value="0" />
  11.   <title>
  12.     <band height="79" splitType="Stretch">
  13.       <staticText>
  14.         <reportElement x="218" y="25" width="118" height="28" />
  15.         <textElement textAlignment="Justified">
  16.           <font size="20" isBold="true" />
  17.         </textElement>
  18.         <text><![CDATA[Exemplo JM]]></text>
  19.       </staticText>
  20.     </band>
  21.   </title>
  22.   <detail>
  23.     <band height="125" splitType="Stretch">
  24.       <staticText>
  25.         <reportElement x="216" y="51" width="122" height="23" />
  26.         <textElement textAlignment="Justified">
  27.           <font size="14" />
  28.         </textElement>
  29.         <text><![CDATA[Olá, JasperReports]]></text>
  30.       </staticText>
  31.     </band>
  32.   </detail>
  33.   <pageFooter>
  34.     <band height="54" splitType="Stretch">
  35.       <staticText>
  36.         <reportElement x="220" y="17" width="114" height="20" />
  37.         <textElement />
  38.         <text><![CDATA[Minha primeira página]]></text>
  39.       </staticText>
  40.     </band>
  41.   </pageFooter>
  42. </jasperReport>
Listagem 1. Exemplo de template – exemplojm.jrxml
Exemplo de página de relatório
Figura 1. Exemplo de página de relatório

iReport

O iReport é uma ferramenta gráfica gratuita criada e mantida pela JasperForge (mesma criadora do JasperReports), com o intuito de automatizar e facilitar o processo de desenvolvimento de relatórios para o framework JasperReports.

Esta ferramenta tem como principal característica permitir a criação e manutenção de arquivos de template, arquivos XML com a extensão .jrxml, por meios gráficos. Ou seja, o iReport gera de forma automática todo o código XML do arquivo de template, tirando esta responsabilidade do desenvolvedor.

Além disso, o iReport fornece aos desenvolvedores muitas outras facilidades e automações, como por exemplo: compilação do arquivo de template (.jrxml), verificação de erros em tempo de desenvolvimento, recurso de pré-visualização do relatório, exportação do relatório para vários formatos, entre outras.

Atualmente o iReport se encontra na versão 4.5.1 – até a escrita deste artigo – e pode ser obtido diretamente do site da JasperForge (confira a seção Links) para as plataformas Linux, Mac, Windows e outras.

Interface de trabalho do iReport

Antes de iniciarmos o desenvolvimento de nosso relatório com o auxílio do iReport, precisamos conhecer um pouco mais sobre essa poderosa ferramenta, a começar por sua interface.

O iReport nos oferece a facilidade de realizar todas as configurações e formatações que faríamos diretamente no arquivo XML, além de permitir compilar, pré visualizar o relatório, entre outras funcionalidades, através de uma interface gráfica bastante amigável e intuitiva.

Neste contexto, começaremos a explorar a ferramenta descrevendo alguns painéis de trabalho do iReport e suas funcionalidades, seguindo as numerações da Figura 2:

  1. Report Inspector: No Report Inspector podemos encontrar todos os componentes que compõem o relatório, como imagens, linhas e textos. Os componentes são agrupados de acordo com a banda (seção) em que podem sem inseridos e organizados de forma hierárquica. É possível, através desta janela, realizar algumas operações básicas com os elementos, como selecionar, copiar, remover, alinhar e outras;
  2. Report Designer: Esta parte representa a folha do relatório. É neste local que desenvolvemos o design do mesmo, inserindo, posicionando e alinhando elementos;
  3. Palette: Este é o local que contém os elementos (texto, imagem, gráficos etc.) que podemos clicar e arrastar para o nosso relatório;
  4. Formatting Tools: Com as opções desta janela conseguimos formatar os elementos do nosso relatório, contando com várias opções de alinhamento e posicionamento;
  5. Properties: Com as opções contidas nesta janela podemos definir as propriedades de um elemento selecionado. Como exemplo de propriedades da página, podemos citar o tamanho das margens, a orientação da página, o número de colunas etc.;
  6. Report Problems: Nesta janela são listados todos os problemas e avisos (warnings) existentes no relatório;

Caso algum destes painéis não esteja disponível, é possível adicioná-lo através da opção Window.

Agora que já conhecemos um pouco das principais características e funcionalidades referentes à interface do iReport, podemos partir para o desenvolvimento do nosso relatório de exemplo.

Interface do iReport
Figura 2. Interface do iReport

Parâmetros

Os parâmetros são os meios onde podemos fornecer dados externos ao relatório, ou seja, dados que não são obtidos através do datasource. Esses dados passados para o relatório geralmente são fornecidos pela própria aplicação que o invoca. Esta passagem de parâmetros é realizada em tempo de execução através de um objeto do tipo Map.

Os parâmetros podem ser usados em várias situações, por exemplo: para passar o nome do usuário da aplicação e exibi-lo no relatório como o usuário que gerou o relatório. Podem ser usados em expressões, e até mesmo em queries do relatório para realização de filtros, como veremos em nosso exemplo.

No iReport podemos visualizar e gerenciar os parâmetros pela janela Report Inspector. Ao consultar esta janela, notamos que por padrão já possuímos alguns parâmetros predefinidos, como, por exemplo: JASPER_REPORT (instância de um objeto JasperReport representando o template do relatório atual), REPORT_PARAMETERS_MAP (que pode receber um map com parâmetros do usuário passados em tempo de execução), entre outros.

Para que seja possível utilizar um parâmetro numa expressão, é preciso envolver o nome do mesmo entre as chaves do código $P{}. Por exemplo, se o nosso parâmetro fosse MEU_PARAMETRO, então o usaríamos desta forma: $P{MEU_PARAMETRO}.

Bandas (seções)

As bandas, também chamadas de seções, são as divisões existentes na página do relatório, como podem ser observadas na Figura 3. Cada uma destas seções possui características e papel específico para o relatório e, de acordo com estas características, é possível tratar seus elementos de maneiras diferentes no momento da geração do relatório. Os comportamentos de cada banda estão descritos na Tabela 1.

São nestas seções que inserimos os elementos que irão compor nosso relatório, como imagens e textos, por exemplo. Podemos visualizar os elementos que cada banda possui na janela Report Inspector do iReport, conforme já informado.

Title Os elementos desta seção são exibidos uma única vez no relatório. É o título do relatório.
Page Header Exibida no topo de todas as páginas do relatório. É o cabeçalho da página.
Column Header Exibida no topo de cada coluna do relatório. É o cabeçalho da coluna. Obs.: se o relatório contiver apenas uma coluna, então esta seção é ignorada.
Detail O detail é exibido para cada linha do datasource, ou seja, se repete enquanto houver linhas para serem exibidas. Resumidamente, a seção de detalhe exibe os itens do relatório.
Column Footer Exibida abaixo de cada coluna do relatório. É o rodapé da coluna. Obs.: semelhante ao Page Header; se houver apenas uma coluna, esta seção é ignorada.
Page Footer Esta é a seção referente ao rodapé da página, sendo exibido no final de cada página do relatório.
Summary Exibido uma única vez no final do relatório.
Tabela 1. Comportamento das seções

Além destas seções que podemos ver na Figura 3, também temos outras duas bandas padrões que podem ser vistas na janela Report Inspector. Essas bandas são: lastPageFooter e background. A primeira faz a função de rodapé da última página do relatório, e a outra representa o fundo da página, na qual podemos inserir conteúdos gerados em todas as páginas e posicionados atrás das bandas.

Caso não seja necessário utilizar uma banda, podemos removê-la facilmente clicando na banda desejada com o botão direito e, em seguida, em Delete Band.

Bandas (seções) do relatório
Figura 3. Bandas (seções) do relatório

Fields

Os fields, ou campos, são usados para representar os dados do datasource ou de uma query em nosso relatório. Eles são preenchidos dinamicamente no momento da geração do relatório.

Os campos são criados automaticamente ao inserirmos uma query em nosso template. Dessa forma, estes são criados com os mesmos nomes e tipos correspondentes às colunas da consulta, facilitando o seu uso dentro do relatório. Outra forma de se inserir um field pode ser feita através da janela Report Inspector, clicando com o botão direito do mouse na opção Fields e em seguida em Add Field.

A partir daí, os campos já podem ser usados em expressões dentro das chaves do código $F{}. Por exemplo, se tivermos um field com o nome MEU_FIELD, o código ficaria: $F{MEU_FIELD}.

Para visualizarmos todos os fields de um relatório, basta acessar a janela Report Inspector e expandir a opção Fields clicando sobre ela.

Variables

Uma variável no JasperReports é representada pelo símbolo $V{}. Assim, caso tenhamos uma variável com o nome minhaVariavel, o acesso a esta dentro de uma expressão, por exemplo, seria realizada através de: $V{minhaVariavel}.

Podemos visualizar todas as variáveis contidas em nosso relatório na janela Report Inspector, na opção Variables. Por padrão, o JasperReports nos oferece algumas variáveis pré-definidas, a saber:

  • PAGE_NUMBER; retorna o número da página corrente;
  • COLUMN_NUMBER: retorna o índice da coluna atual;
  • REPORT_COUNT: retorna o número de registros processados;
  • PAGE_COUNT: variável que contém o número de registros que foram processados ao gerar a página atual;
  • COLUMN_COUNT: contém o número de registros que foram processados durante a geração da coluna atual.

Para criar uma nova variável, basta clicar com o botão direito do mouse sobre a opção Variables e em Add Variable. Em seguida, informe o nome e a classe que irá representar o tipo da variável (exemplo: String, Date, Double, etc.) nas propriedades da mesma. Para remover uma já existente, clique com o botão direito do mouse sobre a variável e depois em Delete. Para editá-la, selecione a variável desejada e a configure na janela de propriedades.

Expressões

As expressões do JasperReports podem ser criadas através de código Java, contendo variáveis, parâmetros e campos, para execução de cálculos exibidos no relatório, por exemplo. Podemos, também, além destes, fazer uso de classes Java (declarando a classe com seu nome completo ou importando-a no template do relatório) nas expressões, uma vez que o código, como já citado, pode ser gerado através da linguagem Java.

Para configurarmos a linguagem utilizada nas expressões do JasperReports, devemos clicar com o botão direto do mouse sobre a raiz do relatório, localizada na janela Report Inspector, e na sequência em Properties. Uma janela conforme a apresentada na Figura 4 será exibida, então selecione a linguagem Java na opção Language.

Configurando a linguagem utilizada nas expressões
Figura 4. Configurando a linguagem utilizada nas expressões

Exemplo

Nosso exemplo será baseado num case de uma empresa de arquivamento. Essa empresa organiza e arquiva documentos diversos de outras empresas.

Estes documentos são organizados em caixas numeradas de forma que, cada caixa poderá conter vários documentos, sendo que esses documentos devem pertencer apenas a um cliente, ou seja, não é permitido que uma caixa possua documentos de clientes variados.

O objetivo do relatório será listar os documentos contidos em cada caixa, agrupados por cliente e caixa, possibilitando a localização dos documentos de forma simples.

Criando o banco de dados

Antes de partir para o relatório, precisamos preparar os dados que serão consultados e listados. Para tal, começaremos o nosso exemplo pelo banco de dados.

O banco de dados utilizado foi o MySQL versão 5.1. Para obter este SGBD, veja o endereço para download na seção Links.

Para o nosso exemplo, vamos criar quatro tabelas: caixa, cliente, documento e tipo documento. Nesta estrutura, um cliente pode possuir um ou mais documentos (notas fiscais, recibos, etc.), e tais documentos serão armazenados e organizados em caixas. Além disso, todo documento será classificado por um tipo, e esta classificação é determinada de acordo com a associação entre um documento e um tipo de documento.

Esta definição é representada pela modelagem exibida na Figura 5, que pode ser gerada a partir dos scripts descritos na Listagem 2.

Os dados a serem inseridos nas tabelas do banco não precisam necessariamente ser os mesmos do exemplo aqui apresentado, mas, por praticidade, os scripts para isso serão disponibilizados para download juntamente com o projeto, no site da Easy Java Magazine.

Os scripts de inserção dos dados e o passo a passo de como realizar as operações no banco de dados não serão listados no artigo, pois não fazem parte do escopo do mesmo.

Após realizar o processo de criação do banco de dados e popular devidamente as tabelas com alguns dados para que possamos usá-los em nosso relatório, já podemos partir para o desenvolvimento deste.

Modelo do banco de dados exemplo
Figura 5. Modelo do banco de dados exemplo
    -- Cria o schema
  CREATE SCHEMA `arquivojm`;
   
  -- Cria a tabela de cliente
  CREATE  TABLE `arquivojm`.`cliente` (
    `id` INT NOT NULL AUTO_INCREMENT ,
    `nome` VARCHAR(45) NOT NULL ,
    `cnpj` VARCHAR(45) NULL ,
    `endereco` VARCHAR(45) NULL ,
    PRIMARY KEY (`id`) );
   
  -- Cria a tabela de caixa
  CREATE  TABLE `arquivojm`.`caixa` (
    `id` INT NOT NULL AUTO_INCREMENT ,
    `cliente` INT NOT NULL ,
    PRIMARY KEY (`id`) ,
    INDEX `fk_cliente` (`cliente` ASC) );
   
  -- Cria a tabela de tipos de documento:
  CREATE  TABLE `arquivojm`.`tipo_documento` (
    `id` INT NOT NULL AUTO_INCREMENT ,
    `nome` VARCHAR(45) NOT NULL ,
    PRIMARY KEY (`id`) );
   
  -- Cria a tabela de documento:
  CREATE  TABLE `arquivojm`.`documento` (
    `id` INT NOT NULL AUTO_INCREMENT ,
    `caixa` INT NOT NULL ,
    `tipo_documento` INT NOT NULL ,
    `cliente` INT NOT NULL ,
    `nome` VARCHAR(45) NOT NULL ,
    `dt_entrada` DATE NULL ,
    `observacao` VARCHAR(45) NULL ,
    PRIMARY KEY (`id`) ,
    INDEX `fk_caixa` (`caixa` ASC) ,
    INDEX `fk_tipo_documento` (`tipo_documento` ASC) ,
    INDEX `fk_cliente` (`cliente` ASC) );
Listagem 2. Scripts para criação do schema do banco de dados e suas tabelas

Criando o primeiro relatório

Para criarmos nosso relatório, iremos contar com o auxílio da ferramenta gráfica iReport, que terá papel fundamental durante todo o processo de desenvolvimento do relatório. Assim, devemos abrir o iReport Designer.

A primeira etapa a ser realizada será a escolha do template. Para fins de aprendizagem e melhor entendimento do processo, iremos optar por um template básico, no qual passaremos a melhorá-lo com os recursos apresentados.

Portanto, acesse o menu File > New, na janela exibida mantenha a opção Blank A4 selecionada e clique em Open this template. Feito isso, será solicitado o nome do template e o local onde ele será salvo (por enquanto podemos salvá-lo no desktop, por exemplo, mas depois iremos importá-lo para o nosso projeto web). Para o nome do nosso template, informe “listagemDocumentos” e prossiga até concluir. Ao finalizar a tela, teremos um template pronto para iniciarmos o trabalho.

O Datasource

Para que o JasperReports consiga extrair as informações que iremos exibir no relatório, precisamos informar uma fonte de dados, isto é, especificar onde se encontram os dados que irão compor o relatório.

A origem dos dados de nosso exemplo é o banco de dados arquivojm, que criamos anteriormente. Neste caso, para criarmos uma conexão com o banco de dados, basta clicar no botão Report Datasources, conforme indica a Figura 6. Em seguida, clique no botão New. Na tela seguinte, será solicitado o tipo de datasource que iremos trabalhar. Para o nosso exemplo, usaremos Database JDBC connection, seguindo o exemplo da Figura 7, então selecione esta opção e avance.

Botão Report Datasources
Figura 6. Botão Report Datasources
Lista com os tipos de datasources
Figura 7. Lista com os tipos de datasources

Além deste, o JasperReports também permite trabalhar com outros tipos de fonte de dados, tais como: arquivos XML, CSV, JSON, JavaBeans (através de Collections ou Arrays), entre outros. Os tipos de datasource suportados podem ser vistos na tela de Datasource (observe a Figura 7).

Na próxima tela devemos fornecer os dados necessários para que o JasperReports se conecte ao banco de dados. Para isso, informe os dados dos seguintes campos de acordo com a Figura 8:

  • Name: Nome da conexão criada;
  • JDBC Driver: Drive do banco de dados;
  • JDBC URL: URL de acesso ao banco de dados;
  • Server Address: Endereço (host) do servidor de banco de dados;
  • Database: Nome do banco de dados;
  • Username: Nome do usuário do banco de dados;
  • Password: Senha do usuário do banco de dados.

Os valores dos campos podem variar de acordo com o ambiente de desenvolvimento. Por exemplo, neste caso o banco de dados está instalado na mesma máquina em que iremos executar o exemplo, por este motivo informamos localhost no endereço do servidor.

Tela de configuração de conexão do banco via JDBC
Figura 8. Tela de configuração de conexão do banco via JDBC

Após informar os dados solicitados, é possível realizar um teste de conexão antes de salvarmos esta tela. Para isso, clique no botão Test. Se a conexão for estabelecida, uma mensagem será exibida indicando que o teste de conexão foi realizado com sucesso. Caso tenha ocorrido algum erro, revise os passos anteriores.

Inserindo a Query

O nosso relatório será preenchido com o resultado da execução de uma query. Esta query trará os registros das tabelas: documentos, tipo_documento, caixa e cliente, criadas anteriormente. Para deixarmos o exemplo mais rico e real, iremos criar dois parâmetros que serão utilizados na condição de filtro da query. Esses parâmetros serão passados pela aplicação web e utilizados no filtro de clientes em nosso relatório.

Para criarmos os parâmetros devemos clicar com o botão direito do mouse sobre a opção Parameters, na janela Report Inspector e, em seguida, em Add parameter. Os parâmetros devem possuir os nomes clienteDe e clienteAte, e ambos devem ser do tipo Integer. Para informar o nome e o tipo dos parâmetros criados, acesse a janela Properties.

Uma vez que já fornecemos a conexão com o banco de dados ao JasperReports, precisamos informar quais os dados que devem ser trazidos para o relatório. Faremos isso criando uma query, da seguinte forma: clique com o botão direito do mouse sobre a raiz do template, na janela de Report Inspector, e depois selecione a opção Edit Query. Feito isso, uma tela semelhante à Figura 9 será exibida.

É nesta tela que devemos informar a query para que o JasperReports consiga trazer os dados que iremos manipular em nosso template. Assim, informe a query conforme o código da Listagem 3. Esta realizará uma busca listando todos os documentos existentes relacionados a cada cliente.

Repare que ao terminar de inserir a query, o iReport já nos traz os campos (Field name) representando as colunas do relatório com seus respectivos tipos (Field Type). Essas colunas serão criadas automaticamente pelo iReport ao confirmar a tela, conforme pode ser visto na Figura 10.

Tela de edição da query do relatório
Figura 9. Tela de edição da query do relatório
Fields
gerados automaticamente através da query
Figura 10. Fields gerados automaticamente através da query
SELECT caixa.codigo CD_CAIXA,
      cliente.id CD_CLIENTE,
      cliente.nome NM_CLIENTE,
      cliente.cnpj CNPJ,
      tipo.nome TIPO,
      documento.nome NM_DOCUMENTO,
      documento.observacao OBSERVACAO,
      documento.dt_entrada DT_ENTRADA
  FROM arquivojm.caixa caixa,
      arquivojm.cliente cliente,
      arquivojm.documento documento,
      tipo_documento tipo
  WHERE caixa.cliente = cliente.id
      AND documento.cliente = caixa.cliente
      AND documento.caixa = caixa.codigo
      AND tipo.id = documento.tipo_documento
      AND cliente.id BETWEEN $P{clienteDe} AND $P{clienteAte}
  ORDER BY caixa.codigo
Listagem 3. Query utilizada no relatório para realizar a consulta no banco

Montando o relatório

A etapa de montagem do relatório consiste basicamente em inserir os elementos que irão compor o mesmo. Alguns desses elementos, que podem ser encontrados na janela Palette, são: textos estáticos, linhas, campos de texto, retângulos e outros. Além de quais elementos farão parte de nosso relatório, definimos também como e onde serão apresentadas as informações.

Para inserirmos um determinado componente em nosso relatório, é preciso selecioná-lo na janela Palette e arrastá-lo para o local desejado. Cada componente possui um conjunto específico de propriedades, o qual nos permite configurá-lo de acordo com a nossa necessidade. Ao adicionar um Static Text (texto estático), por exemplo, podemos configurar o tamanho da fonte e a cor do texto.

Dito isso, começaremos a compor o nosso relatório pelo título. Faremos isso inserindo alguns elementos na banda Title. Nesta seção devemos incluir um texto estático com o conteúdo “RELATÓRIO DE DOCUMENTOS”, e logo acima inserir um elemento chamado “Current date”, que exibe a data atual em que o relatório for gerado. Para alterar o formato da data, configure a opção pattern na janela de propriedades.

Agora iremos criar os títulos das colunas do relatório. Esses títulos serão elementos do tipo Static Field com os seguintes textos: “DOCUMENTO”, “TIPO”, “ENTRADA” e “OBSERVAÇÃO”. Repare que estas colunas correspondem às colunas retornadas pela query.

No próximo passo é preciso definir dois grupos de relatório. Os grupos de relatório do JasperReports, como o próprio nome sugere, são criados para agrupar conteúdos que possuam a mesma informação.

Deste modo, agruparemos as informações de clientes e de caixa. Para criar um agrupamento, clique com o botão direito do mouse sobre a raiz do relatório, e em seguida em Add Report Group. Uma nova janela semelhante à da Figura 11 será exibida. No campo Group name, informe um nome para o grupo, grupoCliente, mantenha a opção Group by the following report object selecionada, e no combo que contém a lista de campos, especifique o campo base para o JasperReport realizar o agrupamento (neste caso, selecione o campo CD_CLIENTE) e clique em Next. Na próxima tela, temos as opções header e footer para o grupo (neste caso, apenas desmarque a opção Add the group footer).

Para criar o grupo de caixa, repita o processo anterior informando grupoCaixa como nome do grupo e CD_CAIXA para o campo agrupado. No entanto, diferentemente dos passos realizados anteriormente, mantenha selecionado ambas as opções, Add the group header e Add the group footer, para que um grupo seja adicionado como cabeçalho e outro como rodapé, respectivamente.

Agora que acabamos de definir os grupos, podemos observar que para cada um foram criadas novas bandas correspondentes. Deste modo podemos inserir elementos nessas bandas. Iremos então inserir na banda grupoCliente os campos (fields) cujos conteúdos serão trazidos da query. Para isso, selecione e arraste para a banda grupoCliente os campos NM_CLIENTE (nome do cliente) e CNPJ (número do CNPJ do cliente). Adicione também dois textos estáticos com os textos “Cliente:” e “CNPJ:” precedendo, respectivamente, os campos inseridos.

Na banda de grupoCaixa iremos inserir apenas o campo CD_CAIXA (código da caixa) precedido do texto estático “Caixa:”.

Chegamos agora na banda Detail. Esta é a banda responsável por exibir os itens do relatório. Portanto, nesta seção iremos adicionar os campos NM_DOCUMENTO, TIPO, DT_ENTRADA e OBSERVACAO. Para facilitar a leitura do relatório, mantenha esses campos alinhados com os textos correspondentes criados no Page Header. Esta banda irá exibir uma linha para cada documento armazenado nas caixas de clientes.

Na banda grupoCaixa Group Footer incluiremos uma variável contadora, responsável por totalizar a quantidade de documentos existentes por caixa. Para isso, basta arrastar a variável grupoCaixa_COUNT, localizada em Variables, na janela de Report Inspector, para dentro da banda. Essa variável foi criada automaticamente pelo iReport na inclusão do grupo e realiza a função de um contador de linhas do mesmo. Insira também o texto estático “Total documentos:” precedendo a variável.

Por fim, na banda Page Footer, exibiremos o número da página corrente e o total de páginas do relatório. O iReport já possui um elemento chamado Page X of Y com essa finalidade, sendo possível customizar as propriedades deste elemento, como, por exemplo, alterar o texto Page por Página. Assim, encontre e arraste este elemento de Palette para a banda de Page Footer.

Ao concluir esses passos, o design do relatório deve ficar parecido com o da Figura 12. Como se pode perceber, algumas formatações e estilos não foram levados em consideração, pois são facilmente aplicados e podem variar de acordo com a escolha e gosto de cada um.

A partir deste ponto já conseguimos pré-visualizar o nosso relatório através do próprio iReport. Ao clicar no botão Preview (veja a Figura 13), o relatório é compilado e preenchido com os dados do banco.

Para manter os elementos alinhados uns com os outros, selecione os elementos desejados mantendo a tecla Ctrl pressionada e clique na opção de alinhamento desejada na janela Formatting Tools Window.

Tela de criação de grupo do relatório
Figura 11. Tela de criação de grupo do relatório
Design do relatório
Figura 12. Design do relatório
Tela de Preview do iReport
Figura 13. Tela de Preview do iReport

O projeto web

Esta etapa consiste basicamente em criar um cenário onde iremos gerar o relatório elaborado anteriormente a partir de uma aplicação web, fazendo uso da API do JasperReports. Portanto, crie um projeto web contendo os jars necessários para o funcionamento do JasperReports e copie o arquivo .jrxml referente ao template do relatório para o diretório /WEB-INF/report/ do projeto.

Por questões de priorização de conteúdo, apenas o código da classe que realiza a chamada do relatório será exibido no artigo, porém, o projeto web completo será disponibilizado para download no site da revista.

Vamos então visualizar o código da Listagem 4, para aprender como trabalhar com a API do JasperReports em nossa aplicação. Na classe RunReport, existem três pontos chaves para a geração do relatório que devem ser detalhados.

O primeiro diz respeito à compilação do relatório (linha 33). Aqui, informamos um InputStream referente ao nosso arquivo de template, para que o método estático JasperCompileManager.compileReport() possa compilá-lo. A compilação resultará em um arquivo com a extensão .jasper.

O segundo ponto é onde passamos os parâmetros que serão utilizados na geração do relatório, assim como a conexão com o banco de dados, e o relatório compilado. Nesta etapa o JasperReports preenche o relatório com os dados do banco e retorna um objeto do tipo JasperPrint (linha 51).

Note que os parâmetros são compostos por dois objetos do tipo Integer, representando o código do cliente. Esses códigos serão usados na query do relatório, mais especificamente na cláusula where (cliente.id BETWEEN $P{clienteDe} AND $P{clienteAte}).

O JasperReports consegue atribuir o valor passado associando o nome da chave do item do Map com o nome do parâmetro do relatório, ou seja, o valor passado para a chave clienteDe é atribuído ao parâmetro clienteDe do relatório.

Por fim, na terceira etapa realizamos a exportação do relatório, utilizando o método estático JasperExportManager.exportReportToPdfStream(), informando um objeto do tipo JasperPrint (obtido no passo anterior), e um objeto do tipo OutputStream. Este método irá gerar o relatório no formato PDF, como o próprio nome sugere.

Ao executar o projeto de exemplo, podemos enfim realizar o download do relatório, bastando apenas informar o filtro de clientes e clicar no botão Gerar relatório. Como resultado, será possível visualizar um relatório no formato PDF semelhante ao dá Figura 14. A tela do sistema pode ser vista na Figura 15.

Relatório de documentos
Figura 14. Relatório de documentos
Tela do sistema web filtrando os clientes cujo ID esteja contido entre 2 e 4
Figura 15. Tela do sistema web filtrando os clientes cujo ID esteja contido entre 2 e 4
  1.  package br.com.arquivistajm;
  2.   
  3.  @ManagedBean
  4.  @RequestScoped
  5.  public class RunReport implements Serializable {
  6.   
  7.    private static final long serialVersionUID = 1L;
  8.   
  9.    
  10.    //Código do cliente usado no filtro do relatório.
  11.   
  12.   private Integer codigoClienteDe = 0;
  13.  
  14.   
  15.    //Código do cliente usado no filtro do relatório.
  16.    
  17.   private Integer codigoClienteAte = 99999;
  18.  
  19.   
  20.    //Gera o relatório pré-compilado pelo iReport.
  21.    
  22.    @return
  23.    @throws JRException
  24.    @throws IOException
  25.    
  26.   public String printReport() throws JRException, IOException {
  27.  
  28.     // Define o caminho do template.
  29.     String path = "/WEB-INF/reports/listagemDocumentos.jrxml";
  30.     InputStream jasperTemplate = FacesContext.getCurrentInstance().
          getExternalContext().getResourceAsStream(path);
  31.  
  32.     // Compila o template.
  33.     JasperReport = JasperCompileManager.compileReport(jasperTemplate);
  34.  
  35.     // Configura os parâmetros.
  36.     Map parametros = new HashMap();
  37.     parametros.put("clienteDe", this.codigoClienteDe);
  38.     parametros.put("clienteAte", this.codigoClienteAte);
  39.  
  40.     // Cria a conexão com o banco de dados.
  41.     Connection conexao = null;
  42.     try {
  43.       Class.forName("com.mysql.jdbc.Driver");
  44.       conexao = DriverManager.getConnection("jdbc:mysql://localhost/arquivojm", "root", "root");
  45.     } catch (Exception e) {
  46.       // TODO: handle exception
  47.     }
  48.  
  49.     // Passagem dos parâmetros e preenchimento do relatório - informamos um
  50.     // datasource vazio, pois a query do relatório irá trazer os dados.
  51.     JasperPrint = JasperFillManager.fillReport(jasperReport, parametros, conexao);
  52.  
  53.     // Obtém a resposta.
  54.     HttpServletResponse response = (HttpServletResponse)
          FacesContext.getCurrentInstance().getExternalContext().getResponse();
  55.  
  56.     ServletOutputStream outputStream = response.getOutputStream();
  57.  
  58.     response.setContentType("application/pdf");
  59.     response.setHeader("Content-Disposition", "attachment; filename=\"relatorio.pdf\"");
  60.  
  61.     // Exportar o relatório para PDF.
  62.     JasperExportManager.exportReportToPdfStream(jasperPrint, outputStream);
  63.  
  64.     outputStream.flush();
  65.     outputStream.close();
  66.     FacesContext.getCurrentInstance().renderResponse();
  67.     FacesContext.getCurrentInstance().responseComplete();
  68.  
  69.     return null;
  70.   }
  71.  
  72.   public Integer getCodigoClienteDe() {
  73.     return codigoClienteDe;
  74.   }
  75.  
  76.   public void setCodigoClienteDe(Integer codigoClienteDe) {
  77.     this.codigoClienteDe = codigoClienteDe;
  78.   }
  79.  
  80.   public Integer getCodigoClienteAte() {
  81.     return codigoClienteAte;
  82.   }
  83.  
  84.   public void setCodigoClienteAte(Integer codigoClienteAte) {
  85.     this.codigoClienteAte = codigoClienteAte;
  86.   }
  87.  
  88. }
Listagem 4. Código da classe RunReport

Conclusões

Neste artigo vimos o que é e como funciona o framework JasperReports, passando pelas fases de criação do template, compilação e exportação. Vimos também que o arquivo de template nada mais é do que um arquivo XML que contém toda a estrutura do relatório.

Conhecemos também a ferramenta gráfica mais popular para o desenvolvimento de relatórios em Java, o iReport. Estudamos suas principais características e aspectos, como a criação de um datasource, inclusão de uma query para obtenção dos dados, além de alguns elementos básicos para compor o relatório.

Por fim, com um exemplo, aprendemos como compilar e invocar, a partir de uma aplicação web, um relatório do tipo JasperReports, o exibindo no formato PDF. Além disso, destacamos através deste exemplo como trabalhar com a rica API do JasperReports.

Mesmo tendo apresentado tantas informações, devido à riqueza do framework e da ferramenta analisada, por questões de espaço, boa parte de seu conteúdo não pôde ser estudado, porém, este pode ser um ótimo ponto de partida para quem quer começar ou está iniciando no JasperReports.