O tema do meu primeiro post é bem oportuno para mim, pois além de ser um tema de extrema importância no dia a dia de um DEVILoper, nas ultimas semanas não tenho respirado, pensado, dormido, comido , bebido e ouvido outra coisa que não fosse “cuspir relatórios” (chefe, me desculpe por essa heheh), jrxml's, XML, jasper, iReport, massive compiler, XPath, field description, detail ... enfim, todo esse universo maravilhoso e confuso dos relatórios corporativos utilizando JasperReports , IReport e XML como fonte de dados (isso mesmo Xis EME ÉLE). Bem, mas tirando o meu desabafo de lado vamos ao nosso objetivo: Criar um relatório jasper utilizando um arquivo XML como fonte de dados, apresentando dados simples e iterando uma lista.
Para que minha explicação ficasse o mais simples e objetiva possível, decidi criar este guia em 5 etapas :
Primeira etapa, conhecendo o seu XML de dados
Segunda etapa, criar um novo relatório e definir o XML como fonte de dados no Ireport
Terceira etapa, criar os campos de acordo com seu XML
Quarta etapa, configurando a query XPath do relatório e as descrições de cada campo
Quinta etapa, criando a classe java para emitir o relatório
Obs: Quando eu digo simples, é simples mesmo, não abordarei muitos detalhes sobre Xpath, XML, layout, desenho de relatórios no IReport, classes do jasper... então quem não tiver um mínimo de familiaridade com a ferramenta, ou nunca tiver desenhado um relatório na vida pode ter serias dificuldades ao seguir este guia ò.Ô
Primeira etapa, conhecendo o seu XML de dados
Antes mesmo de desenhar um relatório, temos de saber o que vamos apresentar conhecendo a estrutura do nosso datasource. Neste exemplo iremos apresentar um boletim escolar, com os dados de um aluno, e uma lista com seu histórico de desempenho do semestre. Então vamos ao nosso XML de dados:
<?xml version="1.0" encoding="ISO-8859-1"?>
João Pimenta
000123
C
6ª
Português
7,0
8,5
7,75
APROVADO
Matemática
6,5
7,7
7,1
APROVADO
Física
4,0
5,5
4,75
REPROVADO
Quimica
6,0
7,5
6,75
APROVADO
História
8,0
9,0
8,5
APROVADO
Ed. Fisica
10,0
8,5
9,25
APROVADO
Segunda etapa, criar um novo relatório e definir o XML como fonte de dados no Ireport:
Para criar um novo relatório clique na barra de menu em Arquivo>Novo Documento ou pressione CTRL + N, aparecera uma janela onde você devera informar as propriedades do relatório, nomeie o arquivo e na aba “i18n” defina a codificação XML para ISO-8859-1 (mesma codificação do XML datasource) para que o relatório tenha suporte a acentos assim como mostra a figura 1.
Figura 1- Criando um novo relatório
Desenhe o seu relatório de acordo com o nosso exemplo mostrado na figura 2, lembrando que os campos do XML que pertencem a uma lista a ser iterada, devem sempre ficar na banda “Detail” do relatório, e que para dados de campos devemos utilizar o elemento “TextField” (Campo Texto) .
Figura 2 – Nosso template do Boletim
Agora vamos definir o arquivo “Boletim.xml” como o datasource do nosso relatório, para isso clique na barra de menu em “Data>Conexões/Fonte de dados “ , na janela que mostra as suas conexões clique em “novo” e na lista de opções clique em “Fonte de dados de arquivo XML” , em seguida defina um nome para a conexão, localize o arquivo XML de dados através do botão “Navegar” e marque a opção “Use a expressão de relatório Xpath quando preencher o relatório” como mostrado na figura 3.
Figura 3 – criando a conexão com o XML datasource
Clique em “Teste” e se houver sucesso clique em “Salvar”.
Terceira etapa, criar os campos do relatório de acordo com seu XML
Para que sejam apresentados os valores do XML de dados em nosso relatório, precisamos definir estes campos, dando a cada um deles um nome e informando através da descrição do campo o caminho da informação. O IReport utiliza o XPath para varrer os valores de um arquivo XML. Para criar os campos, clique em “visualizar>campos do relatório” , aparecera uma janela vazia, pois ainda não definimos os nomes de campos e suas descrições (caminho), nesta janela clique em “novo” para criar um campo, no exemplo a seguir mapearemos o campo ALUNO_NOME do XML, com o tipo “String”, o processo para a criação dos demais campos é praticamente o mesmo, porem existem algumas peculiaridades ao informar a “descrição do campo” (Field Description) que veremos a seguir.
Figura 4 – Mapeando um campo no IReport
Observe que na descrição do campo colocamos a seguinte XPath “//ALUNO_NOME”
, o “//NOME_DO_NO” é utilizado na notação do XPath para buscar o valor de um nó em todo o documento XML, só deve ser utilizado caso o nome deste campo não se repita pelo arquivo e não faça parte de uma lista. Para os campos que tem de ser iterados pela band “Detail”, ou seja, que fazem parte de uma lista, a descrição do campo ficara um pouco diferente, pois utilizaremos a query XPath do relatório, é o que veremos no passo a seguir .
http://www.zvon.org/xxl/XPathTutorial/General/examples.html
http://www.w3schools.com/XPath/default.asp
http://ireport.sourceforge.net/cap7.html
Quarta etapa, configurando a query XPath do relatório e as descrições de cada campo
Vamos escrever a consulta geral do relatório que será utilizada pela band “detail” trazendo as informações de uma lista. Nossa lista consiste em um conjunto de disciplinas que estão no caminho “/BOLETIM/DISCIPLINAS/DISCIPLINA” dentro do XML de dados. Para isto clique em “editar>query do relatório” , aparecerá a janela a seguir:
Figura 5 – A consulta XPath do relatório
Agora crie os campos que ficarão dentro do detail como mostra a figura a seguir:
Figura 6 – Campo dentro do detail
Neste exemplo coloquei o nome do campo totalmente diferente da sua descrição propositalmente apenas para mostra que o nome do campo não precisa necessariamente ser igual ao nome do nó do XML de dados ao qual ele se refere, porem em sua descrição devemos utilizar EXATAMENTE o mesmo nome na consulta XPath. Você deve estar se perguntando agora “onde esta o // antes da palavra ‘NOME’ ?” , e eu lhe respondo: meu caro padawan, na query geral do relatório já informamos o caminho deste campo, por isto apenas o nome do nó do XML de dados se faz necessário . Após criar todos os campos, adicione os mesmos dentro de cada textfield , substituindo a expressão “$F{Field}” por “$F{NOME_DO_CAMPO_CORRESPONDENTE}” (Ex: $F{ALUNO_NOME} ) e teste dentro do Ireport clicando no botão (Executar Relatório usando conexão ativa).
O resultado esperado apresentado no “JasperViewer” (aplicação interna do IReport), será o da figura a seguir:
Figura 7 – Relatório emitido dentro do IReport
Quinta etapa, criando a classe java para emitir o relatório
Agora vamos renderizar nosso relatório através de uma classe java. Para isto crie um projeto java em sua IDE favorita (no meu caso eclipse hehe) , para este exemplo precisaremos das bibliotecas apresentadas na figura a seguir configuradas no classpath de sua aplicação:
itext-1.3.1.jar
jasperreports-3.0.0.jar
xalan.jar
commons-beanutils-1.7.jar
commons-logging-1.0.2.jar
commons-collections-2.1.jar
Figura 8 – Bibliotecas necessárias para o projeto encontradas no diretório “lib” da instalação do IReport
Agora, adicione a seguinte classe ao seu projeto (fique atento ao nome do pacote caso não crie um pacote “com.blogspot.javadevilopers” como no nosso exemplo):
package com.blogspot.javadevilopers;
import java.util.HashMap;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.data.JRXmlDataSource;
import net.sf.jasperreports.view.JasperViewer;
public class EmiteRelatorio {
public static void main(String[] args) {
try {
//Caminho do arquivo Boletim.jasper (bytecode gerado/compilado do nosso relatorio Boletim.jrxml)
String relatorio = System.getProperty("user.dir") + "/src/com/blogspot/javadevilopers/relatorio/Boletim.jasper";
//Configurando a classe JRXmlDataSource que apontara o caminho do nosso XML de dados e sua pesquisa XPath geral
JRXmlDataSource xml =
new JRXmlDataSource("C:/JavaDEVILopers/Guia_JasperReports_Ireport_ XML_5_etapas_JavaDEVILopers/XMLBoletim.xml",
"/BOLETIM/DISCIPLINAS/DISCIPLINA");
/*Gerando o relatorio (Filling) informando o caminho do relatorio, os parametros
(neste caso nenhum paramentro esta sendo passado ao relatorio, por isso o HashMap esta vazio)
e o objeto JRXmlDataSource configurado)*/
JasperPrint jp = JasperFillManager.fillReport(relatorio, new HashMap(),xml);
//Utilizando o JasperView, uma classe desktop do jasper para visualização dos relatorios
JasperViewer.viewReport(jp,false);
} catch (JRException e) {
e.printStackTrace();
}
}
}
Fique atento aos caminhos de localização do seu arquivo de datasource (XML de dados) e do seu arquivo .jasper (relatorio compilado) e altere na classe, infelizmente eu não estou nem um pouco a fim de entregar de bandeja toda a confighuração do projeto, alias vocês já são bem grandinhos e meu objetivo não é mastigar tudo não, quem tem filho barbado é gato e eu já deixei este código bem comentado , parem de chorar . Execute a sua classe e “tcharam” , temos um relatório renderizado no JasperViewer como mostrado a seguir:
Figura 9 - Relatorio Emitido por nossa classe java
Por fim espero que tenham gostado do meu singelo post, desculpem se não me aprofundei nos detalhes mas brevemente nossa equipe trará novos artigos, tutoriais, dicas e guias com foco também para iniciantes. Qualquer duvida postem nos comentarios deixando seu email para contato ou me contatem pelo email edu.medeirospereira@gmail.com .
Abraços!
Mto bom seu post! Era justamente o que eu estava precisando. Pelo iReport consegui compilar perfeitamente, mas qndo tento pela minha aplicação os campos do detalhe do relatório não são exibidos. Você teria idéia de pq isso acontece?
ResponderExcluirou o Xpath para varredura do XML esta errado ou o atributo "id" no XML não existe para cada registro do detail no seu datasource... tirando estas duas hipoteses não consigo ver outra causa para tal erro
ResponderExcluirAs fontes utilizadas pelo relatório podem não estar no PATH "reconhecido" pela aplicação. Isto também é um problema comum em se tratando do Jasper. Muitas vezes o iReport traz consigo as fontes e ao testar com ele o relatório é exibido corretamente, mas ao executar pela aplicação as informações não são exibidas, trazendo consigo páginas "vazias", mas neste caso apenas renderizada incorretamente.
ResponderExcluirEduardo, não creio que seja esse o problema pois estou utilizando esse seu exemplo para testar.
ResponderExcluirCharly, também acredito que seja algo errado com a renderização, pois o cabeçalho do relatório é exibido corretamente, apenas o detalhe não aparece.
Como você está lendo o XML de exemplo? Ou seja, qual o path do arquivo é informado?
ResponderExcluirKelson o código é esse:
ResponderExcluirpublic static void main(String[] args) throws Exception {
try{
String relatorio = "C:/Teste/report2.jasper";
JRXmlDataSource xml =
new JRXmlDataSource("C:/Teste/boletim.xml","/boletim/disciplinas/disciplina");
JasperPrint jp = JasperFillManager.fillReport(relatorio, new HashMap(),xml);
JasperViewer.viewReport(jp,false);
} catch (Exception e) {
e.printStackTrace();
}
}
Tentou assim?
ResponderExcluirJRXmlDataSource xml =
new JRXmlDataSource("C:/Teste/boletim.xml","/BOLETIM/DISCIPLINAS/DISCIPLINA");
Ou seja, tudo maiúsculo!?!?!?
Tentei, nesse caso dá mensagem de que o documento não possui página.
ResponderExcluirBem, se alterando o DS você obtém uma mensagem que não possui páginas, posso supor que ao gerar o relatório você obtém as páginas, mas com os registros "vazios", certo?
ResponderExcluirSe for, muito provavelmente é problema com renderização das fontes mesmo, e neste caso, altere as fontes via iReports para uma outra fonte, bem comum, "Sans" por exemplo, e teste a aplicação novamente.
Ainda, qual a versão de SO, iReports e SDK você está utilizando?
Charly, to usando exatamente a fonte "Sans". Quanto a configuração: SO= XP, iReport= 3.6.0 e SDK= 1.6
ResponderExcluirNa versão 3.6.1 do JR foi adicionada a exceção JRFontNotFoundException que não existia anteriormente, e como os autores colocaram, muitos problemas de renderização eram provocados por a fonte utilizada não estar disponível pra JVM ativa. Minha sugestão, para que possa corrigir, ou descartar a hipótese do problema de fonte, altere a fonte para a fonte utilizada nos cabeçalhos... Eu já tive problemas onde eu utilizava a mesma fonte mas parte era renderizada e outra não... eu apenas alterei a fonte... o Jasper tem dessas "idiossincrasias"... rsss
ResponderExcluirEu iria comentar que outro problema que poderia ocorrer é você está utilizando a classe Integer para os atributos mas estar vindo valores não inteiros, mas como você falou que no iReports a informação é exibida, não cabe.
Charly, nas propriedades dos fields existe os campos "Font name" e "Pdf font name" todos estão com os valores SansSerif e Courier respectivamente, alterei os valores pra diversas fontes e mesmo assim o problema continua.
ResponderExcluirTestei colocar um dos fields do cabeçalho no detalhe e ele também não foi exibido.
Pessoal, descobri o problema. O iReport 3.6.0 usa jasperreports-3.5.2 e meu projeto estava com o jasperreports-3.0.0.
ResponderExcluirFoi só substituir e adicionar o commons-digester-1.7 pra tudo funcionar. Obrigado ae pela ajuda.
Muito obrigado pelas dicas, para mim estar muito bom.
ResponderExcluirEstava procurando ha muito tempo, finalmente consegui preparar meu relatorio.