sexta-feira, 20 de dezembro de 2013

Jasper Reports para os impacientes

Vão te pedir um relatório, meu jovem. Vão te pedir. E é bom você sair do zero. Vem comigo,

eu vou assumir que você já descolou um eclipse novinho, desses que usa maven como se fosse uma coisa boa. Nevermind. E que o java já é o 7.

Se não for, bom, você adapta o que precisar. Ou fale com um adulto.

Comece abrindo o eclipse e criando um projeto maven:
E não se preocupe com a seleção de arquétipo:
Para o groupid e artifactid forneça, respectivamente, sample e samplereport. Se você quer saber o que você acabou de fazer, leia isto.
Dê finish e pronto, um lindo projeto maven. Beleza né? A estrutura do projeto deve ser a mostrada abaixo. Abra o pom.xml:
E agora vem o lado bonito do maven: antigamente, meu caro, você precisava saber qual jar baixar e quais as dependências dele. Versões exatas às vezes. Mas hoje: escreva jasper maven 5.5 no google e entre no primeiro resultado. você vai achar um trecho de xml parecido com este:
<dependency>
  <groupId>net.sf.jasperreports</groupId>
  <artifactId>jasperreports</artifactId>
  <version>5.5.0</version>
</dependency>

Daí cole no seu pom.xml, de modo que fique parecido com o da foto abaixo:
Instantes depois o build automático do eclipse vai facilitar a sua vida baixando (quase, como veremos a seguir) todas as dependências importantes do jasper:
E agora toca programar!
Vamos fazer um pequeno relatório com os nossos contatos. Eles tem id, nome e foto:
A classe segue:
package sample;

import java.awt.Image;

public class Contact {

 private int id;
 private String name;
 private Image photo;

 public int getId() {
  return id;
 }

 public void setId(int id) {
  this.id = id;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public Image getPhoto() {
  return photo;
 }

 public void setPhoto(Image photo) {
  this.photo = photo;
 }

}

Após isso, podemos criar a classe com o exemplo de código de como produzir o relatório do modo mais simples possível:
Aí pode acontecer de o projeto te alertar para este erro, mas o seu java é o 7, a correção aparece no hint:
Segue a classe:
package sample;

import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.imageio.ImageIO;

import net.sf.jasperreports.engine.JRDataSource;
import net.sf.jasperreports.engine.JasperRunManager;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;

public class SampleReport {

 public SampleReport() throws Exception {
  List contacts = new ArrayList();
  int i = 10;
  while (i-- > 0) {
   Contact c = new Contact();
   c.setId(i);
   c.setName("contact " + i);
   c.setPhoto(ImageIO.read(SampleReport.class
     .getResourceAsStream("smile.png")));
   contacts.add(c);
  }

  JRDataSource ds = new JRBeanCollectionDataSource(contacts);

  Map map = new HashMap();

  try(InputStream in = SampleReport.class
    .getResourceAsStream("contacts.jasper")){
   try(OutputStream out = new FileOutputStream("contacts.pdf")){
    JasperRunManager.runReportToPdfStream(in,out, map, ds);
   }
  }
 }

 public static void main(String[] args) throws Exception {
  new SampleReport();
 }

}

Agora abra o seu iReport. Como? não sabe o que é? Bom, comece baixando ele aqui.
Faça a gentileza de, após instalar e abrir o iReport,criar o seguinte relatório no mesmo:
Ele gera um xml (com a famigerada extensão .jrxml) como este:
<?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/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="contacts" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="d2e8d937-c3dd-4bfe-a819-f0d3e061ed2c">
 <property name="ireport.zoom" value="1.0"/>
 <property name="ireport.x" value="0"/>
 <property name="ireport.y" value="0"/>
 <field name="id" class="java.lang.Integer"/>
 <field name="name" class="java.lang.String"/>
 <field name="photo" class="java.awt.Image"/>
 <background>
  <band splitType="Stretch"/>
 </background>
 <title>
  <band height="79" splitType="Stretch"/>
 </title>
 <pageHeader>
  <band height="35" splitType="Stretch"/>
 </pageHeader>
 <columnHeader>
  <band height="61" splitType="Stretch"/>
 </columnHeader>
 <detail>
  <band height="125" splitType="Stretch">
   <textField>
    <reportElement x="0" y="48" width="100" height="20" uuid="d2c201da-1c8a-44b9-be6d-8bd9564d9cc0"/>
    <textFieldExpression><![CDATA[$F{id}]]></textFieldExpression>
   </textField>
   <textField>
    <reportElement x="170" y="48" width="100" height="20" uuid="4826502a-91e8-405b-9897-a3f1e80e128b"/>
    <textFieldExpression><![CDATA[$F{name}]]></textFieldExpression>
   </textField>
   <image>
    <reportElement x="409" y="48" width="76" height="77" uuid="3ecc6235-2c85-4a7f-a0e9-4ba9d81d7874"/>
    <imageExpression><![CDATA[$F{photo}]]></imageExpression>
   </image>
  </band>
 </detail>
 <columnFooter>
  <band height="45" splitType="Stretch"/>
 </columnFooter>
 <pageFooter>
  <band height="54" splitType="Stretch"/>
 </pageFooter>
 <summary>
  <band height="42" splitType="Stretch"/>
 </summary>
</jasperReport>

E então aperte o botão compilar:
Volte para o eclipse, lá você deve atualizar o pacote de resources:
Desse modo o arquivo .jrxml e o .jasper serão visíveis:
Feito isso, podemos executar a classe de teste! Entretanto...
... tem essa dependência não resolvida automaticamente. Adicione-a:
Seu pom.xml deve ficar assim:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>sample</groupId>
 <artifactId>samplereport</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <dependencies>
  <dependency>
   <groupId>net.sf.jasperreports</groupId>
   <artifactId>jasperreports</artifactId>
   <version>5.5.0</version>
  </dependency>
  <dependency>
   <groupId>javax.servlet</groupId>
   <artifactId>javax.servlet-api</artifactId>
   <version>3.1.0</version>
  </dependency>
 </dependencies>
</project>

E agora expere o build automático terminar e execute novamente. Vai dar certo. Oh wait!

 Bom, o jasper usa como linguagem padrão o groovy, um primo do java. Você pode resolver isso adicionando a enorme dependência do groovy ao seu projeto ou mudando a linguagem padrão do relatório para java:
E não esqueça de compilar:
Atualize o pacote no eclipse, e execute novamente:
A saída deverá ser a seguinte:
Mas... e aí? o que aconteceu? Proceda com o velho refresh no projeto:
Um arquivo .pdf surgirá:
Abra com o editor do sistema:
E daí surgirá o resultado:
Simples assim.

O que? Não, não me esforçei em nada pra fazer um leiaute bonito. Deixo esta raiva pra você.
A imagem você acha sozinho na internet, você é capaz, tenha fé.

O trecho de código que gera o relatório faz uso de streams porque deste modo você pode construir o seu de forma mais flexível.

Muita gente deixa os resources fora do classpath, mas eu te recomendo a manter eles por perto... até na hora de escrever testes a coisa fica transparente. Seja web ou desktop seus relatórios em teoria poderão ser testados e gerados sem maiores desafios.

Sem mais para o momento amigos. Bom trabalho a todos!

UPDATE:

Caso seu relatório seja muito grande, em vez de
java.awt.Image 

use
java.io.InputStream

Nenhum comentário :

Postar um comentário