Issuu on Google+

Grupo de Usuários Java http://www.guj.com.br

Relatório no Ireport com dois níveis de expansão, utilizando Grupos e Subrelatório com ArrayList Álvaro Freitas Amorim Neto Este tutorial visa demonstrar a criação de relatório no Ireport, utilizando uma primeira expansão (sub-lista de dados) por grupo e uma segunda expansão com subrelatório.

Entendendo a Estruturação dos Dados do Relatório Primeiramente deve-se entender a necessidade das duas expansões no relatório e sua estrutura de dados. Considere três tabelas no banco de dados (Rua, Casa, Morador). Levando-se em consideração que deve ser emitida uma correspondência que liste para cada rua seu nome e código, as casas que se encontram nela e os moradores de cada casa, e considerando também que uma rua possui 1 ou mais casas, e que cada casa possui 1 ou mais moradores, segue a estrutura adotada:

Classe Rua.java public class Rua { private String nomeRua; private String codRua; public Rua(String nomeRua, String codRua) { this.nomeRua = nomeRua; this.codRua = codRua; } //Getters and Setter omitidos...

Classe Casa.java public class Casa { private private private private private

String String String String String

codCasa; codRua; nomeCasa; corCasa; valorCasa;

public Casa(String codCasa, String codRua, String nomeCasa, String corCasa, String valorCasa) { this.codCasa = codCasa; this.codRua = codRua; this.nomeCasa = nomeCasa; this.corCasa = corCasa; this.valorCasa =valorCasa; } //Getters and Setter omitidos...

Classe Morador.java public class Morador { private String codCasa; private String nomeMorador; private String profissaoMorador; public Morador(String codCasa, String nomeMorador, String profissaoMorador) { this.codCasa = codCasa; this.nomeMorador = nomeMorador; this.profissaoMorador = profissaoMorador; } //Getters and Setter omitidos...

Grupo de Usuários Java – http://www.guj.com.br – Página 1


Grupo de Usuários Java http://www.guj.com.br

A estrutura de classes adotada é apenas fictícia. Foram criados dados para as três classes citadas acima respeitando os “relacionamentos”, como se tais dados tivesse sido obtidos via consulta nas tabelas, e o List a ser passado para o Ireport também foi preenchido respeitando tais relacionamentos.

Dados Compostos Para Relatório Para a simulação foram criadas quatro ruas, para tais ruas foram cridas casas e para as casas moradores. Os dados no Ireport serão agrupados por codRua. Como os moradores são agrupados por casa, é passado um parâmetro ArrayList (moradores) no objeto representando o conjunto de moradores de determinada casa. Sendo assim cada casa já será passada ao Ireport com seus devidos moradores. Esta estrutura facilita bastante a utilização de subrelatório.

Classe ComposicaoDadosParaRelatorio.java public class ComposicaoDadosParaRelatorio { private private private private private private

String codRua; String nomeRua; String nomeCasa; String corCasa; String valorCasa; ArrayList moradores;

public ComposicaoDadosParaRelatorio(String codRua, String nomeRua, String nomeCasa,String corCasa, String valorCasa, ArrayList moradores) { super(); this.codRua = codRua; this.nomeRua = nomeRua; this.nomeCasa = nomeCasa; this.corCasa = corCasa; this.valorCasa = valorCasa; this.moradores = moradores; } //Getters and Setter omitidos...

Montagem do Modelo no Ireport Agora será iniciada a elaboração do modelo no Ireport. Como os dados serão passados via ArrayList, não será necessária a configuração de nenhuma conexão ao banco dentro do Ireport Você observará também que os códigos específicos para chamar o relatório serão mínimos. Primeiramente será desenvolvido o modelo principal e posteriormente o do subrelatório. No relatório principal, deverão ser criados os campos para os atributos codRua, nomeRua, nomeCasa, corCasa, valorCasa e moradores (veja a classe ComposicaoDadosParaRelatorio). Observe na figura abaixo (parte destacada em vermelho) que “moradores” é do tipo Object, uma vez que é um ArrayList. Este Object é que será passado ao subrelatório. Mais adiante será descrito com mais detalhes.

Grupo de Usuários Java – http://www.guj.com.br – Página 2


Grupo de Usuários Java http://www.guj.com.br

Criação de Fields

Após a criação destes fields, deve-se colocá-los na página, nas posições desejadas. Vale lembrar que como os atributos nomeCasa, corCasa e valorCasa serão agrupados pelo código da rua, estes devem ser colocados na faixa detail. Também deve ser colocado nessa faixa o subreport. Você verá na próxima imagem o ícone para a criação do subrelatório, bem como a tela onde a configuração do grupo foi feita:

Observe que foram feitos três círculos vermelhos na imagem. O primeiro círculo, próximo ao “F” é o ícone para criação de subrelatório, o segundo círculo se refere à configuração de grupos, no caso o atributo codRua (Casa será agrupada por tal grupo). A opção “Start on a new page” foi selecionada, fazendo com que os dados de cada rua fossem gerados numa página nova. Grupo de Usuários Java – http://www.guj.com.br – Página 3


Grupo de Usuários Java http://www.guj.com.br

Como esta parte de colocação dos componentes é bastante intuitiva, serão exibidas as telas dos dois modelos criados, o que está sendo discutido e o do subrelatório. A próxima tela a ser explicada com mais detalhes será a do subrelatório, que é um pouco mais trabalhosa. Após inserir o componente do subrelatório e abrir as propriedades dele, observa-se as abas “Common”, “Subreport”, “Subreport(Other)” e “All”. Para o funcionamento do subrelatório de exemplo só será necessária a configuração nas abas “Subreport” e “Subreport(Other)”. Na primeira devemos informar que a fonte de dados do subrelatório é o ArrayList passado (moradores). Como o ArrayList foi passado como Object (descrito anteriormente) é necessário fazer um "cast" para obter ele novamente. Juntamente com tal "cast", deve-se instanciar um JRBeanArrayDataSource, para que este atenda ao subrelatório. Tal operação é muito simples. Para tal, na aba “Subreport” deve-se escolher a opção “use datasource expression” e deve-se colocar a linha de código conforme figura abaixo:

Na aba “Subreport(Other)” você deve colocar o parâmetro que irá informar onde o jasper compilado do subrelatório estará. Para tal deve-se criar o parâmetro pathSubRel conforme figura abaixo:

Grupo de Usuários Java – http://www.guj.com.br – Página 4


Grupo de Usuários Java http://www.guj.com.br

Feito essas etapas o seu modelo estará praticamente pronto. Para maiores detalhes verifique o fonte que certamente ficará fácil entender. Lembre-se que ao criar um Field, deve-se colocar a expressão da seguinte forma $F{atributo} e para criar parâmetro deve ser $P{parâmetro}. O modelo completo e com os fields em seus devidos lugares fica assim:

Alguns textos estáticos foram inseridos apenas por motivos de layout e apresentação. O modelo do subrelatório fica assim:

Este modelo tem apenas dois campos: nomeMorador, profissaoMorador. Para um maior entendimento vamos agora entender como os parâmetros e o List são passados. Neste modelo foram passados dois parâmetros, o pathSubRel e o imagem. O primeiro indica o caminho do subrelatório, e o segundo indica o caminho do logotipo que virá na carta. Observe o código: try{ ArrayList saida = new ArrayList(); saida.add(c1); saida.add(c2); saida.add(c3); saida.add(c4); saida.add(c5); saida.add(c6); saida.add(c7); saida.add(c8); Grupo de Usuários Java – http://www.guj.com.br – Página 5


Grupo de Usuários Java http://www.guj.com.br

saida.add(c9); saida.add(c10); HashMap hs = new HashMap(); hs.put("pathSubRel","C:\\modelo_subrelatorio_1.jasper"); hs.put("imagem","C:\\imagem.GIF"); JRDataSource jrds = new JRBeanArrayDataSource(saida.toArray()); JasperPrint prt = JasperFillManager.fillReport("C:\\modelo_rel_1.jasper", hs, jrds); JasperViewer jrviewer = new JasperViewer(prt,false); jrviewer.show(); }catch(Exception e){ e.printStackTrace();}

No código acima, o ArrayList “saída” já recebe objetos no formato da classe ComposicaoDadosParaRelatorio. Sendo assim, um JRBeanArrayDataSource recebe este ArrayList (lembre-se que esta operação já foi realizada para passar o ArryList moradores para o subrelatório). Observe que os parâmetros pathSubRel e imagem passados no HashMap hs com os caminhos do respectivamente.

também são inicializados e subrelatório e da imagem

Enfim o resultado obtido:

Grupo de Usuários Java – http://www.guj.com.br – Página 6


Grupo de Usuários Java http://www.guj.com.br

Prevenção de Erros Normalmente problemas de Classpath são encontrados ao desenvolver um modelo jasper com mais recursos. Para evitar tais problemas, deve-se adicionar ao projeto alguns jars que acompanham o Ireport. Tais arquivos se encontram dentro da pasta de instalação do Ireport, no subdiretório \lib. No exemplo mostrado neste tutorial foi necessária a adição dos jars mostrados na figura abaixo (foi utilizada o Eclipse para desenvolver o exemplo).

Dados Fictícios Como dito anteriormente, os dados foram inseridos em código apenas para demonstrar o funcionamento do agrupamento e do subrelatório. Para evitar que dúvidas surjam quanto a qualquer parte do código esta classe também será citada como sugestão. Lembre-se que o correto é você preencher os dados através de consulta, e não preenchê-los de forma manual como foi descrito aqui.

Classe Principal import java.util.ArrayList; import java.util.HashMap; import import import import import

net.sf.jasperreports.engine.JRDataSource; net.sf.jasperreports.engine.JasperFillManager; net.sf.jasperreports.engine.JasperPrint; net.sf.jasperreports.engine.data.JRBeanArrayDataSource; net.sf.jasperreports.view.JasperViewer;

public class Principal { public static void main(String[] args) { //Cadastramento dados utilizados //Cadastrando algumas ruas Rua a = new Rua("Rua Belo Horizonte", "1"); Rua b = new Rua("Rua São Paulo", "2"); Rua c = new Rua("Rua Curitiba", "3"); Rua d = new Rua("Rua Espirito Santo", "4"); //Cadastrando Casa ca = new Casa cb = new Casa cc = new Casa cd = new Casa ce = new

algumas casas Casa("A", "1", Casa("B", "1", Casa("C", "1", Casa("D", "2", Casa("E", "2",

"Casa "Casa "Casa "Casa "Casa

1", 2", 3", 4", 5",

"Vermelha", "1000"); "Amarela", "2500"); "Preta", "4444"); "Verde escuro", "1234"); "Prateada", "2333");

Grupo de Usuários Java – http://www.guj.com.br – Página 7


Grupo de Usuários Java http://www.guj.com.br Casa Casa Casa Casa Casa Casa Casa

cf cg ch ci cj ck cl

= = = = = = =

new new new new new new new

Casa("F", Casa("G", Casa("H", Casa("I", Casa("J", Casa("K", Casa("L",

"2", "3", "3", "3", "4", "4", "4",

"Casa "Casa "Casa "Casa "Casa "Casa "Casa

//Cadastrando moradores Morador ma = new Morador("A", Morador mb = new Morador("A", Morador mc = new Morador("A", Morador md = new Morador("A", Morador me = new Morador("C", Morador mf = new Morador("C", Morador mg = new Morador("D", Morador mh = new Morador("D", Morador mi = new Morador("E", Morador mj = new Morador("F", Morador mk = new Morador("G", Morador ml = new Morador("H", Morador mm = new Morador("H", Morador mn = new Morador("I", Morador mo = new Morador("J", Morador mp = new Morador("K",

6", "Marron", "7777"); 7", "Branca", "8876"); 8", "Madeira", "9898"); 9", "Colorida", "2121"); 10", "Cinza claro", "3434"); 11", "Mostarda", "5454"); 12", "Amarelo escuro", "1111");

"Fulano "Fulano "Fulano "Fulano "Fulano "Fulano "Fulano "Fulano "Fulano "Fulano "Fulano "Fulano "Fulano "Fulano "Fulano "Fulano

1 2 3 4 1 2 1 2 1 1 1 1 2 1 1 1

Casa Casa Casa Casa Casa Casa Casa Casa Casa Casa Casa Casa Casa Casa Casa Casa

A", A", A", A", C", C", D", D", E", F", G", H", H", I", J", K",

"Pedreiro"); "Programador"); "Médico"); "Dentista"); "Pedreiro"); "Programador"); "Médico"); "Médico"); "Pedreiro"); "Programador"); "Dentista"); "Pedreiro"); "Programador"); "Pedreiro"); "Dentista"); "Médico");

//ArrayList que armazenará Moradores de cada casa //Isto é ficticio, tais dados deveriam ser buscados via //consulta com Hibernate por exemplo ArrayList moradoresCasaA = new ArrayList(); ArrayList moradoresCasaC = new ArrayList(); ArrayList moradoresCasaD = new ArrayList(); ArrayList moradoresCasaE = new ArrayList(); ArrayList moradoresCasaF = new ArrayList(); ArrayList moradoresCasaG = new ArrayList(); ArrayList moradoresCasaH = new ArrayList(); ArrayList moradoresCasaI = new ArrayList(); ArrayList moradoresCasaJ = new ArrayList(); ArrayList moradoresCasaK = new ArrayList(); moradoresCasaA.add(ma); moradoresCasaA.add(mb); moradoresCasaA.add(mc); moradoresCasaA.add(md); moradoresCasaC.add(me); moradoresCasaC.add(mf); moradoresCasaD.add(mg); moradoresCasaD.add(mh); moradoresCasaE.add(mi); moradoresCasaF.add(mj); moradoresCasaG.add(mk); moradoresCasaH.add(ml); moradoresCasaH.add(mm); moradoresCasaI.add(mn); moradoresCasaJ.add(mo); moradoresCasaK.add(mp); //Dados rua 1 (Obedecendo a relacionamentos fictícios) ComposicaoDadosParaRelatorio c1 = new ComposicaoDadosParaRelatorio(a .getCodRua(), a.getNomeRua(), ca.getNomeCasa(), ca.getCorCasa(), ca.getValorCasa(), moradoresCasaA); ComposicaoDadosParaRelatorio c2 = new ComposicaoDadosParaRelatorio(a .getCodRua(), a.getNomeRua(), cc.getNomeCasa(), cc.getCorCasa(), cc.getValorCasa(), moradoresCasaC); //Dados rua 2 (Obedecendo relacionamentos fictícios) ComposicaoDadosParaRelatorio c3 = new ComposicaoDadosParaRelatorio(b .getCodRua(), b.getNomeRua(), cd.getNomeCasa(), cd.getCorCasa(), cd.getValorCasa(), moradoresCasaD); ComposicaoDadosParaRelatorio c4 = new ComposicaoDadosParaRelatorio(b .getCodRua(), b.getNomeRua(), ce.getNomeCasa(), ce.getCorCasa(), ce.getValorCasa(), moradoresCasaE); ComposicaoDadosParaRelatorio c5 = new ComposicaoDadosParaRelatorio(b .getCodRua(), b.getNomeRua(), cf.getNomeCasa(), cf.getCorCasa(), cf.getValorCasa(), moradoresCasaF); //Dados rua 3 (Obedecendo relacionamentos fictícios) ComposicaoDadosParaRelatorio c6 = new ComposicaoDadosParaRelatorio(c Grupo de Usuários Java – http://www.guj.com.br – Página 8


Grupo de Usuários Java http://www.guj.com.br .getCodRua(), c.getNomeRua(), cg.getNomeCasa(), cg.getCorCasa(), cg.getValorCasa(), moradoresCasaG); ComposicaoDadosParaRelatorio c7 = new ComposicaoDadosParaRelatorio(c .getCodRua(), c.getNomeRua(), ch.getNomeCasa(), ch.getCorCasa(), ch.getValorCasa(), moradoresCasaH); ComposicaoDadosParaRelatorio c8 = new ComposicaoDadosParaRelatorio(c .getCodRua(), c.getNomeRua(), ci.getNomeCasa(), ci.getCorCasa(), ci.getValorCasa(), moradoresCasaI); //Dados rua 4 (Obedecendo relacionamentos fictícios) ComposicaoDadosParaRelatorio c9 = new ComposicaoDadosParaRelatorio(d .getCodRua(), d.getNomeRua(), cj.getNomeCasa(), cj.getCorCasa(), cj.getValorCasa(), moradoresCasaJ); ComposicaoDadosParaRelatorio c10 = new ComposicaoDadosParaRelatorio(d .getCodRua(), d.getNomeRua(), ck.getNomeCasa(), ck.getCorCasa(), ck.getValorCasa(), moradoresCasaK); try { ArrayList saida = new ArrayList(); saida.add(c1); saida.add(c2); saida.add(c3); saida.add(c4); saida.add(c5); saida.add(c6); saida.add(c7); saida.add(c8); saida.add(c9); saida.add(c10); HashMap hs = new HashMap(); hs.put("pathSubRel", "C:\\modelo_subrelatorio_1.jasper"); hs.put("imagem", "C:\\imagem.GIF"); JRDataSource jrds = new JRBeanArrayDataSource(saida.toArray()); JasperPrint prt = JasperFillManager.fillReport( "C:\\modelo_rel_1.jasper", hs, jrds); JasperViewer jrviewer = new JasperViewer(prt, false); jrviewer.show(); } catch (Exception e) { e.printStackTrace(); } } }

Conclusão Observa-se que a técnica de subrelatório do Ireport é de fácil implementação, uma vez que tal framework exige o mínimo de código para relatórios com nível de dificuldade e complexidade medianas. A maior dificuldade é estruturar os dados para passá-los de forma mais simplificada possível de serem agrupados. O exemplo citado neste tutorial é todo preenchido em código, mas respeitando os relacionamentos fictícios. Profissionalmente o Hibernate facilita bastante a passagem de tais dados, uma vez que é possível fazer uma busca que retorne um List já preenchido com os dados desejados.

Álvaro Freitas Amorim Neto (alvaro_fa@yahoo.com.br) é programador Java e trabalha usando as tecnologias Jcompany (http://www.powerlogic.com.br), Hibernate (http://www.hibernate.org/), Struts (http://struts.apache.org/) , etc.

Grupo de Usuários Java – http://www.guj.com.br – Página 9


Ireport Tutorial