Manual Ireport

164
C:\Users\LucilioRocha\Documents\NetBeansProjects\GesTenis\relatorios\reportFornecedor.jr xml http://davidbuzatto.com.br/2010/10/10/jasperreports-trabalhando-com-relatorios-em-java- parte-2-primeiros-relatorios/ JasperReports: Trabalhando com Relatórios em Java Parte 1 (Configurando o Ambiente) Filed under: Desktop , Java , Programação , Relatórios 38 Comentários 09/10/2010 28 Votes Parte 1 Parte 2 Parte 3 Parte 4 Parte 5 Olá a todos. Quem acompanha o blog sabe que no último post há duas semanas atrás eu pedi que vocês sugerissem o tema para o próximo tutorial. Dentre os temas que eu listei, o de criação de relatórios em Java foi o que ganhou. Este tutorial, como o de Flex e Java, vai ser dividido em algumas partes. Eu poderia escrever em apenas um post tudo sobre o tema, mas preferi dividir o tutorial em várias partes pequenas menores que os tutoriais sobre Flex para não ficar muito cansativo. Nesta primeira parte (provavelmente a maior de todas), iremos aprender sobre o framework para criação relatórios que iremos utilizar, o JasperReports, entendendo seu funcionamento, aprendendo a obter e instalar o iReport, que é o editor de relatórios e preparar nosso ambiente de desenvolvimento. Irei novamente utilizar o NetBeans como IDE de desenvolvimento, mas você que usa o Eclipse ou qualquer outra IDE Java não vai ter dificuldades para seguir o tutorial. Na segunda parte, iremos criar uma base de dados de teste para popularmos nossos relatórios e vamos aprender como criar, compilar e utilizar os relatórios criados em aplicações desktop. Na terceira parte, iremos aprender a criar subrelatórios. Na quarta, iremos utilizar fontes de dados data sources diferentes, permitindo então que possamos listar dados nos relatórios que não vem somente de consultas SQL. Por fim, na quinta e última parte, iremos aprender como utilizar nossos relatórios em uma página Web. Após todas essas partes, vocês terão a bagagem necessária para caminharem sozinhos ;) Então, vamos começar!

description

Esclarecedor

Transcript of Manual Ireport

Page 1: Manual Ireport

C:\Users\LucilioRocha\Documents\NetBeansProjects\GesTenis\relatorios\reportFornecedor.jr

xml

http://davidbuzatto.com.br/2010/10/10/jasperreports-trabalhando-com-relatorios-em-java-

parte-2-primeiros-relatorios/

JasperReports: Trabalhando com Relatórios em Java –

Parte 1 (Configurando o Ambiente)

Filed under: Desktop, Java, Programação, Relatórios — 38 Comentários

09/10/2010

28 Votes

Parte 1 – Parte 2 – Parte 3 – Parte 4 – Parte 5

Olá a todos. Quem acompanha o blog sabe que no último post – há duas semanas atrás –

eu pedi que vocês sugerissem o tema para o próximo tutorial. Dentre os temas que eu

listei, o de criação de relatórios em Java foi o que ganhou. Este tutorial, como o de Flex

e Java, vai ser dividido em algumas partes. Eu poderia escrever em apenas um post tudo

sobre o tema, mas preferi dividir o tutorial em várias partes pequenas – menores que os

tutoriais sobre Flex – para não ficar muito cansativo.

Nesta primeira parte (provavelmente a maior de todas), iremos aprender sobre o

framework para criação relatórios que iremos utilizar, o JasperReports, entendendo seu

funcionamento, aprendendo a obter e instalar o iReport, que é o editor de relatórios e

preparar nosso ambiente de desenvolvimento. Irei novamente utilizar o NetBeans como

IDE de desenvolvimento, mas você que usa o Eclipse ou qualquer outra IDE Java não

vai ter dificuldades para seguir o tutorial.

Na segunda parte, iremos criar uma base de dados de teste para popularmos nossos

relatórios e vamos aprender como criar, compilar e utilizar os relatórios criados em

aplicações desktop. Na terceira parte, iremos aprender a criar subrelatórios. Na quarta,

iremos utilizar fontes de dados – data sources – diferentes, permitindo então que

possamos listar dados nos relatórios que não vem somente de consultas SQL. Por fim,

na quinta e última parte, iremos aprender como utilizar nossos relatórios em uma página

Web. Após todas essas partes, vocês terão a bagagem necessária para caminharem

sozinhos ;)

Então, vamos começar!

Page 2: Manual Ireport

Existem atualmente na indústria diferentes frameworks e engines para criação e

processamento de relatórios. Dentre as soluções pagas, talvez o Crystal Reports seja a

mais conhecida. O Crystal Reports é uma solução robusta e que pode ser utilizada com

diversas linguagens de programação. Outra solução paga que é muito utilizada por

quem trabalha com Delphi é o Quick Reports. Em Java, existem atualmente duas

soluções que são mais utilizadas. O JasperReports, que é o framework gratuito mais

popular e que iremos utilizar nos nossos tutoriais e o BIRT (Business Intelligence and

Reporting Tools) que também é gratuito e é mais utilizado por quem trabalha com o

Eclipse.

Como iremos utilizar o JasperReports, vale a pena então entendermos um pouco do seu

funcionamento. Quando trabalhamos com ele, nós criamos os arquivos de código fonte

dos nossos relatórios utilizando XML, sendo que esse arquivo fonte – de extensão

.jrxml – passa por um processo de compilação para gerar gerar arquivos .jasper, que por

sua vez são interpretados pela engine do JasperReports. Nós não iremos escrever esses

arquivos .jrxml na mão, pois iremos construir nossos relatórios utilizando um editor

WYSIWYG (What You See Is What You Get), o iReport. Atualmente, o iReport pode

ser obtido em duas versões. Uma delas é standalone (criada usando a NetBeans

Platform), não precisando de nenhum outro programa para ser utilizada, enquanto a

outra é um plugin para o NetBeans. Iremos utilizar a versão em plugin.

Bem, já falei demais. Chega de blablablá, vamos começar a por a mão na massa, afinal

essa é a melhor forma de aprender :D. Primeiro vamos baixar o iReport. Acesse então o

endereço http://jasperforge.org/projects/ireport e procure o link de download. Na versão

atual do site, para fazer o download, basta clicar no botão ―Download iReport Now―. Ao

clicar no botão, serão apresentadas as versões disponíveis. Nós vamos escolher a última:

Plugin for NetBeans IDE 3.x. A versão atual do iReport é a 3.7.5. Note que a versão do

iReport sempre vai ser a mesma do JasperReports.

Quando terminar de baixar, descompacte o arquivo ―iReport-3.7.5-plugin.zip‖ (a versão

pode variar dependendo de quando você baixar o pacote). Serão extraídos 4 arquivos

com a extensão .nbm (NetBeans Module). Esses arquivos são os pacotes dos plugins que

serão instalados no NetBeans. Com o arquivo descompactado, abra então o seu

NetBeans. Estou usando a útlima versão, 6.9.1. Com o NetBeans aberto, vá no menu

Tools (Ferramentas) e escolha Plugins. Ao abrir o gerenciador de plugins, vá na aba

Downloaded (Baixados?). É nessa aba que você instala os arquivos .nbm. Clique em

Add Plugins (Adicionar Plugins). Veja a Figura abaixo:

Page 3: Manual Ireport

Gerenciador de Plugins

Ao clicar no botão Add Plugins, um diálogo será aberto. Neste diálogo, procure então

pelos arquivos .nbm que foram descompactados a partir do pacote que fizemos

download. Assim que os encontrar, selecione todos e clique Open (Abrir). Veja a Figura

abaixo.

Page 4: Manual Ireport

Escolhendo os pacotes

Ao fazer isso, a janela do gerenciador de plugins será exibida novamente, só que agora

com os quatro pacotes sendo exibidos. Deixe os quatro pacotes marcados e clique em

Install (Instalar). Veja a Figura abaixo.

Page 5: Manual Ireport

Gerenciador de Plugins (instalação)

No primeiro passo do instalador, clique em Next (Próximo). Marque o checkbox para

concordar com os termos da instalação e clique em Install. Aguarde o final da

instalação. Quando a instalação terminar, provavelmente o NetBeans vai pedir para ser

reiniciado. Reinicie a IDE. Quando o ambiente estiver aberto novamente, você vai

perceber que na barra de ferramentas foi inserido um novo botão e um combobox. Ainda

não iremos aprender para que eles servem, por enquanto entenda que eles fazem parte

do plugin do iReport. Veja a Figura abaixo.

Barra de ferramentas alterada

Com o iReport instalado, vamos agora preparar a estrutura de uma aplicação que iremos

usar nas próximas partes do tutorial. Inicie a criação de um novo projeto no NetBeans

escolhendo um projeto do tipo Java Application (Aplicação Java). Veja a Figura abaixo.

Page 6: Manual Ireport

Novo projeto

Clique em Next. Em seguida, dê o nome ao projeto, sugiro ―TutorialRelatorios‖ (sem as

aspas), escolha onde o projeto vai ser salvo e marque a opção Use Dedicated Folder for

Storing Libraries (essa opção vai fazer com que todos os arquivos .jar utilizados fiquem

contidos dentro do projeto, sob o diretório ―lib‖), configure as outras opções de acordo

com a Figura abaixo e clique em Finish.

Page 7: Manual Ireport

Configurando o novo projeto

Ao clicar em Finish, o projeto vai ser criado. A partir de agora já poríamos começar a

criar nossos relatórios no iReport, mas ainda faltam algumas configurações para que

possamos fazer esses relatórios executarem dentro de uma aplicação. Para isso, ainda

temos que adicionar o JasperReports no nosso projeto, bem como todas as suas

dependências, além de termos também que organizar a estrutura do projeto para guardar

nossos relatórios.

Primeiro vamos tratar dos .jars. Ao instalar os plugins do pacote do iReport, uma

biblioteca padrão com os .jars é criada, mas ela vem com alguns erros, então vamos

criar a nossa biblioteca para não termos dores de cabeça depois. Para isso, expanda o nó

raiz do projeto e procure pelo nó Libraries (Bibliotecas). Clique com o botão direito e

escolha Add Library (Adicionar Biblioteca). Veja a Figura abaixo.

Page 8: Manual Ireport

Nova biblioteca

Ao clicar em Add Library, o diálogo para a inserção de bibliotecas será exibido. Neste

diálogo, clique no botão Create… (Criar). Veja a Figura abaixo.

Criando uma nova biblioteca

Ao clicar em Create, será exibido um novo diálogo, onde o nome e o tipo da nova

biblioteca devem ser definidos. Em Library Name (Nome da Biblioteca), configure

Page 9: Manual Ireport

como ―JasperReports-3.7.5″, lembrando de mudar o número da versão caso esteja

utilizando uma versão mais nova. Em Library Type (Tipo da Biblioteca), deixe como

Class Libraries (Bibliotecas de Classe). Por fim, clique no botão OK. Veja a Figura

abaixo.

Criando uma nova biblioteca

Ao clicar em OK, será exibido o diálogo Customize Library (Personalizar Biblioteca?).

É nele que indicaremos os .jars que fazem parte da nossa biblioteca. Quando instalamos

o plugin do iReport no NetBeans é criada uma pasta chamada ―ireport‖ dentro do

diretório de instalação e é lá que estão os .jars que precisamos. Sabendo disso, clique

então no botão Add JAR/Folder (Adicionar JAR/Diretório). Veja a Figura abaixo.

Page 10: Manual Ireport

Adicionando os JARs

Com o diálogo aberto, procure pelo diretório onde a instalação do NetBeans foi feita.

No meu caso, ele foi instalado em C:\Program Files (x86)\NetBeans 6.9.1\. Dentro deste

diretório, procure pelo diretório chamado ―ireport‖ e entre nele. O conteúdo do diretório

é exibido na Figura abaixo, sendo que os diretórios que nos interessam são o diretório

―libs‖ e o diretório ―modules‖ destacados na Figura.

Page 11: Manual Ireport

libs e modules

Primeiramente, acesse o diretório ―libs‖. Dentro dele, existe apenas um .jar (para a

versão 3.7.5 do iReports). Selecione esse .jar (xalan.jar) e clique em Add JAR/Folder.

Veja a Figura abaixo.

Adicionando xalan.jar

Ao clicar, o NetBeans vai perguntar se você deseja mesmo criar um diretório dentro do

diretório ―libs‖ (aquele que vai guardar nossas bibliotecas) com o nome de

Page 12: Manual Ireport

JasperReports-3.7.5 (o nome que demos para a biblioteca, lebram?). Responda Sim.

Veja a Figura abaixo.

Alerta de criação de novo diretório

Ao aceitar a criação do novo diretório, a janela Customize Libraries voltará a aparecer,

agora com o xalan.jar sendo mostrado na lista de .jars. Além da pasta ―libs‖, precisamos

adicionar também os .jars que estão dentro da pasta ―modules‖. Então clique novamente

no botão Add JAR/Folder da janela Customize Libraries e entre no diretório ―modules‖.

Dentro dele existirão alguns .jars, mas não são eles que queremos. Note que além dos

.jars, existe um diretório chamado ―ext‖. Entre nele. Neste diretório estão TODAS as

dependências do JasperReports. Para facilitar as coisas, iremos selecionar TODOS os

.jars. Em um projeto real, o mais sensato seria selecionar apenas os .jars que você tem

certeza que vão ser utilizados. Entretanto, esta abordagem traz um problema. O Jasper

utiliza nos bastidores muitos desses .jars, mesmo que a gente pense que não. Um

exemplo é o spring.jar :(. E o pior! A cada versão, as dependências mudam (já tive

vários problemas com isso). Minha recomendação é que você selecione TODOS os

.jars, e depois, caso já utilize um deles (por exemplo o Hibernate) recomendo então que

você atualize o .jar para a versão mais nova. Enfim, selecione TODOS e clique em Add

JAR/Folder. Veja a Figura abaixo.

Page 13: Manual Ireport

Jars do diretório modules/ext

Ao fazer isso, novamente a janela Customize Library vai ser exibida, mostrando que

todos os .jars foram inseridos. Clique em OK. Ao clicar, o diálogo Add Library será

exibido novamente, mas agora com a nova biblioteca criada. Selecione-a (já vai estar

selecionada por padrão) e clique em Add Library. Veja a Figura abaixo.

Adicionando a biblioteca no projeto

Fazendo isso, o diálogo será fechado e você vai perceber que todos os .jars aparecerão

dentro do projeto. Veja a Figura abaixo.

Page 14: Manual Ireport

Projeto com a biblioteca adicionada

Ok, já temos a biblioteca configurada com todos os .jars do JasperReports. Agora

vamos criar um diretório no nosso projeto para conter as definições dos nossos

relatórios (arquivos .jrxml). Para isso, clique com o botão direito no nó raiz do projeto e

escolha Properties (Propriedades). Veja a Figura abaixo.

Page 15: Manual Ireport

Acessando as propriedades do projeto

Ao clicar em Properties, a janela de propriedades do projeto será exibida. Nesta janela,

selecione o primeiro nó à esquerda (Source – Fonte) e do lado direito, na tabela Source

Package Folders, clique em Add Folder… (Adicionar Diretório). Veja a Figura abaixo.

Page 16: Manual Ireport

Propriedades do projeto

Ao clicar em Add Folder, um diálogo será exibido. Neste diálogo, clique no botão

localizado no canto superior direito. Veja a Figura abaixo.

Page 17: Manual Ireport

Botão para criar um novo diretório

Com isso, um novo diretório será criado. Dê o nome de ―relatorios‖ (sem as aspas e sem

acento agudo), selecione-o e clique em Open. Veja a Figura abaixo.

Page 18: Manual Ireport

Diretório "relatorios" criado

Ao clicar em Open, o novo diretório será inserido na tabela Source Package Folders. Na

primeira coluna é apresentado o caminho do diretório, enquanto na segunda coluna é

apresentado o label que vai identificar esse diretório dentro do projeto. Clique duas

vezes na célula da segunda coluna que corresponde ao label do diretório criado e dê o

nome de ―Relatórios‖. Cuidado! Ao terminar de editar o nome, tecle <ENTER>. Veja a

Figura abaixo.

Page 19: Manual Ireport

Configurando o novo diretório

Ao fazer isso, o label será configurado (saindo da edição) e você agora deve clicar no

botão OK das propriedades do projeto, aceitando assim as modificações que foram

feitas. Veja a Figura abaixo.

Page 20: Manual Ireport

Aceitando as configurações

Pronto, terminamos a configuração do projeto. Se tudo tiver dado certo, o novo diretório

será exibido na estrutura do projeto, sendo que ele será identificado pelo label que foi

configurado no passo anterior. Veja a Figura abaixo.

C:\Program Files\IreportPlugins

Page 21: Manual Ireport

Estrutura do projeto atualizada

Com isso terminamos a primeira parte do tutorial. Aprendemos alguns conceitos sobre o

JasperReports e como instalar o iReport. Aprendemos também a criar e a inserir uma

nova biblioteca no projeto, sendo que essa biblioteca corresponde aos .jars necessários

para nós utilizarmos o JasperReports no nosso programa (quando formos abrir o

relatório a partir do programa). Além disso, aprendemos a criar um diretório dedicado

aos nossos relatórios. Então é isso. Terminamos a primeira parte do tutorial. Com o

cenário pronto, agora podemos começar a brincar com o iReport e criar nossos

primeiros relatórios.

O projeto completo até o momento pode ser obtido neste link.

Fiquem ligados, a próxima parte vem ai ;)

Parte 1 – Parte 2 – Parte 3 – Parte 4 – Parte 5

JasperReports: Trabalhando com Relatórios em Java –

Parte 2 (Primeiros Relatórios)

Page 22: Manual Ireport

Filed under: Desktop, Java, Programação, Relatórios — 53 Comentários

10/10/2010

22 Votes

Parte 1 – Parte 2 – Parte 3 – Parte 4 – Parte 5

Olá! Nesta segunda parte do tutorial sobre criação de relatórios, vamos fazer nossos

primeiros exemplos, entretanto, para que possamos ver algum resultado, ou seja, nossos

relatórios preenchidos com valores, precisamos de uma base de dados para extrairmos

tais dados. Ao invés de criar uma base de dados na mão, iremos utilizar uma base já

pronta. Nos nossos exemplos, vamos utilizar o MySQL como SGBD e iremos utilizar

também o ―Sakila Sample Database‖ para extrairmos nossos dados. Essa base de dados,

é uma base de exemplo que é disponibilizada no site no MySQL

(http://dev.mysql.com/doc/sakila/en/sakila.html), que pode ser usada por

desenvolvedores para fazer testes com consultas SQL. Como nossos primeiros relatórios

vão trabalhar exclusivamente com SQL, vamos utilizar essa base de dados para facilitar

nossa vida.

Então, mãos a obra! Primeiramente, acesse http://dev.mysql.com/doc/index-other.html e

procure por ―Sample Databases―. Nesta seção, são apresentadas algumas bases de dados

de exemplo que podemos baixar. Procure pela sakila database e baixe a base de dados

escolhendo o formato desejado (TGZ ou Zip) na primeira coluna. Para facilitar, este link

é o link para baixar a versão em Zip.

Quando terminar de baixar o arquivo, descompacte-o. Dentro dele estão contidos três

arquivos:

1. sakila-schema.sql: é a estrutura da base de dados;

2. sakila-data.sql: são os dados da base de dados;

3. sakila.mwb: é um projeto do MySQL workbench (http://wb.mysql.com/).

Vamos então carregar os dois primeiros arquivos para o nosso SGBD. Para isso, abra o

MySQL Command Line Client, digite a senha do root e tecle <ENTER> para fazer o

login. Se estiver usando Linux, ou estiver com o bin do MySQL configurado no PATH

do Windows, faça o login no MySQL usando o comando ―mysql -u root -p‖ (sem as

aspas). Quando estamos logados no interpretador do MySQL, podemos utilizar alguns

comandos para a administração das bases de dados existentes. Um desses comandos é o

―source‖ que é utilizado para carregar e executar comandos do SGBD que estão

contidos em um arquivo de texto. Vamos utilizar então este comando para carregar os

dois primerios arquivos do sakila database (a estrutura e os dados). Copiei os arquivos

sakila-schema.sql e sakila-data.sql para o C: para facilitar a digitação do comando. Veja

Page 23: Manual Ireport

na Figura abaixo o comando sendo usado para a carga do primeiro arquivo (sakila-

schema.sql).

Usando o comando source para carregar o arquivo sakila-schema.sql

Assim que você digitar o comando ―source C:/sakila-schema.sql;‖ (sem as aspas) e

teclar <ENTER>, você vai ver que o interpretador do MySQL vai começar a processar o

arquivo, gerando várias saídas. Se tudo der certo, uma base de dados chamada ―sakila‖

será criada, bem como todas as tabelas da sua estrutura. Se quiser verificar que a base de

dados foi criada, basta dar o comando ―show databases;‖ (sem as aspas) para listar as

bases de dados existentes.

Como exercício, da mesma forma que você carregou o arquivo sakila-schema.sql, você

deve agora carregar o sakila-data.sql. Novamente os comandos serão processados e

agora, além da estrutura da base de dados (criada no passo anterior), temos também

vários dados para podermos utilizar em nossas consultas SQL e consequentemente em

nossos relatórios, mas antes de partirmos para os relatórios, vamos falar um pouquinho

da base de dados sakila. A seguir, uma imagem da estrutura da base, carregada no

MySQL Workbench (clique na imagem para ampliar).

Page 24: Manual Ireport

Estrutura da base de dados sakila

Na base de dados sakila estão modeladas diversas tabelas que representam os dados de

uma locadora de DVDs fictícia. Não vou ficar comentando cada tabela, pois apenas com

a leitura do diagrama você vai conseguir entender os relacionamentos entre as elas,

afinal, se você trabalha com bases de dados isso devere ser trivial :D.

Pronto! Agora sim! Vamos aos relatórios! Abra o NetBeans (se ainda não estiver

aberto) e carregue o projeto que criamos na Parte 1 do tutorial. Caso você só tenha lido

o tutorial, não se preocupe, você pode baixar o projeto feito na Parte 1 neste link. Com o

projeto aberto, expanda o nó ―Relatórios‖ do projeto. Você vai notar a existência do

default package (pacote padrão). É nele que vamos criar os arquivos de código fonte

dos nossos relatórios. Sendo assim, clique com o botão direito neste pacote e escolha

New -> Other… (Novo -> Outro…). Veja a Figura abaixo.

Page 25: Manual Ireport

Novo arquivo

Ao clicar em Other… a janela de novo arquivo arquivo será aberta. Em Categories

(Categorias) escolha Report (Relatório) e em File Types (Tipos de Arquivo) escolha

Empty report (Relatório vazio) e clique em Next (Próximo). Veja a Figura abaixo.

Page 26: Manual Ireport

Novo arquivo fonte de relatório

Ao clicar em Next, preencha o campo File Name (Nome do Arquivo) com ―Clientes‖

(sem as aspas) e clique em Finish (Finalizar/Terminar). Veja a Figura abaixo.

Page 27: Manual Ireport

Criando o novo arquivo fonte de relatório

Ao clicar em Finish, o arquivo de código fonte do relatório será criado (Clientes.jrxml)

e a interface de edição do relatório será aberta, com o arquivo Clientes.jrxml carregado.

Note que neste primeiro relatório, vamos simplesmente listar os dados de todos os

clientes, que por sua vez estão contidos na tabela customer da base de dados sakila.

Vamos agora conhecer a interface do editor do iReport. A Figura abaixo contém

diversas áreas numeradas que serão explicadas logo à seguir.

Page 28: Manual Ireport

Interface gráfica do editor WYSIWYG do iReport

1. Gerenciamento de Datasources (Fontes de Dados): A área 1, destacada em

amarelo, é utilizada para gerenciar os datasources que podem ser utilizados nos

testes dos relatórios que estão sendo criados;

2. Área de edição do relatório: A área 2, destacada em azul escuro, contém o

editor visual do relatório (descrito no item 3 a seguir), além de alguns botões

onde podemos visualizar o editor WYSIWYG (Design), o código fonte do

relatório (XML) e visualizar o relatório sendo executado (Preview), além de

podermos configurar a forma que o relatório vai obter os dados que serão

obtidos atravéz do datasource utilizado (primeiro botão após o botão Preview);

3. Editor do relatório: Essa área é utilizada para editar o formato do relatório,

onde cada texto vai aparecer, quais bandas ele vai ter, etc. Existem vários tipos

de bandas. As que são exibidas por padrão são:

o Title: correponde ao cabeçalho do relatório. Aparece somente na

primeira página;

o Page Header: cabeçalho da página. Aparece em todas as páginas;

o Column Header: cabeçalho das colunas. Aparece em todas as páginas;

o Detail: exibe os dados provenientes do datasource, ou seja, são os dados

que queremos mostrar no relatório;

o Column Footer: rodapé das colunas. Aparece em todas as páginas;

o Page Footer: rodapé da página. Aparece em todas as páginas;

o Summary: resumo do relatório. Aparece apenas na última página.

4. Paleta de componentes: Esta área contém os componentes que podem ser

utilizados para montar o relatório;

Page 29: Manual Ireport

5. Propriedades: Área utilizada para exibir e editar as propriedades de um

componente que esteja selecionado;

6. Report Inspector: É nesta área que as configurações do relatório são acessadas,

como quais parâmetros ele contém, quais os campos que são utilizados, quais

bandas estão visíveis, etc.;

7. Saída (Output): Nesta área são exibidos as saídas da execução e compilação do

relatório corrente.

Se a explicação de cada área ficou confusa, não se preocupe. Você vai entender tudo

daqui a pouco. Vamos começar então a mexer no nosso primeiro relatório. Primeiro

então temos que configurar um datasource que vai trazer os dados de algum lugar. Note

que esse datasource é utilizado apenas durante a edição do relatório. Quando formos

executar o relatório dentro de um programa, teremos que passar o datasource

programaticamente, mas isso nós vamos aprender depois. Pois bem, clique então no

botão Report datasources (Fontes de dados do relatório). Veja a Figura abaixo.

Botão Report datasources

Ao clicar neste botão, a janela de gerenciamento de datasources será exibida. Por

padrão, apenas um datasource vai estar configurado no iReport. Este datasource, o

Empty datasource (fonte de dados vazia) pode ser utilizado para visualizarmos apenas a

estrutura do relatório. Vamos então criar o datasource para a base de dados sakila. Para

isso, clique no botão New (Novo). Veja a Figura abaixo.

Page 30: Manual Ireport

Gerenciador de datasources

Ao clicar em New, uma nova janela será exibida. Nesta janela escolhemos o tipo de

datasource que vamos utilizar. No nosso caso, é um Database JDBC connection, pois

iremos obter os dados no nosso relatório utilizando uma query SQL, que por sua vez vai

ser executada através de uma conexão JDBC. Por padrão, este tipo de datasource é o

que vai estar selecionado no assistente. Caso não esteja selecionado, selecione-o e

clique em Next. Veja a Figura abaixo.

Page 31: Manual Ireport

Escolhendo o tipo de datasource

Ao clicar em Next, a janela de configuração do datasource vai ser exibida. Nela

precisamos preencher alguns campos:

Name: nome do datasource. Utilize ―Sakila – JDBC‖ (sem as aspas);

JDBC Driver: o tipo de driver que vamos utilizar. No nosso caso, é o driver do

MySQL;

JDBC URL: endereço do banco de dados que queremos utilizar. No nosso caso

é ―jdbc:mysql://localhost/sakila‖ (sem as aspas);

Username: nome do usuário. Estamos trabalhando em um ambiente de

desenvolvimento, então vamos usar o root;

Password: senha do usuário. No meu caso a senha do root é root também;

Save password: salvar a senha utilizada. Pode deixar marcada essa opção, se

não, toda hora que fizermos uma conexão, o iReport vai pedir a senha do

usuário.

Obs: os campos Server Address e Database são preenchidos apenas se você

quiser usar o Wizard (botão Wizard) para preencher a URL de conexão. Como já

Page 32: Manual Ireport

sabemos o formato da URL para o MySQL e já preenchemos o endereço, não

precisamos usar esses campos do Wizard.

Com tudo preenchido, clique em Save (Salvar). Veja a Figura abaixo.

Configurando o novo datasource

Ao salvar o datasource, a janela anterior será exibida, mostrando que o novo datasource

foi configurado e está marcado como default (Padrão). Clique em Close para fechar a

janela. Fazendo isso, você vai ver que o combobox que contém os datasources estará

exibindo o datasource padrão, ou seja, o ―Sakila – JDBC‖ que criamos. Isso significa

que quando formos criar uma query SQL no nosso relatório ou formos executá-lo para

testar (Preview), o iReport vai usar o datasource que estiver selecionado neste combo.

Novamente, reforço a ideia que este datasource é utilizado APENAS durante o

desenvolvimento do relatório, seja na montagem de queries ou testes do relatório.

Quando formos colocar o relatório para ser aberto em nosso programa, teremos que

Page 33: Manual Ireport

passar programaticamente o datasource que o nosso relatório irá usar. Veja a Figura

abaixo.

Datasource "Sakila - JDBC" selecionado

Muito bem. Configuramos o datasource que vamos utilizar e ele já está selecionado.

Vamos agora ao relatório. Vamos agora editar a query SQL do Clientes.jrxml. Para isso,

clique no botão que está destacado na Figura abaixo.

Acessando o editor de queries

Ao clicar no botão, a janela mostrada na Figura abaixo vai ser exibida.

Page 34: Manual Ireport

Editor de queries

Nesta janela é que vamos editar a query do nosso relatório. Ao inserir a query, os

campos que ela retorna serão automaticamente carregados. Para este relatório, queremos

listar todos os Clientes da locadora de DVDs, então iremos usar a query ―SELECT *

FROM customer;‖ (sem as aspas). Assim que a query for preenchida e executada com

sucesso, todos os campos que a execução dela retornar serão carregados, sendo que

seus respecitvos tipos também serão obtidos. Veja a Figura abaixo.

Page 35: Manual Ireport

Execução da query e carga dos campos

Observando a Figura acima, você pode perceber que ao executar a query informada

foram obtidos os campos customer_id (tipo Integer), store_id (tipo Integer), first_name

(tipo String) e assim por diante. Ao clicar em OK, esses campos (note que estão

selecionados) serão inseridos na definição do relatório, bastando agora nós pegarmos

esses campos e inserir cada um deles, ou os que nos forem relevantes, no Design do

relatório. Para pegar os campos, expanda o nó Fields (Campos) do Report Inspector.

Veja a Figura abaixo.

Page 36: Manual Ireport

Campos inseridos na definiçao do relatório

Suponha que queremos mostrar em nosso relatório apenas o nome, o sobrenome e o e-

mail de cada cliente. Sendo assim, selecione primeiro o campo ―first_name‖ e arraste

para a banda Detail do relatório. Veja a Figura abaixo.

Page 37: Manual Ireport

Iniciando a criação do relatório

Note que onde você soltou o campo fist_name (na bada Detail), foi inserida uma caixa

de texto do tipo Text Field (veja a paleta de componentes) com o valor $F{first_name},

onde $F denota o uso de um campo (F de Field) e o valor entre chaves é o nome do

campo. Na banda Column Header foi inserida outra caixa de texto, só que apenas com o

valor first_name. Essa caixa de texto inserida no cabeçalho da coluna é do tipo Static

Text, ou seja, é um texto estático. Vamos mudar então o valor dessa segunda caixa para

―Nome‖ (sem as aspas) e organizar tanto a caixa de texto estático quanto a de texto

dinâmico. Veja a Figura abaixo.

Page 38: Manual Ireport

Organizando o relatório

Vamos testar agora o relatório, afinal, queremos vê-lo funcionando. Procure pelo botão

Preview e clique nele. O relatório será compilado e exibido. Veja a Figura abaixo.

Page 39: Manual Ireport

Visualizando o relatório

Legal, já estamos vendo os dados que vem do banco de dados no relatório, mas afinal,

qual o motivo de um nome estar tão distante do outro? O motivo é que a banda Detail

está muito alta. A altura da banda Detail sempre vai ser replicada para cada registro

encontrado. Então, para melhorar isso, vamos diminuir a altura da banda Detail. Volte

então na visualização no Designer (usando o botão Designer), selecione a linha azul no

limite inferior da banda Detail e arraste até chegar na altura desejada. Caso você queira

que a banda fique com o tamanho do conteúdo dela (o que tem dentro dela), clique duas

vezes na linha azul. A banda vai ser redimensionada automaticamente. Veja a Figura

abaixo.

Page 40: Manual Ireport

Banda detail redimensionada

Teste novamente o relatório. Você vai notar que agora os nomes estão mais perto um do

outro. Agora, como exercício, arraste os campos last_name e email para o relatório (na

banda Detail) e organize-os. Note que você pode redimensionar cada campo tanto na

largura quanto na altura. Outra tarefa é voltar ao editor da query do relatório e inserir o

comando ORDER BY na query, para ordenar os registros pelo nome (first_name).

Quando fizer tudo isso e mandar visualizar, o resultado deve ser algo parecido com o

apresentado na Figura abaixo.

Page 41: Manual Ireport

Relatório atualizado

Vamos deixar agora o relatório um pouco mais apresentável. Da mesma forma que fez

com a banda Detail, diminua agora banda Colum Header. Clique com o botão direito na

banda Page Header e escolha Delete band. Na banda Title, insira uma caixa de texto

estática, troque o valor do texto para ―Clientes Cadastrados‖ (sem as aspas). Utilize o

editor de propriedades do componente (área 5 da Figura onde são apresentadas as áreas

do iReport) para configurar o tamanho da fonte do componente para 26, negrito (bold),

configure o alinhamento horizontal (horizontal alignment) para centro (center) e o

alinhamento vertical (vertical alignment) para meio (middle). Expanda o campo de texto

para ele ocupar toda a largura da página do relatório. Configure os campos que definem

as colunas da banda detail (aqueles campos de texto contidos no cabeçalho) para

ficarem em negrito. Execute novamente o relatório. Na Figura abaixo é mostrado como

seu relatório deve ter ficado no Preview.

Page 42: Manual Ireport

Editando o relatório

Para finalizar o design do nosso relatório, vamos adicionar o número de página na

banda Page Footer. No Report Inspector, procure pelo nó Variables e expanda-o. Uma

das variáveis pré-configuradas se chama PAGE_NUMBER. Arraste-a para o lado

direito da banda Page Footer e configure o alinhamento horizontal do texto para a

direita (right). Dimensione a altura da banda Page Footer para ficar do tamanho do

campo que foi inserido. Delete as bandas Column Footer e Summary (clique com o

botão direito e escolha delete band em cada uma delas). O design do relatório deve estar

como o da Figura abaixo.

Page 43: Manual Ireport

Design final do relatório

Teste seu relatório e veja que o número da página será exibido no final de cada página.

Note que o campo do campo de texto que foi inserido (um campo dinâmico) é

$V{PAGE_NUMBER}, sendo que o $V denota o uso de uma variável e o valor entre

chaves é o nome de variável. Ainda vamos ver como criar variáveis e parâmetros

manualmente (ainda não falei dos parâmetros).

Agora que já conseguimos criar nosso primeiro relatório, nós vamos aprender um

detalhe muito importante que se conhecido, muitos problemas podem ser evitados.

Quando usamos uma query no editor de queries e o iReport cria automaticamente os

campos (Fields) para nós, ele atributi automaticamente um tipo para cada campo,

dependendo, é claro, do tipo que aquele campo tem quando ele é obtido. Ou seja,

first_name é um campo VARCHAR na tabela customer, então quando esse valor é

obtido no iReport é criado um campo, com o nome first_name (o nome que vem por

padrão) do tipo String, que é a representação para cadeias de caracteres em Java.

Quando queremos usar um campo no nosso relatório, nós podemos arrastar ele

diretamente do Report Inspector para o relatório que o iReport vai se preocupar em criar

um campo dinâmico (Text Field na paleta) e inserir o valor $F{nome_do_campo}

dentro do campo dinâmico. Um detalhe que não vemos acontecer, justamente porque o

iReport faz automáticamente, é a configuração do tipo do campo dinâmico. O tipo do

campo dinâmico tem que ser SEMPRE igual ao tipo do campo que é utilizado.

Para entender o que eu falei, vamos fazer o seguinte teste. No relatório que estamos

criando, arraste para a banda Detail – na frente do campo para e-mail – um campo

dinâmico (Text Field na paleta). Por padrão, o valor do campo vai ser $F{field}. Se

você tentar executar o relatório, o iReport vai reclamar, falando que o campo ―field‖ não

existe. Isso é uma verdade, visto que nenhum campo com o nome field foi criado não é

mesmo? Vamos substituir o valor field para customer_id. O campo vai ficar então com

o valor $F{customer_id}. Tente executar o relatório para ver o que acontece.

Funcionou? Não! Mas qual o motivo? O erro diz ―Cannot cast from Integer to String―.

Isso quer dizer que o valor do campo customer_id é um Integer e o JasperReports está

sendo instruido a fazer um cast explícito de Integer para String. Mas de onde vem essa

String? Lembram que falei que o campo dinâmico (Text Field) tem que ter o mesmo

Page 44: Manual Ireport

tipo de um campo? Ou seja, o campo customer_id é do tipo Integer (inferido na criação

da query), enquanto o campo dinâmico que está inserido no relatório é do tipo String. O

que temos que fazer? Mudar o tipo do campo dinâmico. Para isso, selecione o campo

dinâmico que está na banda Detail e procure pela propriedade ―expression class‖ na

guia de propriedades do editor. O valor que estará lá é java.lang.String. Vamos mudar

para java.lang.Integer. Ao fazer isso, teste novamente o relatório. Agora funcinou não

é? Então, tenha sempre em mente que o tipo de um campo dinâmico tem que SEMPRE

SER DO MESMO TIPO que o campo ($F), a variável ($V), o parâmetro ($P), ou o

resultado de uma expressão que for executada na propriedade Text Field Expression do

campo dinâmico.

Legal, agora nós vamos fazer esse relatório ser executado a partir de um programa.

Lembram que eu falei que para um relatório ser executado, nós precisaríamos passar o

datasource que nós queremos que ele use? Pois bem, no nosso caso, o nosso datasource

é uma conexão JDBC (java.sql.Connection), sendo assim, vamos precisar criar

conexões para passar para a engine de execução do relatório. Vamos então criar uma

fábrica de conexões para utilizarmos. Essa fábrica é uma classe, com o nome

ConnectionFactory. Para criar a classe, primeiramente vá para a aba Projects do

NetBeans (canto superior esquerdo) expanda o nó Source Packages (pacotes de código

fonte) do nosso projeto, e no pacote ―tutorialrelatorios‖, crie um pacote chamado ―jdbc‖

(sem as aspas). Dentro então do pacote jdbc, crie uma classe chamada

ConnectionFactory. Segue o código comentado da classe.

tutorialrelatorios.jdbc.ConnectionFactory.java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

package tutorialrelatorios.jdbc;

import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException;

/** * Uma fábrica de conexões. * * @author David Buzatto */ public class ConnectionFactory { /* * Este bloco estático será executado assim que esta classe for

carregada, * sendo assim, será executado apenas uma vez. */ static { try { /* * Carrega a classe com.mysql.jdbc.Driver, que é a

implementação * do driver JDBC para o MySQL. */ Class.forName( "com.mysql.jdbc.Driver" ); // caso a classe não seja encontrada } catch ( ClassNotFoundException exc ) {

Page 45: Manual Ireport

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

/* * Como log usaremos o stacktrace das excessões, mas

recomendo * que para um projeto real você utilize algum mecanismo

de log * melhor, como o Log4J por exemplo. */ exc.printStackTrace();

} } /** * O método getConnection retorna uma conexão com o banco de

dados baseado * nos parâmetros fornecidos. * * @param url O endereço da base de dados. * @param usuario O usuário que tem permissão na base de dados

especificada. * @param senha A senha do usuário especificado * @return Uma conexão com o banco de dados especificado na url. * @throws SQLException Caso ocorra algum problema durante a

conexão. */ public static Connection getConnection( String url, String usuario, String senha ) throws SQLException { // retorna a conexão a partir do método getConnection de

DriverManager return DriverManager.getConnection( url, usuario, senha ); }

/** * Obtém uma conexão para a base de dados sakila. * * @return Uma conexão para a base de dados sakila. * @throws SQLException Caso ocorra algum problema durante a

conexão. */ public static Connection getSakilaConnection() throws SQLException { return getConnection( "jdbc:mysql://localhost/sakila", "root", "root" ); } }

Page 46: Manual Ireport

Usando o método getSakilaConnection() iremos então obter conexões para a base de

dados sakila, sendo que essa conexão será utilizada pelo JasperReports para executar as

queries que forem definidas nos relatórios.

Além da fábrica de conexões, vamos criar também uma classe que conterá métodos

utilitários para abrir relatórios. Para isso, crie um pacote chamado ―utils‖ (sem as aspas)

dentro do pacote ―tutorialrelatorios‖. Dentro do pacote criado, crie uma classe com o

nome de ReportUtils. Segue o código comentado da classe.

tutorialrelatorios.util.ReportUtils.java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

package tutorialrelatorios.util;

import java.awt.BorderLayout; import java.io.InputStream; import java.sql.Connection; import java.util.Map; import javax.swing.JFrame; import net.sf.jasperreports.engine.JRDataSource; import net.sf.jasperreports.engine.JRException; import net.sf.jasperreports.engine.JasperFillManager; import net.sf.jasperreports.engine.JasperPrint; import net.sf.jasperreports.swing.JRViewer;

/** * Classe com métodos utilitários para executar e abrir relatórios. * * @author David Buzatto */ public class ReportUtils { /** * Abre um relatório usando uma conexão como datasource. * * @param titulo Título usado na janela do relatório. * @param inputStream InputStream que contém o relatório. * @param parametros Parâmetros utilizados pelo relatório. * @param conexao Conexão utilizada para a execução da query. * @throws JRException Caso ocorra algum problema na execução

do relatório */ public static void openReport( String titulo, InputStream inputStream, Map parametros, Connection conexao ) throws JRException { /* * Cria um JasperPrint, que é a versão preenchida do

relatório, * usando uma conexão. */ JasperPrint print = JasperFillManager.fillReport( inputStream, parametros, conexao ); // abre o JasperPrint em um JFrame viewReportFrame( titulo, print );

Page 47: Manual Ireport

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

}

/** * Abre um relatório usando um datasource genérico. * * @param titulo Título usado na janela do relatório. * @param inputStream InputStream que contém o relatório. * @param parametros Parâmetros utilizados pelo relatório. * @param dataSource Datasource a ser utilizado pelo relatório. * @throws JRException Caso ocorra algum problema na execução

do relatório */ public static void openReport( String titulo, InputStream inputStream, Map parametros, JRDataSource dataSource ) throws JRException {

/* * Cria um JasperPrint, que é a versão preenchida do

relatório, * usando um datasource genérico. */ JasperPrint print = JasperFillManager.fillReport( inputStream, parametros, dataSource );

// abre o JasperPrint em um JFrame viewReportFrame( titulo, print ); }

/** * Cria um JFrame para exibir o relatório representado pelo

JasperPrint. * * @param titulo Título do JFrame. * @param print JasperPrint do relatório. */ private static void viewReportFrame( String titulo, JasperPrint print ) { /* * Cria um JRViewer para exibir o relatório. * Um JRViewer é uma JPanel. */ JRViewer viewer = new JRViewer( print ); // cria o JFrame JFrame frameRelatorio = new JFrame( titulo ); // adiciona o JRViewer no JFrame frameRelatorio.add( viewer, BorderLayout.CENTER ); // configura o tamanho padrão do JFrame frameRelatorio.setSize( 500, 500 );

// maximiza o JFrame para ocupar a tela toda. frameRelatorio.setExtendedState( JFrame.MAXIMIZED_BOTH );

Page 48: Manual Ireport

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

// configura a operação padrão quando o JFrame for fechado. frameRelatorio.setDefaultCloseOperation(

JFrame.DISPOSE_ON_CLOSE );

// exibe o JFrame frameRelatorio.setVisible( true ); }

}

Não vamos criar uma interface gráfica para executar nosso relatório, pois vamos abri-lo

diretamente da classe Main do projeto. Perceba que o código usado na classe Main é o

mesmo que você vai utilizar, por exemplo, para abrir o relatório a partir do clique de um

botão, mas antes disso, mais alguns detalhes. Quando fazemos o preview do relatório, o

iReport invoca o compilador do JasperReports para compilar o arquivo .jrxml em um

arquivo .jasper, para então executar o arquivo .jasper, abrindo assim o relatório. Você

deve ter percebido que agora, além do arquivo Clientes.jrxml, existe também o arquivo

Clientes.jasper na nossa pasta de definições de relatórios. Se você quiser compilar

manualmente um relatório sem entrar no preview do mesmo, basta ir no Report

Inspector, com o relatório desejado aberto, clicar com o botão direito no nó raiz do

relatório, que por padrão tem o nome de ―report name‖ (nome do relatório) e escolher

Compile Report (Compilar Relatório).

Vamos então executar nosso relatório a partir do método main da classe Main do nosso

projeto. Segue o código comentado da classe.

1

2

3

4

5

6

7

8

9

10

11

12

13

package tutorialrelatorios; import java.io.InputStream; import java.sql.SQLException; import java.util.HashMap; import java.util.Map; import net.sf.jasperreports.engine.JRException; import tutorialrelatorios.jdbc.ConnectionFactory; import tutorialrelatorios.util.ReportUtils; /** * Ponto de entrada do projeto. * * @author David Buzatto */ public class Main {

Page 49: Manual Ireport

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

/** * @param args the command line arguments */ public static void main(String[] args) { new Main().abrirRelatorioClientes(); }

public void abrirRelatorioClientes() { /* * Obtendo o arquivo do relatório. * Note que estamos utilizando um InputStream para obter o

arquivo que * está dentro do nosso projeto. Fazendo isso, não teremos

problema * quando nosso projeto for empacotado em um .jar. * * Note que o caminho do .jasper inicia com /, ou seja, a

raiz da * localização das classes compiladas do nosso projeto * (o pacote default). * * Utilize a aba Files (canto superior esquerdo) e veja que

os arquivos * .jasper e .jrxml são copiados para o diretório

/build/classes * e por consequencia para o .jar que for criado. * * Se não os estiver vendo, mande dar um Clean and Build no

projeto * (botão direito no nó raiz do projeto, Clean and Build

(Limpar e Construir) * */ InputStream inputStream = getClass().getResourceAsStream(

"/Clientes.jasper" ); // mapa de parâmetros do relatório (ainda vamos aprender a

usar) Map parametros = new HashMap(); try {

// abre o relatório ReportUtils.openReport( "Clientes", inputStream,

parametros, ConnectionFactory.getSakilaConnection() ); } catch ( SQLException exc ) { exc.printStackTrace(); } catch ( JRException exc ) { exc.printStackTrace(); } }

}

Page 50: Manual Ireport

64

Tente executar o projeto teclando F6. Uma excessão será lançada

(java.lang.ClassNotFoundException: com.mysql.jdbc.Driver). Isso se deve ao fato de

que nós ainda não colocamos o driver do MySQL no nosso projeto! Clique então em

Libraries com o botão direito e escolha Add Library. Como as bibliotecas do nosso

projeto ficam inseridas no projeto e não nas configurações do NetBeans, temos que criar

a biblioteca como fizemos com o JasperReports e suas dependências. Mas ao invés de

fazer todo aquele processo na mão, nós podemos importar bibliotecas que estão

configuradas no NetBeans sendo que o driver do MySQL é uma delas. Sendo assim, na

janela que se abriu, clique no botão Import. Ao fazer isso, a janela Import Library irá

aparecer. Procure pela biblioteca ―MySQL JDBC Driver‖, selecione-a e clique no botão

Import Library. Com isso a biblioteca do driver do MySQL será importada para o

projeto. Você vai ver ela na janela que apareceu novamente. Selecione-a e clique em

Add Library. Após fazer isso, tecle F6 novamente para executar o projeto.

Agora sim, uma janela com o relatório será aberta. Experimente utilizar os controles da

janela, tente salvar o relatório em vários formatos, etc. Após brincar um pouco com

isso, feche a janela e vamos a mais algumas explicações para finalizarmos esta parte do

tutorial.

Ao ler os comentários da classe Main, você deve ter percebido duas coisas. Primeiro, o

arquivo .jrxml está sendo copiado para a estrutura compilada do nosso projeto (build) e

por consequência, o arquivo .jrxml vai ser empacotado no .jar, sendo que só queremos

distribuir o arquivo compilado (.jasper). Segundo, ainda não aprendemos a utilizar o

mapa de parâmetros e ainda não foi explicado qual a sua utilidade.

Em relação ao primeiro problema, para excluir certos tipos de arquivos do processo de

build, abra as propriedades do projeto e localize o nó Packaging, dentro do nó Build. Ao

clicar nesta opção, você vai ver um campo chamado ―Exclude From JAR File―. Neste

campo, você informa o padrão de nome dos arquivos que você NÃO QUER que sejam

inseridos no build. Por padrão, o valor é ―**/*.java,**/*.form‖, ou seja, qualquer

arquivo, de qualquer diretório do projeto que tenha extensão ―java‖ e qualquer arquivo,

de qualquer diretório do projeto que tenha extensão ―form‖. Precisamos inserir então

nessa lista os arquivos de extensão ―jrxml‖. Para fazer isso, basta adicionar um item na

lista com o valor ―**/*.jrxml‖ (sem as aspas). O valor final do campo deve ser

―**/*.java,**/*.form, **/*.jrxml‖ (sem as aspas). Ao fazer isso, clique em OK e mande

limpar e refazer o build no projeto (botão direito no nó raiz do projeto, opção Clean and

Build – Limpar e Construir). Vá novamente na aba Files (canto superior esquerdo) e

expanda a pasta /build/classes. Você vai ver que agora somente o arquivo .jasper está

sendo copiado para o build.

Tudo bem até aqui? Espero que sim. Estamos acabando. Agora vamos a parte final, os

parâmetros.

Quando criamos listagens de dados em relatórios, normalmente nós queremos filtrar tais

dados, nos baseando em alguma restrição. Imagine que no nosso relatório de clientes,

nós queiramos filtrar os clientes existentes a partir do primeiro nome deles. Para isso,

teremos que inserir uma restrição na query do relatório para comparar o primeiro nome

com o valor que queremos filtrar. Modificar a query é fácil, mas nós precisamos que

Page 51: Manual Ireport

esse valor que será utilizado na query seja dinâmico, ou seja, a cada vez que

executarmos o relatório, queremos que o valor de restrição seja diferente. Para utilizar

esses valores dinâmicos no iReport, nós usamos os chamados parâmetros. Vamos então

fazer uma cópia do nosso primeiro relatório para inserirmos esse tipo de restrição.

Na aba Projects, procure pelo arquivo Clientes.jrxml na pasta de definições de

relatórios. Clique com o botão direito nele e escolha Copy (Copiar). Clique com o botão

direito no pacote default da pasta de definições de relatórios e escolha Paste (Colar). O

arquivo será colado com o nome de Clientes_1.jrxml. Selecione o arquivo, tecle F2 (ou

botão direito, rename – renomear) e troque o nome para ClientesPorNome.jrxml. Ao

fazer isso, abra o ClientesPorNome.jrxml no editor de relatórios.

Com o arquivo aberto, vá no Report Inspector e procure pela banda Page Header que

estará sendo exibida em cinza claro. Está assim porque ela foi removida lembra? Para

fazer ela aparecer novamente no relatório, clique com o botão direito nela e escolha Add

Band (Adicionar Banda). Ainda não vamos mexer com essa banda, mas só para

adiantar, ela vai ser utilizada para mostrar o filtro que estamos fazendo.

Ainda no Report Inspector, procure pelo nó Parameters (Parâmetros) e expanda-o.

Você vai ver que existem diversos parâmetros pré-configurados no nosso relatório. Nós

queremos criar mais um. Para isso, clique com o botão direito em Parameters e escolha

Add Parameter. Um novo parâmetro, com o nome ―parameter1″ vai ser criado.

Selecione-o e troque o nome dele para ―primeiroNome‖. Perceba que ao selecionar um

parâmetro, o editor de propriedades do iReport mostra diversas propriedades, entre elas

a classe do parâmetro (Parameter Class). Da mesma forma que os campos e variáveis

do relatório, os parâmetros também precisam de um tipo. Este parâmetro que estamos

criando vai ser utilizado no filtro da query, ou seja, ele vai conter o valor que queremos

utilizar como filtro. Um nome é uma String não é? Então a classe desse parâmetro é a

java.lang.String mesmo, mas imagine que queiramos comprar um número. Então a

classe teria que ser de algum tipo numérico ok?

Note também que a propriedade ―Use as prompt‖ deve estar selecionada. Essa

propriedade é utilizada para que quando formos dar o preview no relatório, seja aberto

um diálogo para pedir o valor que queremos que o parâmetro assuma naquela execução.

Execute o relatório para ver isso acontecer. Veja a Figura abaixo.

Page 52: Manual Ireport

Prompt de parâmetro

Mesmo que você informe qualquer valor para o parâmetro, o resultado do relatório vai

ser o mesmo, afinal, não inserimos o parâmetro na query do relatório não é mesmo?

Vamos fazer isso agora. Abra o editor de queries do relatório e edite a query para ficar

assim:

1

2

3

SELECT * FROM customer WHERE first_name LIKE $P{primeiroNome} ORDER BY first_name;

Após editar, clique em OK. Note que foi inserido uma cláusula WHERE na query,

comparando o campo first_name com o valor do parâmetro, usando o operador LIKE.

Note que para utilizarmos o valor do parâmetro, utilizamos a notação

―$P{nomeDoParametro}‖. Imagine que na hora da execução, o parâmetro assuma o

valor ―D%‖, ou seja, queremos qualquer cliente com o nome que inicie com a letra D. A

query na hora da execução ficaria assim:

1

2

3

SELECT * FROM customer WHERE first_name LIKE 'D%' ORDER BY first_name;

Perceberam o que estamos fazendo? Note que as aspas simples serão inseridas

automaticamente pelo JasperReports na hora da execução, pois o parâmetro

primeiroNome é uma String. Teste o relatório e passe no valor do paramâmetro como

‗D%‘ (sem as aspas). O resultado deve estar parecido com o da Figura abaixo.

Page 53: Manual Ireport

Resultado do relatório passando D% no valor do parâmetro

Legal não é? Então caso você queira inserir mais restrições no relatório, basta criar mais

parâmetros e ir modificando a query. Faça mais alguns testes ;). Vamos agora mostrar

para o usuário qual foi a restrição que foi pedida no relatório. Lembram da banda Page

Header que colocamos novamente no relatório? Insira nela um campo de texto estático

(Static Text) e preencha-o com o valor ―Com nome:‖ (sem as aspas), alinhe o texto à

direita e escolha para ficar em negrito (bold). Na frente deste campo, insia um campo

dinâmico (Text Field) e edite seu valor para ―$P{primeiroNome}‖ (sem as aspas).

Percebeu o que estamos fazendo? Vamos mostrar o valor do parâmetro no relatório

também! Lembre-se que o tipo do campo dinâmico tem que ser o mesmo do valor que

ele vai mostrar, no caso uma String, que é o tipo do parâmetro ―primeiroNome‖.

Coloquei também algumas linhas (componente Line da paleta) no relatório para ficar

mais bonitinho ;). Veja a Figura abaixo para ver como ficou.

Page 54: Manual Ireport

Design do relatório finalizado

Muito bem! Agora, para que este novo relatório funcione corretamente quando formos

utilizá-lo no nosso programa, nós precisamos passar o parâmetro que foi configurado

não é mesmo? Lembram do mapa de parâmetros que foi criado? Do tipo Map<String,

Object>? É nele que passamos o valor dos parâmetros. A chave do mapa é uma String,

que vai corresponder ao nome do parâmetro (no nosso caso, primeiroNome). O valor do

item do mapa é um Object, mas precisamos passar instâncias de objetos que casem com

o tipo do parâmetro configurado no relatório. No nosso caso, primeiroNome é do tipo

String lembram? Então o objeto que tem que ser passado no valor do item do mapa

precisa ser uma String, por causa do tipo do parâmetro como já falei. Veja o código

alterado do método abrirRelatorioClientes() da classe Main.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

public void abrirRelatorioClientes() { // note que estamos chamando o novo relatório InputStream inputStream = getClass().getResourceAsStream(

"/ClientesPorNome.jasper" ); // mapa de parâmetros do relatório Map parametros = new HashMap(); /* * Insere o parâmetro primeiroNome no mapa, com o valor F% * ou seja, todos os clientes que tenham primeiro nome começando * com a letra F. */ parametros.put( "primeiroNome", "F%" );

// outros possíveis parâmetros aqui... try { // abre o relatório ReportUtils.openReport( "Clientes", inputStream, parametros, ConnectionFactory.getSakilaConnection() );

Page 55: Manual Ireport

21

22

23

24

25

26

27

28

29

30

} catch ( SQLException exc ) { exc.printStackTrace(); } catch ( JRException exc ) { exc.printStackTrace(); } }

Perceba que caso existam mais parâmetros a serem enviados ao relatório, eles devem ser

inseridos no mesmo mapa. Outro detalhe é que estamos apenas fazendo um exemplo e

passando um valor fixo no parâmetro. Em um caso real, o valor a String ―F%‖ viria de

um campo de texto ou qualquer outro componente da sua interface gráfica.

Com isso terminamos a segunda parte do nosso tutorial. Espero que tenham gostado :).

Na próxima parte iremos aprender a trabalhar com os ―temidos‖ subrelatórios :D. Digo

―temidos‖ porque são um pouco chatos de usar e se você não souber realmente o que

está fazendo e como eles funcionam, você pode ficar um dia inteiro tentando fazer

funcionar e não conseguir :(

Neste link você pode fazer o download do código fonte do projeto até o momento.

Então é isso ai. Um grande abraço!

Parte 1 – Parte 2 – Parte 3 – Parte 4 – Parte 5

JasperReports: Trabalhando com Relatórios em Java –

Parte 3 (Subrelatórios)

Filed under: Desktop, Java, Programação, Relatórios — 23 Comentários

14/10/2010

16 Votes

Page 56: Manual Ireport

Parte 1 – Parte 2 – Parte 3 – Parte 4 – Parte 5

Olá! Hoje vamos aprender a trabalhar com subrelatórios no JasperReports, mas antes de

começar quero explicar algumas coisas. Nos últimos posts, eu tenho tentado formatar os

termos em inglês em itálico e colocar logo em seguida a tradução. Eu vou parar de fazer

isso. Primeiro, pq os termos são simples, e qualquer pessoa que trabalhe com

informática tem mais que obrigação de saber. Segundo, gasto muito tempo formatando

cada parágrafo, revisando se está tudo ok, etc. Então, para agilizar o processo, estou

deixando de lado essa prática. Tenho também tratado os leitores cada hora de um jeito.

Uma hora escrevo na primeira pessoa do singular, na outra, escrevo na terceira do

plural. Vou tentar manter a mesma narração, mas se eu cometer algum deslize, não se

encomodem ok? Então, vamos começar!

Se você já tentou trabalhar com subrelatórios, provavelmente teve algumas frustrações

até conseguir fazer funcionar. Se você nunca trabalhou, hoje vai aprender! Trabalhar

com subrelatórios não é difícil, o problema é entender como as coisas funcionam, mas

antes de falar disso, vamos nos situar no tema. O que é um subrelatório? Como o

próprio nome diz é um relatório que fica dentro de um outro relatório, ou seja, é uma

parte de um relatório maior, mais geral. Vamos entender por meio de um exemplo. Para

isso, abra o diagrama da base de dados sakila clicando aqui e imagine a seguinte

situação: você precisa criar um relatório, onde serão exibidos os dados de todos os

clientes e de todos os filmes que cada um alugou. O layout do relatório teria que ficar

mais ou menos assim:

Page 57: Manual Ireport

Rascunho do layout do relatório de filmes por cliente

Como criar um relatório com esse layout? Usando subrelatórios! A parte mais externa

do layout representa o arquivo de relatório mais geral, onde serão listados os clientes e

onde será inserido o subrelatório. O subrelatório, destacado em azul, será um outro

arquivo de relatório que será utilizado dentro do relatório mais geral. Confuso? Calma,

calma, logo vocês vão enteder. Antes disso, um pouquinho mais de teoria.

O funcionamento de um subrelatório é igual ao de um relatório normal, sendo que existe

apenas uma diferença e é justamente aqui que as pessoas se confundem. Os parâmetros

de um subrelatório não são enviados diretamente do código Java como é feito em um

relatório normal. No caso dos subrelatórios, os parâmetros são enviados pelo relatório

que os contém, para então serem passados ao subrelatório. Então, caso você passe um

parâmetro para o relatório que deve ser usado apenas no subrelatório, o seu relatório vai

ter que ter o ―mesmo‖ parâmetro e você vai ter que criar essa ponte entre o relatório

principal e o subrelatório. Veja a Figura abaixo.

Page 58: Manual Ireport

Parâmetros sendo passados entre as camadas de relatórios

Em vermelho é destacada a transmissão dos parâmetros a partir da aplicação em Java

para o relatório. Esses parâmetros são enviados usando o mapa da parâmetros lembram?

Em laranja é destacada a transmissão dos parâmetros para o subrelatório a partir do

relatório. Veja então que o relatório vai servir de ponte entre os parâmetros desejados,

além de poder criar novos parâmetros e os enviar para o subrelatório. Outro detalhe é

que podem haver diversos níveis de relatórios, ou seja, um subrelatório pode enviar

parâmetros para um subsubrelatório, um subsubrelatório pode enviar parâmetros para

um subsubsubrelatório, e assim por diante.

Finalmente! Vamos à prática! Abra o NetBeans e o projeto que estamos usando

(TutorialRelatorios). Se você não acompanhou a parte anterior do tutorial, ou mesmo

que tenha acompanhado e não tenha feito o exemplo, você pode baixar a versão do

projeto (finalizada na Parte 2) clicando aqui. Na pasta de definições de relatórios que

criamos, crie um novo Empty Report e dê o nome de LocacoesPorClientes. O arquivo

LocacoesPorClientes.jrxml vai ser criado. Caso ele não abra automaticamente no editor,

clique duas vezes para ser carregado no iReport.

Page 59: Manual Ireport

Com o arquivo aberto, vamos primeramente criar um relatório simples, que lista os

clientes a partir de uma pesquisa pelo nome. A query deste relatório vai ser um pouco

mais complexa que a do relatório ―ClientesPorNome‖, criado na Parte 2 do tutorial, pois

nela iremos obter outros dados do cliente que não estão na tabela customer. Não se

esqueça de escolher o datasource correto, o ―Sakila – JDBC‖ ok? Crie também um

parâmetro, do tipo String, com o nome de ―nomeCliente‖. Segue então a query que deve

ser inserida no relatório:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

SELECT

c.customer_id idCliente,

c.first_name nome,

c.last_name sobrenome,

c.email email,

a.address endereco,

a.phone telefone,

ci.city nomeCidade,

co.country nomePais

FROM

customer c,

address a,

city ci,

country co

WHERE

/* junções */

c.address_id = a.address_id AND

a.city_id = ci.city_id AND

ci.country_id = co.country_id AND

/* restrições */

c.first_name LIKE $P{nomeCliente}

Page 60: Manual Ireport

24

25

26

ORDER BY c.first_name;

Ao inserir a query, o iReport vai carregar os campos retornados por ela. Ao clicar em

OK, os campos carregados serão criados na definição do relatório. Os fields lembram?

Expanda então o nó Fields do Report Inspector e arraste e organize esses campos na

banda Detail do relatório. Veja como ficou o meu.

Layout do relatório de locações por clientes

Note que coloquei campos estáticos na banda Detail, tirei as bandas Column Header,

Column Footer e Summary. Criei um parâmetro chamado ―nomeUsuario‖ para mostrar

no cabeçalho da página o nome do usuário do ―sistema‖ que gerou o relatório. Outra

coisa que fiz foi colocar a data e hora que o relatório foi gerado na banda Page Header.

Note que para o uso da data e do formato, foi usado um campo de texto dinâmico, com

o tipo java.util.Date e a propriedade pattern alterada para ―dd/MM/yyyy‘, às‘

HH:mm‘hs'‖ (sem as aspas). Note também que o valor deste campo é gerado a partir de

um código Java! Segue o fonte em XML do relatório. Basta copiar e colar no seu

relatório (usando o botão XML).

LocacoesPorClientes.jrxml

Page 61: Manual Ireport

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

<?xml version="1.0" encoding="UTF-8"?>

<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperrepor

ts http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="report name" pageWidth="595" pageHeight="842" columnWidth="535" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20">

<property name="ireport.zoom" value="1.0"/>

<property name="ireport.x" value="0"/>

<property name="ireport.y" value="0"/>

<parameter name="nomeCliente" class="java.lang.String"/>

<parameter name="nomeUsuario" class="java.lang.String"/>

<queryString>

<![CDATA[SELECT

c.customer_id idCliente,

c.first_name nome,

c.last_name sobrenome,

c.email email,

a.address endereco,

a.phone telefone,

ci.city nomeCidade,

co.country nomePais

FROM

customer c,

address a,

city ci,

country co

WHERE

/* junções */

Page 62: Manual Ireport

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

c.address_id = a.address_id AND

a.city_id = ci.city_id AND

ci.country_id = co.country_id AND

/* restrições */

c.first_name LIKE $P{nomeCliente}

ORDER BY c.first_name;]]>

</queryString>

<field name="idCliente" class="java.lang.Integer"/>

<field name="nome" class="java.lang.String"/>

<field name="sobrenome" class="java.lang.String"/>

<field name="email" class="java.lang.String"/>

<field name="endereco" class="java.lang.String"/>

<field name="telefone" class="java.lang.String"/>

<field name="nomeCidade" class="java.lang.String"/>

<field name="nomePais" class="java.lang.String"/>

<background>

<band splitType="Stretch"/>

</background>

<title>

<band height="75" splitType="Stretch">

<staticText>

<reportElement x="0" y="18" width="555" height="40"/>

<textElement textAlignment="Center" verticalAlignment="Middle">

<font size="25" isBold="true"/>

</textElement>

<text><![CDATA[Locações por Clientes]]></text>

</staticText>

Page 63: Manual Ireport

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

<line>

<reportElement x="0" y="1" width="555" height="1"/>

</line>

<line>

<reportElement x="0" y="74" width="555" height="1"/>

</line>

</band>

</title>

<pageHeader>

<band height="21" splitType="Stretch">

<staticText>

<reportElement x="-1" y="0" width="51" height="20"/>

<textElement textAlignment="Left" verticalAlignment="Middle">

<font isBold="true"/>

</textElement>

<text><![CDATA[Usuário:]]></text>

</staticText>

<textField>

<reportElement x="53" y="0" width="150" height="20"/>

<textElement verticalAlignment="Middle"/>

<textFieldExpression class="java.lang.String"><![CDATA[$P{nomeUsuario}]]></textFieldExpre

ssion>

</textField>

<staticText>

<reportElement x="360" y="0" width="68" height="20"/>

<textElement textAlignment="Left" verticalAlignment="Middle">

<font isBold="true"/>

</textElement>

<text><![CDATA[Gerado em:]]></text>

Page 64: Manual Ireport

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

10

0

10

1

10

2

10

3

10

4

10

</staticText>

<textField pattern="dd/MM/yyyy&apos;, às&apos;

HH:mm&apos;hs&apos;">

<reportElement x="433" y="0" width="122" height="20"/>

<textElement verticalAlignment="Middle"/>

<textFieldExpression class="java.util.Date"><![CDATA[new Date()]]></textFieldExpression>

</textField>

</band>

</pageHeader>

<detail>

<band height="110" splitType="Stretch">

<staticText>

<reportElement x="0" y="3" width="50" height="20"/>

<textElement textAlignment="Left" verticalAlignment="Middle">

<font isBold="true"/>

</textElement>

<text><![CDATA[Nome:]]></text>

</staticText>

<textField>

<reportElement x="0" y="23" width="99" height="20"/>

<textElement verticalAlignment="Middle"/>

<textFieldExpression class="java.lang.String"><![CDATA[$F{nome}]]></textFieldExpression>

</textField>

<staticText>

<reportElement x="103" y="3" width="70" height="20"/>

<textElement textAlignment="Left" verticalAlignment="Middle">

<font isBold="true"/>

</textElement>

Page 65: Manual Ireport

5

10

6

10

7

10

8

10

9

11

0

11

1

11

2

11

3

11

4

11

5

11

6

11

7

11

8

11

9

12

0

12

1

12

<text><![CDATA[Sobrenome:]]></text>

</staticText>

<textField>

<reportElement x="103" y="23" width="136" height="20"/>

<textElement verticalAlignment="Middle"/>

<textFieldExpression class="java.lang.String"><![CDATA[$F{sobrenome}]]></textFieldExpress

ion>

</textField>

<staticText>

<reportElement x="242" y="3" width="70" height="20"/>

<textElement textAlignment="Left" verticalAlignment="Middle">

<font isBold="true"/>

</textElement>

<text><![CDATA[E-mail:]]></text>

</staticText>

<textField>

<reportElement x="242" y="23" width="228" height="20"/>

<textElement verticalAlignment="Middle"/>

<textFieldExpression class="java.lang.String"><![CDATA[$F{email}]]></textFieldExpression>

</textField>

<staticText>

<reportElement x="0" y="47" width="59" height="20"/>

<textElement textAlignment="Left" verticalAlignment="Middle">

<font isBold="true"/>

</textElement>

<text><![CDATA[Endereço:]]></text>

</staticText>

Page 66: Manual Ireport

2

12

3

12

4

12

5

12

6

12

7

12

8

12

9

13

0

13

1

13

2

13

3

13

4

13

5

13

6

13

7

13

8

13

<textField>

<reportElement x="62" y="47" width="177" height="20"/>

<textElement verticalAlignment="Middle"/>

<textFieldExpression class="java.lang.String"><![CDATA[$F{endereco}]]></textFieldExpressi

on>

</textField>

<staticText>

<reportElement x="473" y="3" width="82" height="20"/>

<textElement verticalAlignment="Middle">

<font isBold="true"/>

</textElement>

<text><![CDATA[Telefone:]]></text>

</staticText>

<textField>

<reportElement x="473" y="23" width="82" height="20"/>

<textElement verticalAlignment="Middle"/>

<textFieldExpression class="java.lang.String"><![CDATA[$F{telefone}]]></textFieldExpressi

on>

</textField>

<staticText>

<reportElement x="242" y="47" width="42" height="20"/>

<textElement textAlignment="Left" verticalAlignment="Middle">

<font isBold="true"/>

</textElement>

<text><![CDATA[Cidade:]]></text>

</staticText>

<textField>

<reportElement x="287" y="47" width="106" height="20"/>

<textElement verticalAlignment="Middle"/>

Page 67: Manual Ireport

9

14

0

14

1

14

2

14

3

14

4

14

5

14

6

14

7

14

8

14

9

15

0

15

1

15

2

15

3

15

4

15

5

15

<textFieldExpression class="java.lang.String"><![CDATA[$F{nomeCidade}]]></textFieldExpres

sion>

</textField>

<staticText>

<reportElement x="397" y="47" width="31" height="20"/>

<textElement textAlignment="Left" verticalAlignment="Middle">

<font isBold="true"/>

</textElement>

<text><![CDATA[País:]]></text>

</staticText>

<textField>

<reportElement x="433" y="47" width="122" height="20"/>

<textElement verticalAlignment="Middle"/>

<textFieldExpression class="java.lang.String"><![CDATA[$F{nomePais}]]></textFieldExpressi

on>

</textField>

<staticText>

<reportElement x="167" y="82" width="226" height="20"/>

<textElement textAlignment="Center" verticalAlignment="Middle" rotation="None">

<font size="12" isBold="true"/>

</textElement>

<text><![CDATA[O Subrelatório vai vir

aqui....]]></text>

</staticText>

<line>

<reportElement x="0" y="1" width="555" height="1"/>

</line>

</band>

Page 68: Manual Ireport

6

15

7

15

8

15

9

16

0

16

1

16

2

16

3

16

4

16

5

16

6

16

7

16

8

16

9

17

0

17

1

17

2

17

</detail>

<pageFooter>

<band height="22" splitType="Stretch">

<textField>

<reportElement x="455" y="2" width="100" height="20"/>

<textElement textAlignment="Right" verticalAlignment="Middle"/>

<textFieldExpression class="java.lang.Integer"><![CDATA[$V{PAGE_NUMBER}]]></textFieldExpr

ession>

</textField>

<line>

<reportElement x="0" y="1" width="555" height="1"/>

</line>

</band>

</pageFooter>

</jasperReport>

Page 69: Manual Ireport

3

17

4

17

5

17

6

17

7

17

8

17

9

18

0

18

1

18

2

18

3

18

4

18

5

18

6

18

7

18

8

18

9

19

Page 70: Manual Ireport

0

19

1

19

2

19

3

19

4

19

5

19

6

19

7

19

8

19

9

20

0

20

1

20

2

Depois de colar, volte para o Designer e verifique o que foi feito em cada parte. Após

atualizar o seu relatório, teste-o. O iReport vai pedir dois parâmetros, o nomeCliente

que vai ser usado na query e o nomeUsuario que vai ser usado no pageHeader. Note que

coloquei um campo de texto estático na banda detail, mostrando onde vai ficar o

subrealtório. Vamos criá-lo então. Primeiro, remova o campo de texto estático que tem

o valor ―O Subrelatório vai vir aqui…‖ e aumente a banda detail na altura cerca de 120

pixels (depois iremos deixar do tamanho correto). Na paleta de componentes, procure

por Subreport. Arraste m subreport para a banda Detail. Assim que arrastar e soltar, o

assistente de criação de subrelatórios irá abrir. No primeiro passo, escolha ―Create a

new report‖ e clique em Next. Veja a Figura abaixo.

Page 71: Manual Ireport

Primeiro passo do assistente de subrelatório

No segundo passo, escolha o layout como Blank A4 e clique em Next. Veja a Figura

abaixo.

Page 72: Manual Ireport

Segundo passo do assistente de subrelatório

No terceiro passo, ele vai pedir para inserir uma query. Iremos colocar uma query

provisória, só para poder continuar o assistente. Depois iremos mudá-la. Coloque

―SELECT * FROM country‖ (sem as aspas) e clique em Next. Veja a Figura abaixo.

Page 73: Manual Ireport

Terceiro passo do assistente de subrelatório

No quarto passo, ele vai perguntar os campos que queremos usar. Não adicione

nenhum, pois não vamos usá-los, pois essa não é a query que queremos lembram? Veja

a Figura abaixo.

Page 74: Manual Ireport

Quarto passo do assistente de subrelatório

No quinto passo, o assistente pergunta os grupos que serão usados. Nós não usaremos

grupos, então, da mesma forma que fizemos no passo anterior, clique em Next sem

fazer nada. Veja a Figura abaixo.

Page 75: Manual Ireport

Quinto passo do assistente de subrelatório

No próximo passo, configuramos o nome do arquivo de relatório que vai ser gerado

(Report Name), onde ele vai ser armazenado e como ele vai ser obtido no relatório

principal. Sendo assim, em Report Name insira ―LocacoesPorClientes_Locacoes‖ (sem

as aspas). Não mexa em Location, pq já deve estar apontanto para o diretório do

relatório principal. Abaixo, escolha ―Store the directory name in a parameter‖. Isso vai

ser útil depois, para informarmos onde está o subrelatório. Feito isso, clique em Next.

Veja a Figura abaixo.

Page 76: Manual Ireport

Sexto passo do assistente de subrelatório

No sétimo e último passo é perguntado como os dados do subrelatório serão obtidos.

Marque a opção ―Use the same connection used to fill the master report‖, ou seja,

vamos usar o mesmo objeto Connection passado para executar a query do relatório

principal. Clique em Finish. Veja a Figura abaixo.

Page 77: Manual Ireport

Sétimo passo do assistente de subrelatório

Ao clicar em Finish, o novo arquivo de relatório será criado e aberto. Mas ainda não

vamos mexer nele. Volte ao relatório principal. Você vai perceber que foi inserida uma

caixa cinza no relatório. Essa caixa indica onde o subrelatório vai ser inserido. Note

então que para cada cliente, teremos um subrelatório renderizado, afinal, estamos na

banda Detail não é mesmo? Expanda a caixa na largura, para ocupar quase a totalidade

do relatório e altere a largura da banda detail acomodar a caixa do subrealtório. Veja a

Figura abaixo.

Page 78: Manual Ireport

Layout do relatório principal

Ainda não teste o relatório! Como estamos obtendo todos os países para cada registro de

cliente obtido, o iReport pode travar. Salve o relatório principal e vamos agora para o

arquivo do subrelatório. Caso queria, segue o XML do relatório principal.

LocacoesPorClientes.jrxml

1

2

3

4

5

6

7

8

9

<?xml version="1.0" encoding="UTF-8"?>

<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreport

s http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="report name" pageWidth="595" pageHeight="842" columnWidth="535" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20">

<property name="ireport.zoom" value="1.0"/>

<property name="ireport.x" value="0"/>

<property name="ireport.y" value="0"/>

<parameter name="nomeCliente" class="java.lang.String"/>

Page 79: Manual Ireport

1

0

1

1

1

2

1

3

1

4

1

5

1

6

1

7

1

8

1

9

2

0

2

1

2

2

2

3

2

4

2

5

2

6

<parameter name="nomeUsuario" class="java.lang.String"/>

<parameter name="SUBREPORT_DIR" class="java.lang.String" isForPrompting="false">

<defaultValueExpression><![CDATA["C:\\Users\\David\\Documents

\\Blog\\tutoriais\\TutorialRelatorios\\relatorios\\"]]></defaultValue

Expression>

</parameter>

<queryString>

<![CDATA[SELECT

c.customer_id idCliente,

c.first_name nome,

c.last_name sobrenome,

c.email email,

a.address endereco,

a.phone telefone,

ci.city nomeCidade,

co.country nomePais

FROM

customer c,

address a,

city ci,

country co

WHERE

/* junções */

c.address_id = a.address_id AND

a.city_id = ci.city_id AND

ci.country_id = co.country_id AND

/* restrições */

Page 80: Manual Ireport

2

7

2

8

2

9

3

0

3

1

3

2

3

3

3

4

3

5

3

6

3

7

3

8

3

9

4

0

4

1

4

2

4

3

c.first_name LIKE $P{nomeCliente}

ORDER BY c.first_name;]]>

</queryString>

<field name="idCliente" class="java.lang.Integer"/>

<field name="nome" class="java.lang.String"/>

<field name="sobrenome" class="java.lang.String"/>

<field name="email" class="java.lang.String"/>

<field name="endereco" class="java.lang.String"/>

<field name="telefone" class="java.lang.String"/>

<field name="nomeCidade" class="java.lang.String"/>

<field name="nomePais" class="java.lang.String"/>

<background>

<band splitType="Stretch"/>

</background>

<title>

<band height="75" splitType="Stretch">

<staticText>

<reportElement x="0" y="18" width="555" height="40"/>

<textElement textAlignment="Center" verticalAlignment="Middle">

<font size="25" isBold="true"/>

</textElement>

<text><![CDATA[Locações por Clientes]]></text>

</staticText>

<line>

<reportElement x="0" y="1" width="555" height="1"/>

</line>

<line>

<reportElement x="0" y="74" width="555" height="1"/>

Page 81: Manual Ireport

4

4

4

5

4

6

4

7

4

8

4

9

5

0

5

1

5

2

5

3

5

4

5

5

5

6

5

7

5

8

5

9

6

0

</line>

</band>

</title>

<pageHeader>

<band height="21" splitType="Stretch">

<staticText>

<reportElement x="-1" y="0" width="51" height="20"/>

<textElement textAlignment="Left" verticalAlignment="Middle">

<font isBold="true"/>

</textElement>

<text><![CDATA[Usuário:]]></text>

</staticText>

<textField>

<reportElement x="53" y="0" width="150" height="20"/>

<textElement verticalAlignment="Middle"/>

<textFieldExpression class="java.lang.String"><![CDATA[$P{nomeUsuario}]]></textFieldExpres

sion>

</textField>

<staticText>

<reportElement x="360" y="0" width="68" height="20"/>

<textElement textAlignment="Left" verticalAlignment="Middle">

<font isBold="true"/>

</textElement>

<text><![CDATA[Gerado em:]]></text>

</staticText>

<textField pattern="dd/MM/yyyy&apos;, às&apos;

HH:mm&apos;hs&apos;">

<reportElement x="433" y="0" width="122" height="20"/>

<textElement verticalAlignment="Middle"/>

<textFieldExpression

Page 82: Manual Ireport

6

1

6

2

6

3

6

4

6

5

6

6

6

7

6

8

6

9

7

0

7

1

7

2

7

3

7

4

7

5

7

6

7

7

class="java.util.Date"><![CDATA[new Date()]]></textFieldExpression>

</textField>

</band>

</pageHeader>

<detail>

<band height="175" splitType="Stretch">

<staticText>

<reportElement x="0" y="3" width="50" height="20"/>

<textElement textAlignment="Left" verticalAlignment="Middle">

<font isBold="true"/>

</textElement>

<text><![CDATA[Nome:]]></text>

</staticText>

<textField>

<reportElement x="0" y="23" width="99" height="20"/>

<textElement verticalAlignment="Middle"/>

<textFieldExpression class="java.lang.String"><![CDATA[$F{nome}]]></textFieldExpression>

</textField>

<staticText>

<reportElement x="103" y="3" width="70" height="20"/>

<textElement textAlignment="Left" verticalAlignment="Middle">

<font isBold="true"/>

</textElement>

<text><![CDATA[Sobrenome:]]></text>

</staticText>

<textField>

<reportElement x="103" y="23" width="136" height="20"/>

<textElement verticalAlignment="Middle"/>

<textFieldExpression

Page 83: Manual Ireport

7

8

7

9

8

0

8

1

8

2

8

3

8

4

8

5

8

6

8

7

8

8

8

9

9

0

9

1

9

2

9

3

9

4

class="java.lang.String"><![CDATA[$F{sobrenome}]]></textFieldExpressi

on>

</textField>

<staticText>

<reportElement x="242" y="3" width="70" height="20"/>

<textElement textAlignment="Left" verticalAlignment="Middle">

<font isBold="true"/>

</textElement>

<text><![CDATA[E-mail:]]></text>

</staticText>

<textField>

<reportElement x="242" y="23" width="228" height="20"/>

<textElement verticalAlignment="Middle"/>

<textFieldExpression class="java.lang.String"><![CDATA[$F{email}]]></textFieldExpression>

</textField>

<staticText>

<reportElement x="0" y="47" width="59" height="20"/>

<textElement textAlignment="Left" verticalAlignment="Middle">

<font isBold="true"/>

</textElement>

<text><![CDATA[Endereço:]]></text>

</staticText>

<textField>

<reportElement x="62" y="47" width="177" height="20"/>

<textElement verticalAlignment="Middle"/>

<textFieldExpression class="java.lang.String"><![CDATA[$F{endereco}]]></textFieldExpressio

n>

</textField>

<staticText>

Page 84: Manual Ireport

9

5

9

6

9

7

9

8

9

9

1

0

0

1

0

1

1

0

2

1

0

3

1

0

4

1

0

5

1

0

6

1

0

7

1

0

<reportElement x="473" y="3" width="82" height="20"/>

<textElement verticalAlignment="Middle">

<font isBold="true"/>

</textElement>

<text><![CDATA[Telefone:]]></text>

</staticText>

<textField>

<reportElement x="473" y="23" width="82" height="20"/>

<textElement verticalAlignment="Middle"/>

<textFieldExpression class="java.lang.String"><![CDATA[$F{telefone}]]></textFieldExpressio

n>

</textField>

<staticText>

<reportElement x="242" y="47" width="42" height="20"/>

<textElement textAlignment="Left" verticalAlignment="Middle">

<font isBold="true"/>

</textElement>

<text><![CDATA[Cidade:]]></text>

</staticText>

<textField>

<reportElement x="287" y="47" width="106" height="20"/>

<textElement verticalAlignment="Middle"/>

<textFieldExpression class="java.lang.String"><![CDATA[$F{nomeCidade}]]></textFieldExpress

ion>

</textField>

<staticText>

<reportElement x="397" y="47" width="31" height="20"/>

<textElement textAlignment="Left" verticalAlignment="Middle">

<font isBold="true"/>

Page 85: Manual Ireport

8

1

0

9

1

1

0

1

1

1

1

1

2

1

1

3

1

1

4

1

1

5

1

1

6

1

1

7

1

1

8

1

1

9

1

2

</textElement>

<text><![CDATA[País:]]></text>

</staticText>

<textField>

<reportElement x="433" y="47" width="122" height="20"/>

<textElement verticalAlignment="Middle"/>

<textFieldExpression class="java.lang.String"><![CDATA[$F{nomePais}]]></textFieldExpressio

n>

</textField>

<line>

<reportElement x="0" y="1" width="555" height="1"/>

</line>

<subreport>

<reportElement x="7" y="71" width="544" height="100"/>

<connectionExpression><![CDATA[$P{REPORT_CONNECTION}]

]></connectionExpression>

<subreportExpression class="java.lang.String"><![CDATA[$P{SUBREPORT_DIR} +

"LocacoesPorClientes_Locacoes.jasper"]]></subreportExpression>

</subreport>

</band>

</detail>

<pageFooter>

<band height="22" splitType="Stretch">

<textField>

<reportElement x="455" y="2" width="100" height="20"/>

<textElement textAlignment="Right" verticalAlignment="Middle"/>

<textFieldExpression class="java.lang.Integer"><![CDATA[$V{PAGE_NUMBER}]]></textFieldExpre

ssion>

</textField>

Page 86: Manual Ireport

0

1

2

1

1

2

2

1

2

3

1

2

4

1

2

5

1

2

6

1

2

7

1

2

8

1

2

9

1

3

0

1

3

1

1

3

<line>

<reportElement x="0" y="1" width="555" height="1"/>

</line>

</band>

</pageFooter>

</jasperReport>

Page 87: Manual Ireport

2

1

3

3

1

3

4

1

3

5

1

3

6

1

3

7

1

3

8

1

3

9

1

4

0

1

4

1

1

4

2

1

4

3

1

4

Page 88: Manual Ireport

4

1

4

5

1

4

6

1

4

7

1

4

8

1

4

9

1

5

0

1

5

1

1

5

2

1

5

3

1

5

4

1

5

5

1

5

Page 89: Manual Ireport

6

1

5

7

1

5

8

1

5

9

1

6

0

1

6

1

1

6

2

1

6

3

1

6

4

1

6

5

1

6

6

1

6

7

1

6

Page 90: Manual Ireport

8

1

6

9

1

7

0

1

7

1

1

7

2

1

7

3

1

7

4

1

7

5

1

7

6

1

7

7

1

7

8

1

7

9

1

8

Page 91: Manual Ireport

0

1

8

1

1

8

2

1

8

3

1

8

4

1

8

5

1

8

6

1

8

7

1

8

8

1

8

9

1

9

0

1

9

1

1

9

Page 92: Manual Ireport

2

1

9

3

1

9

4

1

9

5

1

9

6

1

9

7

1

9

8

1

9

9

2

0

0

2

0

1

2

0

2

2

0

3

A primeira coisa que vamos fazer no arquivo do subrelatório é excluir todas as bandas,

exceto a Detail e a Column Header. Vamos agora criar um parâmetro chamado

Page 93: Manual Ireport

―idCliente‖, que vai ser usado na nossa query para que possamos obter os filmes de um

determinado cliente. O tipo deve deve ser Integer. Vamos agora editar a query do

relatório, onde vamos obter o nome e o ano do filme alugado, além da data de

devolução, sendo que iremos mostrar apenas os filmes que já foram alugados, ou seja,

com data de devolução diferente de NULL. Teremos que fazer junções em algumas

tabelas para podermos obter os filmes alugados por um determinado cliente. A query

vai ficar assim:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

SELECT

f.title titulo,

f.release_year anoLancamento,

r.return_date dataDevolucao

FROM

customer c,

rental r,

inventory i,

film f

WHERE

/* junções */

r.customer_id = c.customer_id AND

r.inventory_id = i.inventory_id AND

i.film_id = f.film_id AND

/* restrições */

c.customer_id LIKE $P{idCliente} AND

r.return_date IS NOT NULL

ORDER BY r.return_date, f.title;

Page 94: Manual Ireport

Ao clicar em OK, o iReport vai gerar os campos para podermos utilizar no subrelatório.

Organize então os campos da mesma forma que mostrado na Figura abaixo.

Layout do subrelatório

Note que diminui a largura da página para 6,5 polegadas (6.5 inches). Para fazer isso, no

Report Inspector, clique com o botão direito no nó raiz (deve estar com o nome do

arquivo de relatório) e vá em Page Format (primeira opção) e altere a largura (Width)

para 6.5 polegadas e clique em OK. Segue o código XML do subrelatório.

LocacoesPorClientes_Locacoes.jrxml

1

2

3

4

5

6

7

8

9

1

0

1

1

1

2

<?xml version="1.0" encoding="UTF-8"?>

<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreport

s http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="LocacoesPorClientes_Locacoes" language="groovy" pageWidth="468" pageHeight="802" columnWidth="468" leftMargin="0" rightMargin="0" topMargin="0" bottomMargin="0">

<property name="ireport.zoom" value="1.0"/>

<property name="ireport.x" value="0"/>

<property name="ireport.y" value="0"/>

<parameter name="idCliente" class="java.lang.Integer"/>

<queryString>

<![CDATA[SELECT

f.title titulo,

f.release_year anoLancamento,

r.return_date dataDevolucao

Page 95: Manual Ireport

1

3

1

4

1

5

1

6

1

7

1

8

1

9

2

0

2

1

2

2

2

3

2

4

2

5

2

6

2

7

2

8

2

9

FROM

customer c,

rental r,

inventory i,

film f

WHERE

/* junções */

r.customer_id = c.customer_id AND

r.inventory_id = i.inventory_id AND

i.film_id = f.film_id AND

/* restrições */

c.customer_id LIKE $P{idCliente} AND

r.return_date IS NOT NULL

ORDER BY r.return_date, f.title;]]>

</queryString>

<field name="titulo" class="java.lang.String"/>

<field name="anoLancamento" class="java.sql.Date"/>

<field name="dataDevolucao" class="java.sql.Timestamp"/>

<background>

<band splitType="Stretch"/>

</background>

<columnHeader>

<band height="25">

<staticText>

<reportElement x="0" y="0" width="100" height="20"/>

<textElement textAlignment="Center"

Page 96: Manual Ireport

3

0

3

1

3

2

3

3

3

4

3

5

3

6

3

7

3

8

3

9

4

0

4

1

4

2

4

3

4

4

4

5

4

6

verticalAlignment="Middle">

<font isBold="true"/>

</textElement>

<text><![CDATA[Devolvido em]]></text>

</staticText>

<staticText>

<reportElement x="103" y="0" width="47" height="20"/>

<textElement verticalAlignment="Middle">

<font isBold="true"/>

</textElement>

<text><![CDATA[Título]]></text>

</staticText>

<staticText>

<reportElement x="326" y="0" width="117" height="20"/>

<textElement verticalAlignment="Middle">

<font isBold="true"/>

</textElement>

<text><![CDATA[Ano de Lançamento]]></text>

</staticText>

<line>

<reportElement x="0" y="24" width="468" height="1"/>

</line>

</band>

</columnHeader>

<detail>

<band height="21" splitType="Stretch">

<textField pattern="dd/MM/yyyy">

<reportElement x="0" y="1" width="100" height="20"/>

<textElement textAlignment="Center" verticalAlignment="Middle"/>

<textFieldExpression

Page 97: Manual Ireport

4

7

4

8

4

9

5

0

5

1

5

2

5

3

5

4

5

5

5

6

5

7

5

8

5

9

6

0

6

1

6

2

6

3

class="java.sql.Timestamp"><![CDATA[$F{dataDevolucao}]]></textFieldEx

pression>

</textField>

<textField>

<reportElement x="103" y="1" width="219" height="20"/>

<textElement verticalAlignment="Middle"/>

<textFieldExpression class="java.lang.String"><![CDATA[$F{titulo}]]></textFieldExpression>

</textField>

<textField pattern="yyyy">

<reportElement x="326" y="1" width="117" height="20"/>

<textElement verticalAlignment="Middle"/>

<textFieldExpression class="java.util.Date"><![CDATA[$F{anoLancamento}]]></textFieldExpres

sion>

</textField>

</band>

</detail>

</jasperReport>

Page 98: Manual Ireport

6

4

6

5

6

6

6

7

6

8

6

9

7

0

7

1

7

2

7

3

7

4

7

5

7

6

7

7

7

8

7

9

8

0

Page 99: Manual Ireport

8

1

8

2

8

3

8

4

Dê um preview no subreport, inserindo o valor ―1‖ (sem as aspas) para o parâmetro

idCliente. O preview deve ser parecido com o mostrado na Figura abaixo.

Preview do subrelatório

Engraçado notar que tem filmes que foram alugados pelo Cliente ―1‖ antes de terem

sido lançados :D Enfim, estamos quase lá. Falta agora nós fazermos os dois relatórios

funcionarem juntos. Lembram que falei que os parâmetros do subrelatório teriam de ser

Page 100: Manual Ireport

enviados pelo relatório principal? No nosso caso, o nosso subrelatório espera pelo

parâmetro ―idCliente‖ ($P{idCliente}) para executar sua query. Então precisamos fazer

com que o relatório principal passe este valor, que está sendo guardado do campo

idCliente ($F{idCliente}) que é obtido na query do relatório principal.

Para isso, vá no relatório principal e selecione a caixa que vai conter o subrelatório. Ao

selecioná-la, procure pela propriedade Parameters no painel de propriedades. O valor

vai estar definido como ―No parameter defined‖. Clique no pequeno botão a direita e a

janela mostrada na Figura abaixo vai ser exibida.

Configuração de parâmetros

Esta janela é utilizada para criar um parâmetro de passagem (eu que inventei esse nome

de ―parâmetro de passagem‖), que deve ter o mesmo nome do parâmetro esperado pelo

subrelatório. Os parâmetros de passagem ficam na coluna destacada em roxo da tabela.

O valor desse parâmetro é gerado pela expressão que for definida (coluna destacada em

verde). Para criar o novo parâmetro de passagem, clique no botão Add. Ao clicar no

botão, a janela mostrada na Figura abaixo é mostrada.

Page 101: Manual Ireport

Janela para adicionar parâmetros de passagem

Preencha o campo ―Subreport parameter name‖ com o valor idCliente (nome do

parâmetro do subrelatório) e preencha o campo ―Value expression‖ com o valor

$F{idCliente}, ou seja, o campo idCliente da query do relatório principal e clique em

OK. Veja a Figura abaixo.

Page 102: Manual Ireport

Criando novo parâmetro de passagem

Note que você pode usar o editor de expressões (Expression editor) clicando no botão

destacado em laranja. Entendeu o que fizemos? Amarramos o parâmetro idCliente do

subrelatório com o valor que vai ser inserido no campo idCliente ($F{idCliente}), ou

seja, a cada vez que o subrelatório for chamado (para cada cliente) o valor do parâmetro

idCliente vai ser configurado com o valor do campo idCliente. Note que o valor do

parâmetro do subrelatório tem que ser do mesmo tipo que o valor gerado pela expressão

de valor (value expression). É nesta mesma janela que você vai amarrar todos os

parâmetros do subrelatório com valores gerados no relatório ou passados para ele. Por

exemplo, o subrelatório tem um parâmetro chamado ―paramSub1‖ e o valor deste

parâmetro é passado ao relatório principal no parâmetro chamado ―paramPrin1‖. Então

você teria que amarrar paramSub1 (coluna name, em verde) com a expressão

$P{paramPrin1} (coluna expression, em roxo) entendeu? É como se estivéssemos

chamando um método, passando parâmetros para ele. Segue então o código XML do

relatório principal até o momento.

LocacoesPorClientes.jrxml

1

2

3

<?xml version="1.0" encoding="UTF-8"?>

<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreport

Page 103: Manual Ireport

4

5

6

7

8

9

1

0

1

1

1

2

1

3

1

4

1

5

1

6

1

7

1

8

1

9

2

0

2

1

2

2

2

s http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="report name" pageWidth="595" pageHeight="842" columnWidth="535" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20">

<property name="ireport.zoom" value="1.0"/>

<property name="ireport.x" value="0"/>

<property name="ireport.y" value="0"/>

<parameter name="nomeCliente" class="java.lang.String"/>

<parameter name="nomeUsuario" class="java.lang.String"/>

<parameter name="SUBREPORT_DIR" class="java.lang.String" isForPrompting="false">

<defaultValueExpression><![CDATA["C:\\Users\\David\\Documents

\\Blog\\tutoriais\\TutorialRelatorios\\relatorios\\"]]></defaultValue

Expression>

</parameter>

<queryString>

<![CDATA[SELECT

c.customer_id idCliente,

c.first_name nome,

c.last_name sobrenome,

c.email email,

a.address endereco,

a.phone telefone,

ci.city nomeCidade,

co.country nomePais

FROM

customer c,

address a,

city ci,

country co

WHERE

Page 104: Manual Ireport

3

2

4

2

5

2

6

2

7

2

8

2

9

3

0

3

1

3

2

3

3

3

4

3

5

3

6

3

7

3

8

3

9

4

/* junções */

c.address_id = a.address_id AND

a.city_id = ci.city_id AND

ci.country_id = co.country_id AND

/* restrições */

c.first_name LIKE $P{nomeCliente}

ORDER BY c.first_name;]]>

</queryString>

<field name="idCliente" class="java.lang.Integer"/>

<field name="nome" class="java.lang.String"/>

<field name="sobrenome" class="java.lang.String"/>

<field name="email" class="java.lang.String"/>

<field name="endereco" class="java.lang.String"/>

<field name="telefone" class="java.lang.String"/>

<field name="nomeCidade" class="java.lang.String"/>

<field name="nomePais" class="java.lang.String"/>

<background>

<band splitType="Stretch"/>

</background>

<title>

<band height="75" splitType="Stretch">

<staticText>

<reportElement x="0" y="18" width="555" height="40"/>

<textElement textAlignment="Center" verticalAlignment="Middle">

<font size="25" isBold="true"/>

</textElement>

<text><![CDATA[Locações por Clientes]]></text>

Page 105: Manual Ireport

0

4

1

4

2

4

3

4

4

4

5

4

6

4

7

4

8

4

9

5

0

5

1

5

2

5

3

5

4

5

5

5

6

5

</staticText>

<line>

<reportElement x="0" y="1" width="555" height="1"/>

</line>

<line>

<reportElement x="0" y="74" width="555" height="1"/>

</line>

</band>

</title>

<pageHeader>

<band height="21" splitType="Stretch">

<staticText>

<reportElement x="-1" y="0" width="51" height="20"/>

<textElement textAlignment="Left" verticalAlignment="Middle">

<font isBold="true"/>

</textElement>

<text><![CDATA[Usuário:]]></text>

</staticText>

<textField>

<reportElement x="53" y="0" width="150" height="20"/>

<textElement verticalAlignment="Middle"/>

<textFieldExpression class="java.lang.String"><![CDATA[$P{nomeUsuario}]]></textFieldExpres

sion>

</textField>

<staticText>

<reportElement x="360" y="0" width="68" height="20"/>

<textElement textAlignment="Left" verticalAlignment="Middle">

<font isBold="true"/>

</textElement>

Page 106: Manual Ireport

7

5

8

5

9

6

0

6

1

6

2

6

3

6

4

6

5

6

6

6

7

6

8

6

9

7

0

7

1

7

2

7

3

7

<text><![CDATA[Gerado em:]]></text>

</staticText>

<textField pattern="dd/MM/yyyy&apos;, às&apos;

HH:mm&apos;hs&apos;">

<reportElement x="433" y="0" width="122" height="20"/>

<textElement verticalAlignment="Middle"/>

<textFieldExpression class="java.util.Date"><![CDATA[new Date()]]></textFieldExpression>

</textField>

</band>

</pageHeader>

<detail>

<band height="175" splitType="Stretch">

<staticText>

<reportElement x="0" y="3" width="50" height="20"/>

<textElement textAlignment="Left" verticalAlignment="Middle">

<font isBold="true"/>

</textElement>

<text><![CDATA[Nome:]]></text>

</staticText>

<textField>

<reportElement x="0" y="23" width="99" height="20"/>

<textElement verticalAlignment="Middle"/>

<textFieldExpression class="java.lang.String"><![CDATA[$F{nome}]]></textFieldExpression>

</textField>

<staticText>

<reportElement x="103" y="3" width="70" height="20"/>

<textElement textAlignment="Left" verticalAlignment="Middle">

<font isBold="true"/>

Page 107: Manual Ireport

4

7

5

7

6

7

7

7

8

7

9

8

0

8

1

8

2

8

3

8

4

8

5

8

6

8

7

8

8

8

9

9

0

9

</textElement>

<text><![CDATA[Sobrenome:]]></text>

</staticText>

<textField>

<reportElement x="103" y="23" width="136" height="20"/>

<textElement verticalAlignment="Middle"/>

<textFieldExpression class="java.lang.String"><![CDATA[$F{sobrenome}]]></textFieldExpressi

on>

</textField>

<staticText>

<reportElement x="242" y="3" width="70" height="20"/>

<textElement textAlignment="Left" verticalAlignment="Middle">

<font isBold="true"/>

</textElement>

<text><![CDATA[E-mail:]]></text>

</staticText>

<textField>

<reportElement x="242" y="23" width="228" height="20"/>

<textElement verticalAlignment="Middle"/>

<textFieldExpression class="java.lang.String"><![CDATA[$F{email}]]></textFieldExpression>

</textField>

<staticText>

<reportElement x="0" y="47" width="59" height="20"/>

<textElement textAlignment="Left" verticalAlignment="Middle">

<font isBold="true"/>

</textElement>

<text><![CDATA[Endereço:]]></text>

</staticText>

Page 108: Manual Ireport

1

9

2

9

3

9

4

9

5

9

6

9

7

9

8

9

9

1

0

0

1

0

1

1

0

2

1

0

3

1

0

4

1

0

5

<textField>

<reportElement x="62" y="47" width="177" height="20"/>

<textElement verticalAlignment="Middle"/>

<textFieldExpression class="java.lang.String"><![CDATA[$F{endereco}]]></textFieldExpressio

n>

</textField>

<staticText>

<reportElement x="473" y="3" width="82" height="20"/>

<textElement verticalAlignment="Middle">

<font isBold="true"/>

</textElement>

<text><![CDATA[Telefone:]]></text>

</staticText>

<textField>

<reportElement x="473" y="23" width="82" height="20"/>

<textElement verticalAlignment="Middle"/>

<textFieldExpression class="java.lang.String"><![CDATA[$F{telefone}]]></textFieldExpressio

n>

</textField>

<staticText>

<reportElement x="242" y="47" width="42" height="20"/>

<textElement textAlignment="Left" verticalAlignment="Middle">

<font isBold="true"/>

</textElement>

<text><![CDATA[Cidade:]]></text>

</staticText>

<textField>

<reportElement x="287" y="47" width="106" height="20"/>

<textElement verticalAlignment="Middle"/>

<textFieldExpression

Page 109: Manual Ireport

1

0

6

1

0

7

1

0

8

1

0

9

1

1

0

1

1

1

1

1

2

1

1

3

1

1

4

1

1

5

1

1

6

1

1

7

1

class="java.lang.String"><![CDATA[$F{nomeCidade}]]></textFieldExpress

ion>

</textField>

<staticText>

<reportElement x="397" y="47" width="31" height="20"/>

<textElement textAlignment="Left" verticalAlignment="Middle">

<font isBold="true"/>

</textElement>

<text><![CDATA[País:]]></text>

</staticText>

<textField>

<reportElement x="433" y="47" width="122" height="20"/>

<textElement verticalAlignment="Middle"/>

<textFieldExpression class="java.lang.String"><![CDATA[$F{nomePais}]]></textFieldExpressio

n>

</textField>

<line>

<reportElement x="0" y="1" width="555" height="1"/>

</line>

<subreport>

<reportElement x="7" y="71" width="544" height="100"/>

<subreportParameter name="idCliente">

<subreportParameterExpression><![CDATA[$F{idClien

te}]]></subreportParameterExpression>

</subreportParameter>

<connectionExpression><![CDATA[$P{REPORT_CONNECTION}]

]></connectionExpression>

<subreportExpression class="java.lang.String"><![CDATA[$P{SUBREPORT_DIR} +

"LocacoesPorClientes_Locacoes.jasper"]]></subreportExpression>

</subreport>

Page 110: Manual Ireport

1

8

1

1

9

1

2

0

1

2

1

1

2

2

1

2

3

1

2

4

1

2

5

1

2

6

1

2

7

1

2

8

1

2

9

1

3

</band>

</detail>

<pageFooter>

<band height="22" splitType="Stretch">

<textField>

<reportElement x="455" y="2" width="100" height="20"/>

<textElement textAlignment="Right" verticalAlignment="Middle"/>

<textFieldExpression class="java.lang.Integer"><![CDATA[$V{PAGE_NUMBER}]]></textFieldExpre

ssion>

</textField>

<line>

<reportElement x="0" y="1" width="555" height="1"/>

</line>

</band>

</pageFooter>

</jasperReport>

Page 111: Manual Ireport

0

1

3

1

1

3

2

1

3

3

1

3

4

1

3

5

1

3

6

1

3

7

1

3

8

1

3

9

1

4

0

1

4

1

1

4

Page 112: Manual Ireport

2

1

4

3

1

4

4

1

4

5

1

4

6

1

4

7

1

4

8

1

4

9

1

5

0

1

5

1

1

5

2

1

5

3

1

5

Page 113: Manual Ireport

4

1

5

5

1

5

6

1

5

7

1

5

8

1

5

9

1

6

0

1

6

1

1

6

2

1

6

3

1

6

4

1

6

5

1

6

Page 114: Manual Ireport

6

1

6

7

1

6

8

1

6

9

1

7

0

1

7

1

1

7

2

1

7

3

1

7

4

1

7

5

1

7

6

1

7

7

1

7

Page 115: Manual Ireport

8

1

7

9

1

8

0

1

8

1

1

8

2

1

8

3

1

8

4

1

8

5

1

8

6

1

8

7

1

8

8

1

8

9

1

9

Page 116: Manual Ireport

0

1

9

1

1

9

2

1

9

3

1

9

4

1

9

5

1

9

6

1

9

7

1

9

8

1

9

9

2

0

0

2

0

1

2

0

Page 117: Manual Ireport

2

2

0

3

2

0

4

2

0

5

2

0

6

Teste o relatório e veja o que acontece. Você vai perceber que para cada cliente será

gerado uma lista de filmes. Agora que está tudo pronto, organize o layout do

subrelatório e personalize da forma que achar melhor. Eu coloquei a largura com 7,694

polegadas e expandi a linha para ocupar toda a largura. Note que se você mudar alguma

coisa no subrelatório, vc precisará compilar apenas ele. Agora, para finalizar, vamos

chamar este relatório a partir do nosso programa em Java, mas para isso ainda temos

que fazer algumas pequenas modificações no arquivo de relatório principal.

Para entender o que vamos fazer, abra o arquivo LocacoesPorClientes.jrxml e selecione

a caixa do subrelatório. Nas propriedades procure pela propriedade Subreport

Expression. Essa expressão que é responsável em fazer o subrelatório ser carregado, ou

seja, é ela que define para o relatório principal a localização do subrelatório. Por padrão

– na verdade, pq definimos quando usamos o assistente de subrelatórios – ela vai conter

o valor $P{SUBREPORT_DIR} + ―LocacoesPorClientes_Locacoes.jasper‖, ou seja, o

caminho do subrelatório é formado pelo valor do parâmetro SUBREPORT_DIR

concatenado com o nome do arquivo de Subrelatório. O problema é que o parâmetro

SUBREPORT_DIR está configurado com um valor fixo, que corresponde ao caminho

absoluto do relatório e isso não é bom… O que vamos fazer então é fazer com que tudo

execute corretamente tanto no projeto, quanto no programa compilado e empacotado.

Primeiro, no Report Inspector, procure pelo parâmetro SUBREPORT_DIR. Ao

selecioná-lo, verifique a propriedade ―Default Value Expression‖. Ela vai estar definida

como o caminho absoluto do diretório onde está o subrelatório. Vamos mudar esse valor

para ―/‖ (com as aspas), ou seja, uma String que contém uma barra, que vai indicar a

raiz do projeto. O tipo da classe do parâmetro ainda é String. Ok, aqui está pronto.

Agora selecione novamente a caixa do subrelatório. Na propriedade Subreport

expression entre com o seguinte código.

1 getClass().getResource( $P{SUBREPORT_DIR} +

"LocacoesPorClientes_Locacoes.jasper" )

Page 118: Manual Ireport

Note que o ponto e vírgula da instrução não é colocado. Essa linha de código vai

retornar um objeto URL que aponta para o arquivo do subrelatório

(―/LocacoesPorClientes_Locacoes.jasper‖), sendo então carregado corretamente tanto

no projeto, quanto no .jar. Note que poderíamos fixar esse valor sem precisar usar o

parâmetro, mas caso haja a necessidade de mudar os diretórios dos subrelatórios, essa

abordagem facilita o trabalho, tendo apenas que mudar o valor padrão do parâmetro.

Como a expressão vai retornar um objeto URL, ainda nas propriedades da caixa do

subrelatório, mude a Expression Class (logo abaixo da Subreport Expression) para

java.net.URL.

Feito isso, salve o relatório e dê um preview. Na aba iReport output vai ser acusado um

warning, dizendo que não é possível encontrar o relatório, no entando o relatório vai ser

renderizado direitinho. Agora não precisamos mais nos preocupar, pois tanto no

iReport, quanto no .jar que for ser gerado do projeto, o relatório vai abrir corretamente

com o subrelatório.

O código do método abrirRelatorioClientes() da classe Main foi alterado para:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

public void abrirRelatorioClientes() {

InputStream inputStream = getClass().getResourceAsStream(

"/LocacoesPorClientes.jasper" );

Map<String, Object> parametros = new HashMap<String, Object>();

parametros.put( "nomeCliente", "F%" );

try {

ReportUtils.openReport( "Locações por Clientes",

inputStream, parametros,

ConnectionFactory.getSakilaConnection() );

} catch ( SQLException exc ) {

exc.printStackTrace();

} catch ( JRException exc ) {

exc.printStackTrace();

}

Page 119: Manual Ireport

18

19

}

O código das versões finais tanto do arquivo de relatório principal, quanto do

subrelatório estão listadas a seguir.

LocacoesPorClientes.jrxml

1

2

3

4

5

6

7

8

9

1

0

1

1

1

2

1

3

1

4

1

5

1

6

1

7

<?xml version="1.0" encoding="UTF-8"?>

<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreport

s http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="report name" pageWidth="595" pageHeight="842" columnWidth="535" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20">

<property name="ireport.zoom" value="1.0"/>

<property name="ireport.x" value="0"/>

<property name="ireport.y" value="0"/>

<parameter name="nomeCliente" class="java.lang.String"/>

<parameter name="nomeUsuario" class="java.lang.String"/>

<parameter name="SUBREPORT_DIR" class="java.lang.String" isForPrompting="false">

<defaultValueExpression><![CDATA["/"]]></defaultValueExpressi

on>

</parameter>

<queryString>

<![CDATA[SELECT

c.customer_id idCliente,

c.first_name nome,

c.last_name sobrenome,

c.email email,

a.address endereco,

a.phone telefone,

ci.city nomeCidade,

co.country nomePais

Page 120: Manual Ireport

1

8

1

9

2

0

2

1

2

2

2

3

2

4

2

5

2

6

2

7

2

8

2

9

3

0

3

1

3

2

3

3

3

4

FROM

customer c,

address a,

city ci,

country co

WHERE

/* junções */

c.address_id = a.address_id AND

a.city_id = ci.city_id AND

ci.country_id = co.country_id AND

/* restrições */

c.first_name LIKE $P{nomeCliente}

ORDER BY c.first_name;]]>

</queryString>

<field name="idCliente" class="java.lang.Integer"/>

<field name="nome" class="java.lang.String"/>

<field name="sobrenome" class="java.lang.String"/>

<field name="email" class="java.lang.String"/>

<field name="endereco" class="java.lang.String"/>

<field name="telefone" class="java.lang.String"/>

<field name="nomeCidade" class="java.lang.String"/>

<field name="nomePais" class="java.lang.String"/>

<background>

<band splitType="Stretch"/>

</background>

Page 121: Manual Ireport

3

5

3

6

3

7

3

8

3

9

4

0

4

1

4

2

4

3

4

4

4

5

4

6

4

7

4

8

4

9

5

0

5

1

<title>

<band height="75" splitType="Stretch">

<staticText>

<reportElement x="0" y="18" width="555" height="40"/>

<textElement textAlignment="Center" verticalAlignment="Middle">

<font size="25" isBold="true"/>

</textElement>

<text><![CDATA[Locações por Clientes]]></text>

</staticText>

<line>

<reportElement x="0" y="1" width="555" height="1"/>

</line>

<line>

<reportElement x="0" y="74" width="555" height="1"/>

</line>

</band>

</title>

<pageHeader>

<band height="21" splitType="Stretch">

<staticText>

<reportElement x="-1" y="0" width="51" height="20"/>

<textElement textAlignment="Left" verticalAlignment="Middle">

<font isBold="true"/>

</textElement>

<text><![CDATA[Usuário:]]></text>

</staticText>

<textField>

<reportElement x="53" y="0" width="150" height="20"/>

<textElement verticalAlignment="Middle"/>

Page 122: Manual Ireport

5

2

5

3

5

4

5

5

5

6

5

7

5

8

5

9

6

0

6

1

6

2

6

3

6

4

6

5

6

6

6

7

6

8

<textFieldExpression class="java.lang.String"><![CDATA[$P{nomeUsuario}]]></textFieldExpres

sion>

</textField>

<staticText>

<reportElement x="360" y="0" width="68" height="20"/>

<textElement textAlignment="Left" verticalAlignment="Middle">

<font isBold="true"/>

</textElement>

<text><![CDATA[Gerado em:]]></text>

</staticText>

<textField pattern="dd/MM/yyyy&apos;, às&apos;

HH:mm&apos;hs&apos;">

<reportElement x="433" y="0" width="122" height="20"/>

<textElement verticalAlignment="Middle"/>

<textFieldExpression class="java.util.Date"><![CDATA[new Date()]]></textFieldExpression>

</textField>

</band>

</pageHeader>

<detail>

<band height="196" splitType="Stretch">

<staticText>

<reportElement x="0" y="3" width="50" height="20"/>

<textElement textAlignment="Left" verticalAlignment="Middle">

<font isBold="true"/>

</textElement>

<text><![CDATA[Nome:]]></text>

</staticText>

<textField>

<reportElement x="0" y="23" width="99" height="20"/>

Page 123: Manual Ireport

6

9

7

0

7

1

7

2

7

3

7

4

7

5

7

6

7

7

7

8

7

9

8

0

8

1

8

2

8

3

8

4

8

5

<textElement verticalAlignment="Middle"/>

<textFieldExpression class="java.lang.String"><![CDATA[$F{nome}]]></textFieldExpression>

</textField>

<staticText>

<reportElement x="103" y="3" width="70" height="20"/>

<textElement textAlignment="Left" verticalAlignment="Middle">

<font isBold="true"/>

</textElement>

<text><![CDATA[Sobrenome:]]></text>

</staticText>

<textField>

<reportElement x="103" y="23" width="136" height="20"/>

<textElement verticalAlignment="Middle"/>

<textFieldExpression class="java.lang.String"><![CDATA[$F{sobrenome}]]></textFieldExpressi

on>

</textField>

<staticText>

<reportElement x="242" y="3" width="70" height="20"/>

<textElement textAlignment="Left" verticalAlignment="Middle">

<font isBold="true"/>

</textElement>

<text><![CDATA[E-mail:]]></text>

</staticText>

<textField>

<reportElement x="242" y="23" width="228" height="20"/>

<textElement verticalAlignment="Middle"/>

<textFieldExpression class="java.lang.String"><![CDATA[$F{email}]]></textFieldExpression>

</textField>

Page 124: Manual Ireport

8

6

8

7

8

8

8

9

9

0

9

1

9

2

9

3

9

4

9

5

9

6

9

7

9

8

9

9

1

0

0

1

0

1

<staticText>

<reportElement x="0" y="47" width="59" height="20"/>

<textElement textAlignment="Left" verticalAlignment="Middle">

<font isBold="true"/>

</textElement>

<text><![CDATA[Endereço:]]></text>

</staticText>

<textField>

<reportElement x="62" y="47" width="177" height="20"/>

<textElement verticalAlignment="Middle"/>

<textFieldExpression class="java.lang.String"><![CDATA[$F{endereco}]]></textFieldExpressio

n>

</textField>

<staticText>

<reportElement x="473" y="3" width="82" height="20"/>

<textElement verticalAlignment="Middle">

<font isBold="true"/>

</textElement>

<text><![CDATA[Telefone:]]></text>

</staticText>

<textField>

<reportElement x="473" y="23" width="82" height="20"/>

<textElement verticalAlignment="Middle"/>

<textFieldExpression class="java.lang.String"><![CDATA[$F{telefone}]]></textFieldExpressio

n>

</textField>

<staticText>

<reportElement x="242" y="47" width="42" height="20"/>

<textElement textAlignment="Left" verticalAlignment="Middle">

Page 125: Manual Ireport

1

0

2

1

0

3

1

0

4

1

0

5

1

0

6

1

0

7

1

0

8

1

0

9

1

1

0

1

1

1

1

1

2

1

1

3

1

<font isBold="true"/>

</textElement>

<text><![CDATA[Cidade:]]></text>

</staticText>

<textField>

<reportElement x="287" y="47" width="106" height="20"/>

<textElement verticalAlignment="Middle"/>

<textFieldExpression class="java.lang.String"><![CDATA[$F{nomeCidade}]]></textFieldExpress

ion>

</textField>

<staticText>

<reportElement x="397" y="47" width="31" height="20"/>

<textElement textAlignment="Left" verticalAlignment="Middle">

<font isBold="true"/>

</textElement>

<text><![CDATA[País:]]></text>

</staticText>

<textField>

<reportElement x="433" y="47" width="122" height="20"/>

<textElement verticalAlignment="Middle"/>

<textFieldExpression class="java.lang.String"><![CDATA[$F{nomePais}]]></textFieldExpressio

n>

</textField>

<line>

<reportElement x="0" y="1" width="555" height="1"/>

</line>

<subreport>

<reportElement x="0" y="96" width="555" height="100"/>

<subreportParameter name="idCliente">

<subreportParameterExpression><![CDATA[$F{idClien

Page 126: Manual Ireport

1

4

1

1

5

1

1

6

1

1

7

1

1

8

1

1

9

1

2

0

1

2

1

1

2

2

1

2

3

1

2

4

1

2

5

1

2

te}]]></subreportParameterExpression>

</subreportParameter>

<connectionExpression><![CDATA[$P{REPORT_CONNECTION}]

]></connectionExpression>

<subreportExpression class="java.net.URL"><![CDATA[getClass().getResource(

$P{SUBREPORT_DIR} + "LocacoesPorClientes_Locacoes.jasper"

)]]></subreportExpression>

</subreport>

<staticText>

<reportElement x="0" y="72" width="555" height="20"/>

<textElement textAlignment="Center" verticalAlignment="Middle">

<font size="12" isBold="true"/>

</textElement>

<text><![CDATA[Filmes alugados]]></text>

</staticText>

<line>

<reportElement x="0" y="71" width="555" height="1"/>

</line>

<line>

<reportElement x="0" y="92" width="555" height="1"/>

</line>

</band>

</detail>

<pageFooter>

<band height="22" splitType="Stretch">

<textField>

<reportElement x="455" y="2" width="100" height="20"/>

<textElement textAlignment="Right" verticalAlignment="Middle"/>

<textFieldExpression class="java.lang.Integer"><![CDATA[$V{PAGE_NUMBER}]]></textFieldExpre

Page 127: Manual Ireport

6

1

2

7

1

2

8

1

2

9

1

3

0

1

3

1

1

3

2

1

3

3

1

3

4

1

3

5

1

3

6

1

3

7

1

3

ssion>

</textField>

<line>

<reportElement x="0" y="1" width="555" height="1"/>

</line>

</band>

</pageFooter>

</jasperReport>

Page 128: Manual Ireport

8

1

3

9

1

4

0

1

4

1

1

4

2

1

4

3

1

4

4

1

4

5

1

4

6

1

4

7

1

4

8

1

4

9

1

5

Page 129: Manual Ireport

0

1

5

1

1

5

2

1

5

3

1

5

4

1

5

5

1

5

6

1

5

7

1

5

8

1

5

9

1

6

0

1

6

1

1

6

Page 130: Manual Ireport

2

1

6

3

1

6

4

1

6

5

1

6

6

1

6

7

1

6

8

1

6

9

1

7

0

1

7

1

1

7

2

1

7

3

1

7

Page 131: Manual Ireport

4

1

7

5

1

7

6

1

7

7

1

7

8

1

7

9

1

8

0

1

8

1

1

8

2

1

8

3

1

8

4

1

8

5

1

8

Page 132: Manual Ireport

6

1

8

7

1

8

8

1

8

9

1

9

0

1

9

1

1

9

2

1

9

3

1

9

4

1

9

5

1

9

6

1

9

7

1

9

Page 133: Manual Ireport

8

1

9

9

2

0

0

2

0

1

2

0

2

2

0

3

2

0

4

2

0

5

2

0

6

2

0

7

2

0

8

2

0

9

2

1

Page 134: Manual Ireport

0

2

1

1

2

1

2

2

1

3

2

1

4

2

1

5

2

1

6

2

1

7

2

1

8

2

1

9

LocacoesPorClientes_Locacoes.jrxml

1

2

3

4

<?xml version="1.0" encoding="UTF-8"?>

<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreport

s http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="LocacoesPorClientes_Locacoes" language="groovy" pageWidth="554" pageHeight="802" columnWidth="554" leftMargin="0" rightMargin="0"

Page 135: Manual Ireport

5

6

7

8

9

1

0

1

1

1

2

1

3

1

4

1

5

1

6

1

7

1

8

1

9

2

0

2

1

2

2

2

3

topMargin="0" bottomMargin="0">

<property name="ireport.zoom" value="1.0"/>

<property name="ireport.x" value="0"/>

<property name="ireport.y" value="0"/>

<parameter name="idCliente" class="java.lang.Integer"/>

<queryString>

<![CDATA[SELECT

f.title titulo,

f.release_year anoLancamento,

r.return_date dataDevolucao

FROM

customer c,

rental r,

inventory i,

film f

WHERE

/* junções */

r.customer_id = c.customer_id AND

r.inventory_id = i.inventory_id AND

i.film_id = f.film_id AND

/* restrições */

c.customer_id LIKE $P{idCliente} AND

r.return_date IS NOT NULL

ORDER BY r.return_date, f.title;]]>

</queryString>

Page 136: Manual Ireport

2

4

2

5

2

6

2

7

2

8

2

9

3

0

3

1

3

2

3

3

3

4

3

5

3

6

3

7

3

8

3

9

4

0

<field name="titulo" class="java.lang.String"/>

<field name="anoLancamento" class="java.sql.Date"/>

<field name="dataDevolucao" class="java.sql.Timestamp"/>

<background>

<band splitType="Stretch"/>

</background>

<columnHeader>

<band height="25">

<staticText>

<reportElement x="0" y="0" width="100" height="20"/>

<textElement textAlignment="Center" verticalAlignment="Middle">

<font isBold="true"/>

</textElement>

<text><![CDATA[Devolvido em]]></text>

</staticText>

<staticText>

<reportElement x="103" y="0" width="47" height="20"/>

<textElement verticalAlignment="Middle">

<font isBold="true"/>

</textElement>

<text><![CDATA[Título]]></text>

</staticText>

<staticText>

<reportElement x="326" y="0" width="117" height="20"/>

<textElement verticalAlignment="Middle">

<font isBold="true"/>

</textElement>

<text><![CDATA[Ano de Lançamento]]></text>

</staticText>

Page 137: Manual Ireport

4

1

4

2

4

3

4

4

4

5

4

6

4

7

4

8

4

9

5

0

5

1

5

2

5

3

5

4

5

5

5

6

5

7

<line>

<reportElement x="0" y="24" width="554" height="1"/>

</line>

</band>

</columnHeader>

<detail>

<band height="21" splitType="Stretch">

<textField pattern="dd/MM/yyyy">

<reportElement x="0" y="1" width="100" height="20"/>

<textElement textAlignment="Center" verticalAlignment="Middle"/>

<textFieldExpression class="java.sql.Timestamp"><![CDATA[$F{dataDevolucao}]]></textFieldEx

pression>

</textField>

<textField>

<reportElement x="103" y="1" width="219" height="20"/>

<textElement verticalAlignment="Middle"/>

<textFieldExpression class="java.lang.String"><![CDATA[$F{titulo}]]></textFieldExpression>

</textField>

<textField pattern="yyyy">

<reportElement x="326" y="1" width="117" height="20"/>

<textElement verticalAlignment="Middle"/>

<textFieldExpression class="java.util.Date"><![CDATA[$F{anoLancamento}]]></textFieldExpres

sion>

</textField>

</band>

</detail>

</jasperReport>

Page 138: Manual Ireport

5

8

5

9

6

0

6

1

6

2

6

3

6

4

6

5

6

6

6

7

6

8

6

9

7

0

7

1

7

2

7

3

7

4

Page 139: Manual Ireport

7

5

7

6

7

7

7

8

7

9

8

0

8

1

8

2

8

3

8

4

O preview da versão final do meu relatório ficou assim:

Page 140: Manual Ireport

Versão final do relatório

Então é isso! Terminamos mais uma parte do tutorial! Espero que tenham gostado e que

tenha auxiliado quem ainda tinha dificuldade com os subrelatórios. O projeto finalizado

desta parte do tutorial pode ser obtido neste link. Na próxima parte do tutorial iremos

aprender a trabalhar com outros tipos de datasources além das conexões que estamos

usando até agora.

Grande abraço a todos! Até a próxima parte ;)

Parte 1 – Parte 2 – Parte 3 – Parte 4 – Parte 5

JasperReports: Trabalhando com Relatórios em Java –

Parte 4 (Diferentes tipos de Fontes de Dados –

Datasources)

Filed under: Java, Programação, Relatórios — 15 Comentários

11/11/2010

Page 141: Manual Ireport

9 Votes

Parte 1 – Parte 2 – Parte 3 – Parte 4 – Parte 5

Olá a todos! Finalmente, depois de um bom tempo sem postar, vamos à quarta parte do

tutorial sobre relatórios! Nesta parte iremos aprender a usar outros tipos de datasources

para obtermos os dados que serão apresentados nos nossos relatórios. Como de

costume, vou explicar como fazer para utilizar a funcionalidade, permitindo que vocês

consigam caminhar sozinhos posteriormente.

Nas três partes anteriores, a nossa fonte de dados era uma conexão JDBC que era usada

para executar uma query SQL. A partir do resultado da query, o JasperReports

preenchia o relatório para nós. Imagine agora a seguinte situação: Eu tenho uma lista de

objetos do tipo ―Cliente‖ e quero exibir essa lista de clientes em um relatório. Note que

eu já tenho a lista, que foi obtida de alguma forma, ou seja, usando um DAO, ou

executando uma query pelo Hibernate.

Para conseguir fazer isso, utilizamos outros tipos de datasources. Se você está seguindo

o tutorial desde o início, seu projeto do NetBeans deve estar preparado para iniciarmos.

Caso não esteja seguindo, faça o download do projeto clicando aqui. Abra o projeto, e

procure pela classe ―ReportUtils‖ no pacote ―tutorialrelatorios.util‖. O código dela deve

estar assim:

tutorialrelatorios.util.ReportUtils.java

1

2

3

4

5

6

7

package tutorialrelatorios.util;

import java.awt.BorderLayout;

import java.io.InputStream;

import java.sql.Connection;

import java.util.Map;

import javax.swing.JFrame;

Page 142: Manual Ireport

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

import net.sf.jasperreports.engine.JRDataSource;

import net.sf.jasperreports.engine.JRException;

import net.sf.jasperreports.engine.JasperFillManager;

import net.sf.jasperreports.engine.JasperPrint;

import net.sf.jasperreports.swing.JRViewer;

/**

* Classe com métodos utilitários para executar e abrir relatórios.

*

* @author David Buzatto

*/

public class ReportUtils {

/**

* Abre um relatório usando uma conexão como datasource.

*

* @param titulo Título usado na janela do relatório.

* @param inputStream InputStream que contém o relatório.

* @param parametros Parâmetros utilizados pelo relatório.

* @param conexao Conexão utilizada para a execução da query.

* @throws JRException Caso ocorra algum problema na execução do

relatório

*/

public static void openReport(

String titulo,

InputStream inputStream,

Map parametros,

Connection conexao ) throws JRException {

/*

Page 143: Manual Ireport

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

* Cria um JasperPrint, que é a versão preenchida do

relatório,

* usando uma conexão.

*/

JasperPrint print = JasperFillManager.fillReport(

inputStream, parametros, conexao );

// abre o JasperPrint em um JFrame

viewReportFrame( titulo, print );

}

/**

* Abre um relatório usando um datasource genérico.

*

* @param titulo Título usado na janela do relatório.

* @param inputStream InputStream que contém o relatório.

* @param parametros Parâmetros utilizados pelo relatório.

* @param dataSource Datasource a ser utilizado pelo relatório.

* @throws JRException Caso ocorra algum problema na execução do

relatório

*/

public static void openReport(

String titulo,

InputStream inputStream,

Map parametros,

JRDataSource dataSource ) throws JRException {

/*

* Cria um JasperPrint, que é a versão preenchida do

relatório,

Page 144: Manual Ireport

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

* usando um datasource genérico.

*/

JasperPrint print = JasperFillManager.fillReport(

inputStream, parametros, dataSource );

// abre o JasperPrint em um JFrame

viewReportFrame( titulo, print );

}

/**

* Cria um JFrame para exibir o relatório representado pelo

JasperPrint.

*

* @param titulo Título do JFrame.

* @param print JasperPrint do relatório.

*/

private static void viewReportFrame( String titulo, JasperPrint print ) {

/*

* Cria um JRViewer para exibir o relatório.

* Um JRViewer é uma JPanel.

*/

JRViewer viewer = new JRViewer( print );

// cria o JFrame

JFrame frameRelatorio = new JFrame( titulo );

// adiciona o JRViewer no JFrame

Page 145: Manual Ireport

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

frameRelatorio.add( viewer, BorderLayout.CENTER );

// configura o tamanho padrão do JFrame

frameRelatorio.setSize( 500, 500 );

// maximiza o JFrame para ocupar a tela toda.

frameRelatorio.setExtendedState( JFrame.MAXIMIZED_BOTH );

// configura a operação padrão quando o JFrame for fechado.

frameRelatorio.setDefaultCloseOperation(

JFrame.DISPOSE_ON_CLOSE );

// exibe o JFrame

frameRelatorio.setVisible( true );

}

}

Note que nessa classe existem dois métodos chamados ―openReport(…)‖. O primeiro

deles é o que utilizamos até agora, que recebe uma String que vai ser usada como título

do JFrame utilizado como container do relatório, um InputStream que vai ser usado para

obtermos o arquivo .jasper, um Map que contém os parâmetros passados para o relatório

e, por fim, uma Connection para a base de dados que usamos na query do relatório.

Note que o segundo método ―openReport(…)‖ tem praticamente a mesma assinatura do

primeiro, mudando apenas o último parâmetro, que nessa versão do método é um

JRDataSource. A implementação do método é igual ao outro, com a diferença de ser

passado o JRDataSource para o JasperFillManager.fillReport(…) ao invés da

Connection.

Page 146: Manual Ireport

O JRDataSource é uma interface que define o contrato que os datasources devem seguir

para que o JasperReports possa usar os dados contidos neles dentro do relatório. A

documentação da interface JRDataSource pode ser vista clicando aqui. Ao analisar a

documentação, vocês vão ver que existem diversas implementações da interface

JRDataSource. Nós vamos focar em duas:

JRBeanCollectionDataSource: Utilizada para usar coleções como fonte de dados, ou seja, qualquer classe que implemente – ou interface que estenda – a interface java.util.Collection. Por exemplo, um ArrayList, que implementa a interface List que por sua vez estende a interface Collection. A documentação deste tipo de datasource pode ser vista clicando aqui;

JRBeanArrayCollectionDataSource: Utilizado para usar arrays de objetos como fonte de dados. A documentação deste tipo de datasource pode ser vista clicando aqui.

Legal não é? Então, além da conexão JDBC, nós podemos utilizar vários outros tipos de

datasources. Vou o primeiro deles, e depois a utilização do segundo vai ficar como

exercício. Não vou explicar cada um dos tipos existentes, pois o funcionamento deles é

sempre muito parecido. Se você precisar de outro tipo de datasource, basta ler a

documentação.

A utilização dos datasources não é complicada, bastando você criar um objeto do tipo

do datasource desejado e passar o parâmetro que ele espera, entretanto precisamos

alterar uma configuração no iReport para indicar ao compilador onde estão as classes

que vamos utilizar para instanciar os objetos e enviar no datasource. Antes de fazer isso,

vamos criar uma classe no nosso projeto, sendo que essa classe será utilizada como a

nossa entidade. Nós vamos instanciar objetos dessa classe manualmente, mas em um

caso real, esses objetos virão de algum outro lugar, como uma query do Hibernate como

eu já mencionei. Vamos lá então!

Clique com o botão direito no pacote ―tutorialrelatorios‖, escolha New -> Java Package.

Se esta opção não estiver sendo exibida, clique em Other, escolha a categoria Java e em

File Type escolha Java Package. Com o assistente aberto, insira

―tutorialrelatorios.entidades‖ (sem as aspas) em Package Name e clique em Finish. O

pacote será criado. Clique com o botão direito neste pacote, escolha New -> Java Class.

Preencha o campo Class Name com ―Cliente‖ (sem as aspas) e clique em Finish. A

classe será gerada e será aberta no editor. Crie os campos id (privado, Long), nome

(privado, String) e sobrenome (privado, String). Com os campos criados, gere os gets e

os sets. Segue o código da classe Cliente.

tutorialrelatorios.entidades.Cliente.java

1

2

3

4

5

package tutorialrelatorios.entidades;

/**

* Representa um Cliente.

*

Page 147: Manual Ireport

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

* @author David Buzatto

*/

public class Cliente {

private Long id;

private String nome;

private String sobrenome;

public Long getId() {

return id;

}

public void setId( Long id ) {

this.id = id;

}

public String getNome() {

return nome;

}

public void setNome( String nome ) {

this.nome = nome;

}

public String getSobrenome() {

return sobrenome;

}

public void setSobrenome( String sobrenome ) {

Page 148: Manual Ireport

33

34

35

36

37

38

this.sobrenome = sobrenome;

}

}

Agora, antes de partirmos para o nosso relatório, precisamos configurar o iReport para

enxergar as classes do nosso projeto, permitindo assim que possamos utilizar nossas

entidades no relatório. Antes disso, dê um build no projeto (botão direito no projeto,

Build, ou Clean and Build), para que o diretório de build seja gerado, ou seja, o

diretório que contém os arquivos compilados no nosso projeto. Com o build feito, entre

no menu Tools e vá em Options. Clique no botão do iReport e procure pela guia

Classpath. Com a guia aberta, clique no botão Add Folder. Ao clicar no botão, será

exibido um diálogo para você procurar a pasta desejada. Nós precisamos encontrar a

pasta build/classes do nosso projeto. No meu caso, eu estou salvando o projeto em

―C:\Users\David\Documents\Blog\tutoriais‖, então o build/classes está localizado em

―C:\Users\David\Documents\Blog\tutoriais\TutorialRelatorios\build\classes‖. Procure

então pelo o seu build/classes, selecione o diretório e clique em Open. O editor de

opções da IDE deve ficar assim:

Page 149: Manual Ireport

Editando o Classpath do iReport

Com isso feito, o iReport vai conseguir enxergar as classes do nosso projeto, além de

permitir que objetos de nossas classes possam ser utilizadas dentro do relatório. Vamos

criar nosso relatório então? Clique então com o botão direito no <default package> da

nossa pasta de definições de relatórios, escolha New -> Empty Report. Como já temos

um relatório chamado Clientes (que usa uma query lembram?), vamos dar o nome nesse

relatório de ClientesCollectionDS, pois vamos utilizar o datasource do tipo

JRBeanCollectionDataSource. Assim que clicar em Finish no assistente de criação de

relatórios, o arquivo ClientesCollectionDS.jrxml será gerado e será aberto no editor.

Para simplificar, remova todas as bandas, exceto a Title, a Column Header e a Detail.

Na banda Title crie um campo de texto estático e defina o título do relatório. O meu

ficou assim:

Page 150: Manual Ireport

Layout Inicial do Relatório de Clientes usando Collection DS

Agora chegou a parte onde vamos obter os atributos da nossa entidade Cliente. Clique

no botão usado para editar a query do relatório e acesse a guia ―JavaBean Datasource‖.

Note que não vamos criar uma query. Com a aba aberta, preencha o campo ―Class

name‖ com ―tutorialrelatorios.entidades.Cliente‖ (sem as aspas) e clique no botão Read

Attributes. Vão ser lidos 4 atributos: class, id, nome e sobrenome. Selecione todos,

exceto o class e clique em ―Add selected field(s)‖. Ao fazer isso, os campos serão

inseridos na tabela de campos do editor. Veja a Figura abaixo.

Page 151: Manual Ireport

Carregando Campos de Uma Classe

Perceba que você precisa inserir o nome completo da classe (pacote + nome da classe)

para que o iReport encontre a classe e a possa utilizar no relatório. Com isso feito,

clique em OK. Os campos serão criados no Report Inspector da mesma forma que

seriam criados caso estivéssemos usando uma query tradicional. Agora que os campos

estão criados, basta vocês montarem o relatório, arrastando os campos para a banda

Detail e editando o título de cada um deles. O meu ficou assim:

Page 152: Manual Ireport

Layout Final do Relatório de Clientes usando Collection DS

Note que se vocês tentarem dar um ―Preview‖ no relatório, vocês serão avisados que o

relatório não contém páginas, justamente porque não existem dados para serem

exibidos. É possível criar um datasource para ser usado no preview do relatório, mas

isso eu vou deixar como exercício para vocês caso vocês queiram descobrir como faz :).

Compilem o relatório e vamos agora modificar o método main da classe Main para

chamar o relatório criado, passando os dados para o relatório. Abra a classe Main do

projeto e copiem o método abrirRelatorioClientes. Mudem o nome do método copiado

para abrirRelatorioClientesDS. Agora, como exercício antes de ver o código pronto,

tentem chamar o novo relatório, criando um JRBeanCollectionDataSource e passando

para o método openReport. Conseguiram? Espero que sim! Segue o código completo da

classe Main.

tutorialrelatorios.Main.java

1

2

3

4

5

6

package tutorialrelatorios;

import java.io.InputStream;

import java.sql.SQLException;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;

Page 153: Manual Ireport

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

import java.util.Map;

import net.sf.jasperreports.engine.JRDataSource;

import net.sf.jasperreports.engine.JRException;

import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;

import tutorialrelatorios.entidades.Cliente;

import tutorialrelatorios.jdbc.ConnectionFactory;

import tutorialrelatorios.util.ReportUtils;

/**

* Ponto de entrada do projeto.

*

* @author David Buzatto

*/

public class Main {

/**

* @param args the command line arguments

*/

public static void main(String[] args) {

new Main().abrirRelatorioClientesDS();

}

public void abrirRelatorioClientes() {

InputStream inputStream = getClass().getResourceAsStream(

"/LocacoesPorClientes.jasper" );

Map parametros = new HashMap();

parametros.put( "nomeCliente", "F%" );

Page 154: Manual Ireport

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

try {

ReportUtils.openReport( "Locações por Clientes",

inputStream, parametros,

ConnectionFactory.getSakilaConnection() );

} catch ( SQLException exc ) {

exc.printStackTrace();

} catch ( JRException exc ) {

exc.printStackTrace();

}

}

public void abrirRelatorioClientesDS() {

InputStream inputStream = getClass().getResourceAsStream(

"/ClientesCollectionDS.jasper" );

Map parametros = new HashMap();

// criando os dados que serão passados ao datasource

List dados = new ArrayList();

for ( long i = 1; i <= 50; i++ ) {

Cliente c = new Cliente();

c.setId( i );

c.setNome( "Nome Cliente " + i );

c.setSobrenome( "Sobrenome Cliente " + i );

dados.add( c );

Page 155: Manual Ireport

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

}

// criando o datasource com os dados criados

JRDataSource ds = new JRBeanCollectionDataSource( dados );

try {

// passando o datasource para o método de criação e

exibição do relatório

ReportUtils.openReport( "Clientes - Bean Collection Data

Source", inputStream, parametros,

ds );

} catch ( JRException exc ) {

exc.printStackTrace();

}

}

}

Ao executar a classe Main, o relatório será exibido. O meu ficou assim:

Page 156: Manual Ireport

Exibição Final do Relatório Criado

Como exercício, reaproveitem o método criado para utilizar um

JRBeanArrayDataSource. Lembrem-se que um datasource deste tipo espera um array,

não uma coleção.

Com isso finalizamos a quarta parte do tutorial! O projeto com o estado atual do nosso

tutorial pode ser baixado clicando-se aqui. Na próxima parte do tuorial, iremos aprender

como utilizar os relatórios em páginas Web, finalizando então o básico que vocês

devem saber para poder trabalhar com relatórios. Até mais! Grande abraço!

Parte 1 – Parte 2 – Parte 3 – Parte 4 – Parte 5

JasperReports: Trabalhando com Relatórios em Java –

Parte 5 (Relatórios na Web)

Filed under: Java, Programação, Relatórios, Web — 37 Comentários

12/11/2010

Page 157: Manual Ireport

10 Votes

Parte 1 – Parte 2 – Parte 3 – Parte 4 – Parte 5

Olá a todos! Nesta quinta e última parte do nosso tutorial, iremos aprender a como usar

os nossos relatórios em um projeto Web. Esse parte do tutorial vai ser rápida, pois já

temos praticamente tudo o que precisamos. Primeiro gostaria de pedir para quem não

está acompanhando o tutorial, que baixe o projeto finalizado na Parte 4 clicando aqui.

Iremos criar um novo projeto no NetBeans, só que agora do tipo Web e vamos

configurá-lo com base no que já fizemos no nosso projeto original. Vamos lá então!

No NetBeans, vá em File -> New Project. No assistente de criação de projetos, escolha

―Java Web‖ na lista de categorias e na lista de tipos de projetos, escolha ―Web

Application‖. Clique em ―Next‖. Em ―Project Name‖ dê o nome do projeto. Eu sugiro

―TutorialRelatoriosWeb‖ (sem as aspas). Em ―Project Location‖ escolha onde o projeto

vai ser salvo. Eu vou deixar na mesma pasta do projeto original. Marque a opção ―Use

Dedicated Folder for Storing Libraries‖ e deixe o valor padrão (.\lib). Se quiser, marque

a opção ―Set as Main Project‖. Clique em ―Next‖.

No próximo passo, onde é configurado o servidor que a aplicação vai ser executada, eu

vou deixar o Tomcat escolhido. Se vocês preferirem usar outro servidor, não tem

problema, basta selecioná-lo na lista. Deixe desmarcada a opção ―Use dedicated library

folder for server JAR files‖. Em ―JavaEE version‖, deixe escolhida a versão padrão,

pois não precisamos nos preocupar com isso no nosso projeto de testes. No meu caso,

ficou selecionado Java EE 5. Em ―Context Path‖ deixe o valor sugerido. No meu caso, é

―/TutorialRelatoriosWeb‖. Como não vamos usar nenhum framework MVC, você já

pode clicar em ―Next‖. Feito isso, o projeto será criado e será aberto no NetBeans.

Com o projeto criado, acesse suas propriedades clicando com botão direito na raiz do

projeto e escolhendo a opção ―Properties‖, que é a última da lista. Em ―Categories‖

procure pelo item ―Run‖ e selecione-o. Desmarque a opção ―Deploy on Save‖ para

evitar que seja feito um deploy a cada vez que salvarmos algo do nosso projeto. Já que

estamos aqui, vamos aproveitar para configurar as bibiliotecas. Não vou colocar as

figuras desse processo, pois já foi explicado nas primeiras partes do tutorial.

Selecione o item ―Libraries‖ na lista de categorias e clique no botão ―Add Library‖.

Primeiro vamos importar o driver do MySQL que vamos utilizar. Na janela que foi

aberta, clique no botão ―Import‖. Procure pela biblioteca ―MySQL JDBC Driver‖,

selecione-a e clique no botão ―Import Library‖. A biblioteca vai ser importada e

aparecerá na janela anterior, mas ela ainda não foi inserida no projeto. Antes de a

inserirmos, vamos criar a biblioteca do JasperReports. Para isso, clique no botão

―Create…‖. Em ―Library Name‖ entre com o valor ―JasperReports-3.7.5‖ (sem as

aspas) e clique em ―OK‖. Note que eu vou manter a versão do JasperReports utilizado

nas partes anteriores do tutorial, sendo assim sua versão pode variar dependendo de

quando você estiver seguindo esse tutorial, visto que novas versões do JasperReports

Page 158: Manual Ireport

são lançadas frequentemente. Se a versão que você estiver usando for mais nova, vamos

dizer, 3.7.6, defina um nome da biblioteca que reflita a versão utilizada, ou seja

―JasperReports-3.7.6‖.

Feito isso, a janela ―Customize Library‖ será exibida. Clique no botão ―Add

JAR/Folder‖. Como já fizemos isso uma vez nas partes anteriores do tutorial, o projeto

original já tem essa biblioteca configurada com os JARs necessários. Então vamos usá-

los. Procure pela pasta do projeto original (TutorialRelatorios). Dentro dela, entre na

pasta ―lib‖. Dentro da pasta ―lib‖, existirá uma pasta chamada ―JasperReports-3.7.5‖. O

número da versão pode variar de acordo com a sua versão. Entre nela, selecione todos

os JARs e clique no botão ―Add JAR/Folder‖. O NetBeans vai perguntar se você quer

criar um diretório com o nome da biblioteca dentro da pasta ―lib‖ do projeto atual

(TutorialRelatoriosWeb). Diga que sim e os JARs serão listados na janela ―Customize

Library‖. Clique em OK.

Novamente a janela ―Add Library‖ será exibida, agora contendo a também a biblioteca

do JasperReports que acabamos de configurar. Selecione tanto a biblioteca do

JasperReports quanto a biblioteca do MySQL e clique no botão ―Add Library‖. Agora

as bibliotecas serão adicionadas no projeto.

Ainda na janela de propriedades, procure a categoria ―Sources‖ (primeira) e selecione-a.

Vamos criar agora o diretório onde guardaremos os nossos fontes do relatório. Na tabela

―Source Package Folders‖, clique no botão ―Add Folder…‖. Serão exibidas os

diretórios contidos no projeto. Crie então uma nova pasta, chamada ―relatorios‖ (sem

acentos e sem aspas), selecione-a e clique em ―Open‖. A pasta será referenciada na

tabela. Clique duas vezes na célula correspondente à coluna ―Label‖ da pasta, preencha

com ―Relatórios‖ (sem as aspas) e tecle <ENTER> para trocar o ―Label‖ da pasta. Esse

―Label‖ vai ser utilizado para mostrar a pasta de relatórios na árvore do projeto.

Estamos quase lá. Por fim, ainda na janela de propriedades, selecione a categoria

―Packaging‖, dentro da categoria ―Build‖. Em ―Exclude From WAR File‖, adicione

uma vírgula e o valor ―**./*.jrxml‖ (sem as aspas). Isso fará com que os nossos

arquivos fonte de relatórios não sejam empacotados no arquivo WAR. O valor final do

campo deve ficar assim: ―**/*.java,**/*.form, **/*.jrxml‖ (sem as aspas). Pronto!

Clique em OK na janela de propriedades e aguarde o NetBeans escanear as novas

configurações do projeto.

Agora, abra o projeto anterior, vá na pasta de ―Relatórios‖ dele, copie o arquivo

―ClientesPorNome.jrxml‖ e cole na pasta ―Relatórios‖ do novo projeto. Ainda não feche

o projeto anterior. No projeto atual, abra o relatório que foi copiado e faça um Preview

dele para ver se está tudo ok. Lembre-se que o datasource correto (Sakila – JDBC) tem

que estar selecionado lá na barra de ferramentas do NetBeans. Se o relatório for

renderizado e os dados aparecerem é porque está tudo ok.

Até agora nenhuma novidade. Criamos e configuramos o novo projeto e copiamos e

testamos o arquivo de relatório que já fizemos para o novo projeto. Agora vamos às

novidades.

Vamos criar um Servlet que vai ser responsável em pegar os possíveis dados do request

que serão usados como parâmetros para os relatórios e invocar o JasperReports para

Page 159: Manual Ireport

criar o relatório. O funcionamento é parecido com o que fizemos no nosso programa

desktop, entretanto agora não iremos mais criar um JFrame para exibir os relatórios,

pois estamos usando um navegador não é mesmo? O que o nosso Servlet vai fazer é

criar diretamente um arquivo .pdf do relatório e mandar exibir no navegador – caso haja

algum plugin para leitura de PDF instalado – ou então o navegador vai sugerir que você

faça o download do arquivo gerado.

Em ―Source Packages‖, crie três pacotes: ―tutorialrelatoriosweb.jdbc‖,

―tutorialrelatoriosweb.servlets‖ e ―tutorialrelatoriosweb.util‖ (todos sem as aspas). Vá

no projeto anterior, no pacote ―tutorialrelatorios.jdbc‖, copie a classe

ConnectionFactory e cole no pacote ―tutorialrelatoriosweb.jdbc‖ do novo projeto. Se

quiser, feche o projeto anterior. Agora no novo projeto, vá na pasta

―tutorialrelatoriosweb.util‖ e crie uma classe com o nome de ―ReportUtils‖ (sem as

aspas). Ainda não vamos implementar nada nela. Feito isso, clique com o botão direito

no pacote ―tutorialrelatoriosweb.servlets‖, vá em New -> Servlet. Se a opção Servlet

não estiver sendo exibida, selecione ―Other‖ e em ―Categories‖ selecione ―Web‖ e em

―File Types‖ escolha ―Servlet‖ e clique em ―Next‖.

O assistente para criar um novo Servlet será exibido. Em ―Class Name‖ preencha com

―ReportServlet‖ (sem as aspas) e clique em ―Next‖. Tanto ―Servlet Name‖ quanto

―URL Pattern‖ vão ser deixados da forma que o NetBeans sugeriu, ou seja,

―ReportServlet‖ e ―/ReportServlet‖ respectivamente. Clique em ―Finish‖.

O NetBeans vai gerar por padrão uma implementação padrão do método

processRequest(…). Faça com que o seu fique assim:

1

2

3

4

5

6

7

8

9

10

11

12

protected void processRequest(HttpServletRequest request,

HttpServletResponse response)

throws ServletException, IOException {

OutputStream out = null;

// aqui nós geramos o relatório...

if ( out != null ) {

out.close();

}

}

Page 160: Manual Ireport

Note que ainda não implementamos o método processRequest(…). Da mesma forma

que fizemos no projeto anterior, vamos agora criar um método utilitário na classe

ReportUtils que vai ser responsável em gerar o relatório. Segue a implementação

comentada da classe ReportUtils.

tutorialrelatoriosweb.util.ReportUtils.java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

package tutorialrelatoriosweb.util;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.sql.Connection;

import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import net.sf.jasperreports.engine.JRException;

import net.sf.jasperreports.engine.JRExporter;

import net.sf.jasperreports.engine.JRExporterParameter;

import net.sf.jasperreports.engine.JasperFillManager;

import net.sf.jasperreports.engine.JasperPrint;

import net.sf.jasperreports.engine.export.JRPdfExporter;

/**

* Classe com métodos utilitários para gerar relatórios.

*

* @author David Buzatto

*/

public class ReportUtils {

/**

* Gera o relatório em PDF.

*

Page 161: Manual Ireport

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

* @param inputStream InputStream que contém o relatório.

* @param parametros Parâmetros utilizados pelo relatório.

* @param conexao Conexão utilizada para a execução da query.

* @param response HttpServletResponse que será usado como base

para

* gerar o relatório.

* @return O OutputStream do HttpServletResponse passado.

* @throws JRException Caso ocorra algum problema na geração do

relatório.

* @throws IOException Caso ocorra algum problema na obtenção do

* OutputStream.

*/

public static OutputStream createPDFReport(

InputStream inputStream,

Map<String, Object> parametros,

Connection conexao,

HttpServletResponse response ) throws JRException,

IOException {

// configura o content type do response

response.setContentType( "application/pdf" );

// obtém o OutputStream para escrever o relatório

OutputStream out = response.getOutputStream();

/*

* Cria um JasperPrint, que é a versão preenchida do

relatório,

* usando uma conexão.

*/

JasperPrint jasperPrint = JasperFillManager.fillReport(

Page 162: Manual Ireport

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

inputStream, parametros, conexao );

// Exporta em PDF, escrevendo os dados no output stream do

response.

JRExporter exporter = new JRPdfExporter();

exporter.setParameter( JRExporterParameter.JASPER_PRINT,

jasperPrint );

exporter.setParameter( JRExporterParameter.OUTPUT_STREAM,

out );

// gera o relatório

exporter.exportReport();

// retorna o OutputStream

return out;

}

}

Como vocês podem perceber, o método createPDFReport(…) da classe ReportUtils

gera um relatório em PDF e o escreve no OutputStream do response do Servlet. Caso

vocês queiram outros tipos de exportação, basta mudar o tipo do exportador. Clicando

aqui, vocês podem ver a documentação da interface JRExporter e de todas as classes

que a implementam. Note que ao mudar o exportador, você também precisa alterar o

content type do response para refletir o tipo de arquivo gerado.

Vamos agora atualizar o nosso Servlet. O método processRequest(…) vai ficar assim:

1

2

protected void processRequest(HttpServletRequest request,

HttpServletResponse response)

Page 163: Manual Ireport

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

throws ServletException, IOException {

OutputStream out = null;

// obtém o relatório compilado

InputStream inputStream = getClass().getResourceAsStream(

"/ClientesPorNome.jasper" );

// preenche o mapa de parâmetros

Map<String, Object> parametros = new HashMap<String, Object>();

parametros.put( "primeiroNome", "D%" );

try {

// gera o relatório e atribui o OutputStream gerado

out = ReportUtils.createPDFReport( inputStream, parametros,

ConnectionFactory.getSakilaConnection(), response );

} catch ( SQLException exc ) {

exc.printStackTrace();

} catch ( JRException exc ) {

exc.printStackTrace();

} finally {

// se não aconteceu nenhum problema, fecha o output stream

if ( out != null ) {

out.close();

}

}

Page 164: Manual Ireport

30

31

32

}

Com isso feito, rode a aplicação e aponte o navegador para o endereço

―http://localhost:8084/TutorialRelatoriosWeb/ReportServlet&#8221; (sem as aspas).

Por padrão o Tomcat usado em desenvolvimento no NetBeans roda na porta 8084.

Certifque-se que o seu está rodando nesta porta e se não estiver, use a porta correta. Se

você seguiu corretamente o tutorial até aqui, será gerado então um .pdf com todos os

clientes que tenham o primeiro nome iniciando com a letra ―D‖ (veja o parâmetro

―primeiroNome‖ passado para o relatório).

Note que agora, para passar parâmetros para o relatório, basta você obter os parâmetros

pelo request e então adicionar os parâmetros desejados no mapa de parâmetros do

relatório. Se quiser outros tipos de exportação, por exemplo, para Excel, basta criar um

novo método na classe ReportUtils, que configura o content type apropriado

(―application/ms-excel‖) e o exportador necessário (JRXlsExporter ou JRXlsxExporter).

Tanto a passagem de parâmetros quanto a geração de outros tipos de arquivos ficam

como exercício para vocês. O Servlet ReportServlet pode ser generalizado também,

permitindo que o nome do arquivo do relatório a ser gerao seja passado via request :).

Com isso terminamos nosso tutorial sobre relatórios em Java! Espero que tenham

gostado! Para baixar o projeto criado nesta parte, clique aqui. Nos próximos tutoriais

iremos aprender a usar a biblioteca JavaScript jQuery, que é extremamente útil e facilita

muito a nossa vida.

Então é isso pessoal! Grande abraço a todos! Até a próxima ;)