4 de junho de 2011

JasperReports 4.0.1: Agrupando dados

Na postagem de hoje vamos agrupar os pedidos por cliente, assim:


Para este exemplo eu vou utilizar o JPA (visto em postagens anteriores), em um projeto Desktop, só para ser mais rápido, o foco da postagem será o agrupamento então para outros detalhes colocarei apenas os links com exemplos.

Banco de dados
Antes de começar vamos ver qual será as tabelas utilizadas no banco de dados:


Criando o projeto..
Inicialmente vamos no NetBeans criar um novo Aplicativo Java(Desktop) com o nome de Pedidos. Dentro do pacote pedidos(criado por padrão) crie um pacote com o nome de model, ficando assim: pedidos.model, as classes do model serão criadas pelo JPA, ou seja serão geradas a partir do banco, caso não saiba como fazer, veja aqui. Quando geradas o projeto ficará com essa estrutura:

Por eu estar utilizando o MySQL preciso incluir a biblioteca do mesmo dentro do projeto... então em Bibliotecas adicione a biblioteca MySQL JDBC Driver que já tem no NetBeans, caso contrário é facilmente encontrado na Internet.

Novamente dentro do pacote pedidos, crie um novo pacote com o nome de dao, ficando como: pedidos.dao, e dentro dele crie uma nova classe Java com o nome de PedidoDAO.java:
public class PedidoDAO {

    EntityManagerFactory emf = Persistence.createEntityManagerFactory("PedidosPU");
    EntityManager em = emf.createEntityManager();

    public List<Pedido> listarPedidos() {
        List<Pedido> pedidos = null;
        try {
            Query query = em.createQuery(
                    "Select p from Pedido p order by p.cliente.nome");
            pedidos = query.getResultList();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            em.close();
        }
        return pedidos;
    }
}
OBS: ao criar o EntityManagerFactory veja que passo por parâmetro  a String PedidosPU, este valor é  o nome da Persistence Unit, que é encontrado no persistence.xml, por isso confirme se é este o nome que aparece no seu persistence.
Outro detalhe é quanto a consulta... essa parte é de extrema importância: para eu poder agrupar os dados, eu preciso mandar as informações ordenadas de acordo pelo o que eu quero agrupar, neste caso eu quero agrupar por cliente, então dou um order by pelo nome do cliente.
Até agora esse é o nosso projeto:


Depois de ter feito isso, no NetBeans clique em Limpar e Construir, para que ele gere o nosso .jar
Agora vamos dar uma pausa no projeto e vamos criar nosso .jasper...

No iReport
Como vamos utilizar o datasource do tipo JavaBean datasource, aconselho ver esta postagem antes de continuar, caso contrário não será possível entender o que está sendo feito.
No iReport aberto, crie um novo relatório do tipo Blank A4, para mais informações de como criar um relatório veja aqui, e coloque o nome do mesmo como pedidos... depois de criado, nas propriedades do report troque a Language para Java:


Agora antes de continuar, lembre-se de setar no classpath do iReport (ver na postagem sobre JavaBean datasource) o .jar criado do projeto acima...Depois de feito isso, vamos deixar no nosso relatório apenas as seguintes bands: Title, Column Header e Detail 1, quanto as outras pode removê-las, ficando assim:


Agora vamos pegar os fields que vamos precisar para fazer o relatório... então em Report Query vamos selecionar os atributos da classe Pedido... para isso, faça como na imagem abaixo:


No Report Inspector, confirme se os fields foram criados, caso sim, ainda no Report Inspector, na raiz (pedidos) clique com o botão direito e vá em Add report group, coloque o nome de pedido:


Ao clicar em próximo, aparece a seguinte tela, onde pode deixar marcado apenas a opção de Add the group header, pois o group footer não iremos utilizar, e por fim clique em Finalizar:


O nosso relatório passa a ter as seguintes bands:


Agora vamos estruturar nosso relatório, deixando-o assim (abaixo da imagem digo o que tem em cada band), aconselho clicar na imagem para ampliar e ver corretamente as bands:


Primeiramente na band Title, foi colocado apenas um static text como título do relatório. Logo abaixo no Column Header, tem mais um static text informando o "Nome do Cliente"... agora no pedido Group Header 1  que é onde a coisa acontece eu coloquei um text field com o field que pega o nome do cliente, e ainda na mesma band, logo abaixo do text field eu adicionei dois static text: um para código e outro para o valor do pedido. Por fim na band Detail 1, é colocado dois text fields referentes ao código e ao valor (lembrar de alterar os expression class dos text fields de acordo com o tipo dos fields)
Feito tudo isso vamos compilar o nosso relatório para gerar o .jasper (no botão que parece um martelinho) caso não dê nenhum problema podemos continuar no projeto agora.

Voltando ao projeto...
Novamente no pacote pedidos vamos criar agora nosso pacote controle, ficando assim: pedidos.controle e dentro dele crie uma classe Java com o nome de PedidoControle.java, antes de fazermos a codificação dela, vamos dentro do pacote controle, criar um pacote relatorios onde iremos armazenar nosso .jasper, ficando dessa forma: pedidos.controle.relatorios e dentro dele jogue o .jasper gerado ao compilar o relatório:

Antes que esqueçamos, precisamos jogar as bibliotecas do JasperReports dentro do projeto, caso não as tenha ainda, pode consegui-las nesta postagem. Agora sim vamos editar a classe PedidoControle:
public class PedidoControle {

    private PedidoDAO pedidoDAO;

    private void gerarRelatorioDesktop(JRDataSource jrds, Map<Object, Object> parametros, String arquivo) {
        try {
            JasperPrint print = JasperFillManager.fillReport(arquivo, parametros, jrds);
            JasperViewer.viewReport(print, false);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void gerarRelatorio() {
        String arquivo = "src/pedidos/controle/relatorios/pedidos.jasper";

        pedidoDAO = new PedidoDAO();

        JRDataSource jrds = new JRBeanCollectionDataSource(pedidoDAO.listarPedidos());
        gerarRelatorioDesktop(jrds, null, arquivo);
    }
}

Como já foi visto em outras postagens não irei explicar novamente o que acontece neste código.
Para finalizar, vamos chamar nosso método gerarRelatorio() na classe Main.java:
public class Main {

    public static void main(String[] args) {
        PedidoControle controle = new PedidoControle();
        controle.gerarRelatorio();
    }
}

Bom... ao executar o projeto, se tudo ocorrer bem, abrirá a janela no JasperViewer, o resultado será:


E por aqui ficamos com mais uma postagem sobre JasperReports... =)

10 comentários:

  1. Andii, seus códigos sempre me dão uma mega ajuda! vlw pela postagem! me salvou mais uma vez! =D

    ResponderExcluir
  2. Exatamente o que eu precisava. Valeu!

    ResponderExcluir
  3. Boa noite Anddi Brunetta, ja conseguiu fazer a janela do JasperViewer abrir no lado do cliente?
    Minha aplicação esta em um servidor, quando acesso a aplicação através de outra maquina e clico no botão para gerar o relatório, a janela do JasperViewer abre no Servidor e não na maquina do cliente que realizou a requisição, teria um exemplo para me ajudar?

    ResponderExcluir
  4. Excelente! Era justamente isso que eu estava precisando.

    ResponderExcluir
  5. Olá Anddi, Você passa a lista para os relatórios, mas onde é configurada o recebimento desta lista no Ireport e como chamar um item da lista nos fields?

    ResponderExcluir
    Respostas
    1. Olá! Antes de continuar aconselho a dar uma lida nessa postagem aqui: http://javasemcafe.blogspot.com.br/2011/05/jasperreports-401-utilizando-javabean.html e depois voltar na postagem atual e continuar no "No IReport"

      Excluir
    2. Olá Andii, obrigado por responder minha pergunta. Eu já tinha lido esta postagem e nela você explica como criar os fields através de um jar de beans. A minha dúvida é como é recebida a lista de dados pelo Ireport que no exemplo é : pedidoDAO.listarPedidos() e como acessar os dados desta lista no fields?

      Excluir
  6. Parabéns pela postagem, simples e muito eficiente, me salvou hoje

    ResponderExcluir

Deixe seu comentário... ;)