segunda-feira, 11 de abril de 2011

Compilação de dicas Ireport

           Ultimamente venho trabalhando muito com relatórios feitos no Ireport (até mais do que eu gostaria) e como sei que é difícil conseguir boas dicas, resolvi fazer uma compilação de dicas aqui para quem passa por alguns “perrengues” com essa ferramenta.

  Passar uma lista como datasource de um subrelatorio

            Deve-se usar essa expressão no datasourceconection do subrelatorio new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{Lista}) 
           O field Lista é a lista de objetos que deseja que seja passado para o relatório.
           No subrelatorio se quizer pegar os atributos do objeto da lista é so declara-los como Field que o jasper vai fazer o papel de mapea-los para você.




         Na imagem acima tenho o meu field $F{servicos}  que é do tipo List

Não passar nenhum dado para o Subrelatorio e mesmo assim fazer com que ele abra


          Basta usar a seguinte expressão  new JREmptyDataSource(), com isso o relatório ira abrir sem precisar de  valor algum.


 Criar uma expressão para se verdadeira imprimir o relatório ou campo do relatório

          Se quiser que o relatório ou algum campo dele só imprima de acordo com alguma condição    basta colocar um teste booleano na propriedade print when expression                                                         
               Ex:  new Boolean($V{campoDouble}.doubleValue()>0) Nesse exemplo só sera impresso se o campo for maior que zero. A imagem abaixo ilustra esse exemplo:




  Passando um Mapa como parâmetro

         Declara-se um Field  do tipo Map 
         Ex: org.apache.commons.collections.map.HashedMap 
         Nesse exemplo usei HashedMap, mas poderia ter sido usado qualquer outro tipo de   mapa,no relatório que ira receber o Mapa como parâmetro será preciso declarar uma variável, seta-se o variable class com o caminho da classe que está sendo salva no mapa 
         Ex: com.meuprojeto.to.MinhaClasseTO 
         No variable expression coloca-se a chave que irá pegar o valor do mapa.
           
        Ex:$P{meuMap}.get($F{valorDaChaveMapa}), depois no Field do relatório é so pegar o valor assim: $V{minhaVariavel}.geMeuAtributo()


Passando uma lista de Strings para o subrelatorio


        Se quiser passar uma lista de Strings para um subrelatorio e recuperar os valores deverá declarar o field com a expressão $F{_THIS},  com isso conseguira recuperar os valores da lista.


 Criando um texto  que precise conter uma palavra em negrito no meio


         Se precisar inserir uma palavra em negrito no meio de um texto, como feito nessa frase, basta setar o Markup como styled e  usar a tag <style isBold="true"> No texto Negrito </style> como na imagem abaixo:

21 comentários:

  1. Tiago, muito bom o post

    No meu caso preciso passar um List por parâmetro para o ireport, lista essa que será usada em um subreport.

    No ireport eu crio um novo parâmetro no master do tipo collection e nomeio com o mesmo nome passado no map.

    Em seguida crio um subreport e dou um new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource((java.util.List)$P{lista}) no data source expression.

    Agora como faço para pegar os valores dessa lista????

    Desde já agradeço
    Alexandre

    ResponderExcluir
  2. Por que você precisa passar por parâmetro? não declara um tipo List no seu Bean?? ai você declara um field no seu relatório master e passa como dataSource para o subrelatório.

    No subrelatorio você declara os fields dos atributos contidos no Objeto da sua Lista

    ResponderExcluir
  3. Boa tarde amigo, parabéns pelo post, gostaria de pedir uma ajuda para criar um subrelatorio, estou recebendo o seguinte erro na compilação:
    Error retrieving field value from bean : valores

    Se puder ajudar.
    Abrass

    ResponderExcluir
  4. Olá Siri, sabe dizer se os fields que você declarou no subrelatorio existem mesmo na coleção passada para ele como datasource? outro ponto a ser verificado é se os tipos dos fields estão idênticos aos do bean. se não me engano esse "valores" é um field do seu bean investiga ele.

    ResponderExcluir
  5. Boa tarde!

    Cara, você sabe como acessar um método de uma lista que é passado num data source?
    Por exemplo, eu tenho um objeto A com uma lista L com objetos B.

    Tentei algo assim mas o retorno do get é um Object, então ele não encontra o método. Teria que fazer um cast, ou algo do tipo.
    $F{lista}.get($V{indice}).metodo();

    Valeu

    ResponderExcluir
  6. Consegui fazer assim, um cast no braço mesmo,

    ((entidade.Cenario)$F{listaCenario}.get($V{PAGE_NUMBER})).getDescricao()

    Mas não achei muito elegante.. existe uma forma mais correta?

    ResponderExcluir
  7. Boa Tarde Tiago.

    Eu tenho um relatório que contém um subrelatório. Neste subrelatório eu tenho um outro subrelatório, então o meu problema é que neste último relatório só imprime o primeiro elemento da lista duplicado duas vezes em vez de imprimir os dois elementos. Você pode me ajudar sobre o que está acontecendo? Todos os subrelatórios apresentam os dados no campo DETAIL.

    ResponderExcluir
  8. Anônimo,
    A lista você está passando pelo datasource tem um "Objeto" com X metodos e você quer acessar os metodos desse objeto é isso? se for tenta declarar no subrelatorio o field do tipo do teu objeto.
    Ex: teu objeto é Pessoa então no tipo do field você declara como sendo do tipo br.com.bean.Pessoa
    Você declara o caminho todo do pacote até a classe e quando tiver em alguma banda no relatório vc faz o seguinte para acessar $F{pessoa}.metodo()
    Se não me engano isso resolve, testa ai e me da uma resposta amanhã no trabalho confiro se assim dá certo.

    ResponderExcluir
  9. Oi Vando,
    me responde uma coisa a lista você está passando como datasource tanto para o ultimo como para o penúltimo subrelatorio? se sim ela imprime no penúltimo corretamente e no ultimo aparece esse problema relatado? de qualquer maneira verifica se no field do ultimo relatorio está checado a propriedade print repeated values.

    ResponderExcluir
  10. Sim, Tiago, no penúltimo ele imprime os dados corretamente, mas no último ele faz isso. Imprime o primeiro elemento duas vezes...

    Vou tentar fazer o que você falou.

    obrigado.

    ResponderExcluir
  11. Me ajudou bastante.
    Já estava a 1 semana preso no subrelatorio.
    Ótimo post, parabens.

    Abraço.

    ResponderExcluir
    Respostas
    1. Fico feliz por saber que post foi útil Douglas, obrigado pelo feedback.
      Abraço.

      Excluir
  12. Boas dicas Tiago, vamos ver se pode ajudar-me...
    Preciso gerar um relatório de uma lista de clientes, para isso tenho a entidade Clientes, com nome, telefone, ambos String, e um objeto Endereco(refere-se a outra entidade), nesta outra entidade Endereco, tenho um objeto Cidade(refere-se a entidade Cidade), aí sim nesta entidade tenho o nome(String) da cidade, não estou conseguindo pegar este nome da cidade, estou tentando por sub-relatórios assim:
    Cliente(Master)->Endereco(sub de Cliente)->Cidade(sub de Endereco), configurei certinho a expressão do datasource connection de cada um, mas da erro que não acha o Field.
    Utilizo o ireport 4.5.1 e JavaBean DataSource.

    Desde já Obrigado....

    Abs.

    ResponderExcluir
    Respostas
    1. Oi William,
      Cara tem certeza que o objeto Cidade tem um getNome() e está declarado do mesmo tipo do field do relatório?
      Qualquer coisa você poderia fazer esse teste cria o relatório master(clientes) e um subrelatorio para endereços onde poderia estanciar um dataSource vazio "new JREmptyDataSource()" e passar para eles parâmetros com os valores que precisa Ex: $F{cliente.endereco.cidade.nome} ai no subrelatorio vc recebe isso como parâmetro e coloca em um field.

      qualquer coisa posta o erro que está dando.

      abraço

      Excluir
  13. Muchas gracias por el post, podrias ayudarme con mi error?

    13/11/2012 11:33:44 net.sf.jasperreports.engine.fill.JRFillSubreport prepare
    GRAVE: Fill 1: exception
    java.lang.NoClassDefFoundError: org/apache/commons/beanutils/PropertyUtils
    at net.sf.jasperreports.engine.data.JRAbstractBeanDataSource.getBeanProperty(JRAbstractBeanDataSource.java:111)
    at net.sf.jasperreports.engine.data.JRAbstractBeanDataSource.getFieldValue(JRAbstractBeanDataSource.java:96)
    at net.sf.jasperreports.engine.data.JRBeanCollectionDataSource.getFieldValue(JRBeanCollectionDataSource.java:100)
    at net.sf.jasperreports.engine.fill.JRFillDataset.setOldValues(JRFillDataset.java:1330)
    at net.sf.jasperreports.engine.fill.JRFillDataset.next(JRFillDataset.java:1231)
    at net.sf.jasperreports.engine.fill.JRFillDataset.next(JRFillDataset.java:1207)
    at net.sf.jasperreports.engine.fill.JRBaseFiller.next(JRBaseFiller.java:1544)
    at net.sf.jasperreports.engine.fill.JRVerticalFiller.fillReport(JRVerticalFiller.java:142)
    at net.sf.jasperreports.engine.fill.JRBaseFiller.fill(JRBaseFiller.java:909)
    at net.sf.jasperreports.engine.fill.JRBaseFiller.fill(JRBaseFiller.java:841)
    at net.sf.jasperreports.engine.fill.JRFillSubreport.fillSubreport(JRFillSubreport.java:656)
    at net.sf.jasperreports.engine.fill.JRSubreportRunnable.run(JRSubreportRunnable.java:59)
    at net.sf.jasperreports.engine.fill.JRThreadSubreportRunner.run(JRThreadSubreportRunner.java:227)
    Mensaje de Error: java.lang.NoClassDefFoundError: org/apache/commons/beanutils/PropertyUtils
    at java.lang.Thread.run(Thread.java:619)
    Caused by: java.lang.ClassNotFoundException: org.apache.commons.beanutils.PropertyUtils
    at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
    ... 14 more

    ResponderExcluir
    Respostas
    1. Creo que algunos campos que se indica en el Jasper no contiene método en su clase en obtenero son con diferentes tipos

      Excluir
  14. Tiago,

    Estou preso com o seguinte cenário:

    Relatório de Contracheques, o Contracheque tem uma lista de EventoSalarial, que é composto por 5 campos String.

    Recebo a lista em meu relatório master como um field, passo como um new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{eventosSalariais}) mas no sub relatório eu não consigo recuperar as informações como um field ou parametro.

    J´[a tentei de tudo um pouco e não funcionou.

    ResponderExcluir
    Respostas
    1. Olá Fabio,

      Desculpe a demora, vamos ver se entendi:
      Você tem um objeto ContraCheque que é passado como o dataSource para o relatório master e nesse ContraCheque você tem uma lista de EventoSalarial que é passado como dataSource para abrir o subReport. Nesse subreport vc declarou os 5 campos Strings como Fields e mesmo assim não imprimiu?
      Estranho se puder me passar mais detalhes por email: tiagocelular1@gmail.com

      Excluir
  15. Tiago,

    Parabéns pela iniciativa e pelo empenho em nos ajudar!
    Meu cenário, é como o do colega acima, trabalho com contracheque porém optei por inserir os eventos em um componente "table". O que ocorre é que eu preciso em um espaço estático, inserir os eventos que são de tamanho dinâmicos, ou seja, que preencha com branco quando nao atingir o limite. E quando ultrapassar o limite, que gere um novo relatorio com os mesmo detalhes e com as linhas restantes . Sera possivel isso ou terei que fazer algo como subGroup??

    Agradeço desde ja.

    ResponderExcluir
    Respostas
    1. Oi Vinicius,

      Primeiro, obrigado pelo elogio. Nunca passei por esse cenário, mas acredito que subgrupo para quebra do relatório seria a melhor maneira mesmo.

      Excluir
  16. Boa tarde. Tiago vamos ver se você pode me ajudar.
    Tenho um relatório com o iReport, ele esta rodando perfeitamente, exceto que o meu field do subRelatório não imprimi o primeiro item da lista, no PDF aparece a partir do segundo item. Como faço para ajustar isto ele imprimir desde o primeiro item.

    ResponderExcluir