Relatório dinâmico com JasperReports

20 respostas
E

Como eu faço para criar um relatório com JasperReports dinâmico, ou seja,
eu criar o xml via código.
O usuário irá escolher os campos que vão aparecer. Eu sei que se eu colocar dois fields e não passar nenhum parâmetro não irá aparecer. Mas eu preciso distribuir estes campos de uma forma que não fiquem espaços em branco no meio do relatório. Para isso que precisaria criar o relatório do zero, ou seja, precisaria criar o xml da forma que eu quiser via código.

Ou se existe algum outro jeito de eu fizer isso, ou alguma outra idéia de como eu posso fazer este relatório de uma forma que os campos fiquem bem distribuídos.

Obrigado

20 Respostas

A

ae pessoal estou precisandu saber isso!! alguem ajuda ae!!!

A

ae pessoal ngm pode me ajudar aki!?!?!?

B

Complicadinho hein cara!!!..
Se fosse só alternar as colunas, diria pra vc colocar colunas bobas no relatorio, tipo COLUNA_1, COLUNA_2… e criando um DataSource, retornar a colunas que o cara selecionou no lugar da COLUNA_1, etc…

Mas mexendo no tamanho…

Até é possível criar o xml na mao, usar o inputstream pra compilar e gerar o relatorio a partir do compilado… mas nunca fiz, só sei em teoria…

Mas ia ser chato ficar posicionando dinamicamente os campos…

mais ideias…

Ou talvez usar uma fonte fixa de tamanho, colocar uma unica linha no report, e na query montar a linha usando LTRIM e RTRIM, colocando espaçoes em branco e talz…

Abraços!

S

Olá, no meu caso eu não precisei montar o relatório porém precisei disponibilizar ao usuário a opção de ajustar a posição dos campos.
Para isso utilizei o JDOM que disponibiliza uma interface pra você mexer no XML como no DOM usando Javascript.
No caso de criar o XML do zero, também é uma boa opção.

vlw.

M

arthurnn e efukuda:vocês já começaram a fazer algo???

meu caso, acho q é um pouco pior…rs…

O que tenho que fazer é um relatório que traga uma síntese de um questionário, onde muitos participantes responderão.
Com isso, preciso de um relatório dinâmico onde o usuário não riá escolher apenas os campos que serão exibidos, poderão escolher tb, a qtde de respostas, o tipo de resultado, etc.
To pensando até que poderá ser exibida alguma banda e outras não.

qual seria a melhor solução?! gerar o código xml do zero sempre?!, utilizar o DOM (não conheço)??, ou ainda existe alguma outra???

obrigado

J

Olá

Bem, antes de tudo você precisa ter claramente o que o seu cliente precisa ver.
Muitas vezes achar uma solução em JasperDesign é preciso "desenhar" seu relatório e ter uma conexão nas situações em que ele ocorre.

Não sei exatamente seu caso, mas acredito que trabalhando com grupos e ScriptLets seja possível fazer tudo o que você precisa.

No entanto, cria o XML na mão via código, é um trabalho braçal. A melhor opção é você ter um relatório seco, com funcionalidades padrão (que estarão sempre no relatório) e a parte dinâmica, que será criada em tempo de execução.
Esta é uma solução mista. Trabalhar com Relatório Dinâmico não é tão simples...(sei bem como é)... estou desenvolvendo um framework para gerar relatório sem XML (http://www.jasperforge.org/sf/projects/jautoreport). Quando ficar pronto, divulgarei a comunidade Java.

Você pode começar a trabalhar com as bandas (sejam elas fixas ou dinâmicas) e trabalhadas via código.

Recuperando uma Banda:
JRDesignGroup grupoCabecalho = (JRDesignGroup) jasperDesign.getGroupsMap().get("group");
ou Criando uma nova:
JRDesignGroup grupoTotal = new JRDesignGroup();
                grupoTotal.setExpression(); // expressão em qual momento ele será exibido. ver JRDesignExpression.
                grupoTotal.setName("groupTotal");
                grupoTotal.setStartNewColumn(true);
                jasperDesign.addGroup(grupoTotal);
               // Adicionando rodapé. lembre-se que nos grupos tem-se cabeçalho e rodapé.
                grupoTotalBand = new JRDesignBand();
                grupoTotalBand.setSplitAllowed(true);
                grupoTotalBand.setHeight(20);
                grupoTotal.setGroupFooter(grupoTotalBand);

                jasperDesign.addGroup(detalhamentoBand);

Note que a referência jasperDesign faz referência ao objeto JasperDesign, que pode ser criado via loading de algum XML ou inteiramente na mão.

Depois de criar os grupos, você pode pegar a referência de cada um, ou recuperá-las via Map através do nome, e usar objetos JRDesignTextField para criar os campos dinamicamente. Quando o objeto for criado, você os adiciona na referência de seu grupo.

Bom, tentei ajudar da forma que entendi seu problema. Se não ficou claro, retorne e assim que puder ajudo.

Att.

J

Correção: Troque a palavra banda por grupo. :smiley:

As bandas são mais fáceis.

M

jonataswingeter:
No entanto, cria o XML na mão via código, é um trabalho braçal. A melhor opção é você ter um relatório seco, com funcionalidades padrão (que estarão sempre no relatório) e a parte dinâmica, que será criada em tempo de execução.
Você quis dizer q eu devo desenhar meu relatório completo (as partes fixas e dinâmicas) e depois, via código, ir removendo o que eu não quero exibir???

Com certeza já ajudou, muito obrigado…
tentarei algo aki, e posto se tiver dúvida

valeu por enquanto… :slight_smile:

J

Opa.

Não, é como falei:

Você precisa ter um XML daquilo que será imutável, isto é, não no sentido de conteúdo, mas de design. Aquilo que ficará fixo em seu relatório independente das trocas de posições e também alguma regra no qual você deverá exibir um grupo ou esconder outro, de acordo como groupExpression.

Daí então você vai ler esse relatório XML, transformar em um JasperDesign e apartir daí adicionar os componentes dinâmicos para desenhar aquilo que for preciso, ao seu relatório inicial.

Solução mista.

Att,

M

jonataswingeter: acho q consegui resolver meu problema, criarei tudo dinamicamente atraves de código, não utilizarei o iReport. No meu caso será mais fácil assim.

aproveitando… vc já trabalhou, ou sabe, como criar gráficos com o jasper??? no meu caso tb os faria dinamicamente atraves do código.

aguardo resposta
valeu
abraços

J

http://jasperforge.org/sf/wiki/do/viewPage/projects.jasperreports/wiki/Samples

Olhe JFreeChart Sample

Att.

M

acontece o seguinte…

eu já trabalho com JFreeChart, mas estou querendo vincula-lo com o Jasper e tá dificil achar algo na net.

Achei algo sobre as classes: JRChart, JRDesignChart, JRDesignChartAxis, JRChartPlot…

estou meio perdido com elas…pois cada uma faz uma parte do gráfico e depois temos que uní-las, eu acho…

vc sabe alguma coisa a respeito disso???

valeu
abraço

J

Então…

Porque você não consegue integrar com JFreeChart?

Não implementei muitos recursos ainda com Gráficos em Jasper, mas vou te explicar uma coisa:

JRChart é a interface que estabelece um contrato de exibição;
JRDesignChart é a implementação do contrato, ou seja, você usa este componente para criar um gráfico e adiciona à alguma banda.

Att.

M

olha o q eu estou fazendo:

JRDesignChart chart = new JRDesignChart(null, JRChart.CHART_TYPE_LINE); chart.setY(100); chart.setHeight(100); chart.setMode(JRChart.MODE_OPAQUE); chart.setBorderColor(Color.RED); chart.setBackcolor(Color.GREEN); chart.setForecolor(Color.BLACK); chart.setWidth(200); chart.setDataset(DÚVIDA); band.addElement(chart);
eu vi que o JFreeChart utiliza um Dataset, mas estou perdido em como criá-lo para setar no chart.

e sem o Dataset, não se cria o gráfico. E também não consegui setar um obejeto JFreeChart no JRDesignChart (nem sei se dá).

obs.: desculpe ficar te importunando, mas se puder continuar ajudando seria ótimo.

valeu

J

http://jsourcery.com/api/sourceforge/jasperreports/1.2.8/net/sf/jasperreports/engine/JRChartDataset.html

Você deve usar JRDesignXXX para implementar o dataset de acordo com o seu gráfico.

att.

M

fiz o JFreeChart gerar uma imagem (o gráfico) e coloquei a imagem no pdf.

ficou assim:
JRDesignParameter parameter = new JRDesignParameter();
parameter.setName("imagenzinha");
parameter.setValueClass(java.awt.Image.class);
jasperDesign.addParameter(parameter);

JFreeChart jfc = criaGrafico();
Image graf = jfc.createBufferedImage(300, 400);
parameters.put("imagenzinha", graf);

JRDesignImage image = new JRDesignImage(jasperDesign);
image.setX(0);
image.setY(100);
image.setHeight(89);
image.setWidth(216);
expression = new JRDesignExpression();
expression.setValueClass(Image.class);
expression.setText("$P{imagenzinha}");
image.setExpression(expression);
band.addElement(image);


public static JFreeChart criaGrafico(){
    // objeto gráfico
    JFreeChart chart = null;

    // valores do gráfico
    double[][] Values = new double[][] {{1,2},{2,1}};
    // Criar dataset com os itens a serem mostrados
    DefaultIntervalCategoryDataset dataset = new DefaultIntervalCategoryDataset(Values, Values);

    // categorias do gráfico
    String[] Category = new String[] {"Cat1","Cat2"};
    // poe o label das categorias
    dataset.setCategoryKeys(Category);

    // Series do gráfico
    String[] Series = new String[] {"Ser1","Ser2"};
    // põe o nome das series
    dataset.setSeriesKeys(Series);

    // Nome eixo X
    String CategoryName = "Eixo X";
    // Cria o item de categorias
    CategoryAxis categoryAxis = new CategoryAxis(CategoryName);

    // cria o item de valores do gráfico - nome do Eixo Y
    ValueAxis valueAxis = new NumberAxis("Eixo Y");

    // inverte o gráfico
    ((NumberAxis) valueAxis).setInverted(false); // false

    // para criar os dados para o gráfico
    CategoryPlot plot = null;

    // criar barras ou linhas
    AbstractCategoryItemRenderer renderer = null;

    // de acordo com o tipo do gráfico
          // criar barras 3d
          renderer = new BarRenderer3D(5,5);
          // aumenta(valor negativo)/diminue(valor positivo) da largura da margem da barra
          ((BarRenderer3D) renderer).setItemMargin(0.0);
          // cor nas laterais do chart quando no efeito 3d
          ((BarRenderer3D) renderer).setWallPaint(Color.BLACK);
          // Posicão do label na barra positivo (sobe) e negativo (desce)
          ((BarRenderer3D) renderer).setItemLabelAnchorOffset(5);
          // margem a esquerda da primeira barra
          categoryAxis.setLowerMargin(0.05); // 0.05
          // margem a direita da ultima barra
          categoryAxis.setUpperMargin(0.05); // 0.05

    // cria as categorias
    plot = new CategoryPlot(dataset, categoryAxis, valueAxis, renderer);
    // indica se é horizontal ou vertical
    plot.setOrientation(PlotOrientation.VERTICAL);
    // mostrar linhas de grades verticais
    plot.setDomainGridlinesVisible(true); // false
    // a cor das linhas de grades verticais
       plot.setDomainGridlinePaint(Color.GRAY);
    // mostrar linhas de grades horizontais
    plot.setRangeGridlinesVisible(true);
    // a cor das linhas de grades horizontais
    plot.setRangeGridlinePaint(Color.GRAY);
    // a cor do fundo do grafico
    plot.setBackgroundAlpha(0); //teste para deixar transparente
//    plot.setBackgroundPaint(Color.);
    // zoom no gráfico
//    plot.zoom(10.0);


    // cria o chart
    chart = new JFreeChart("TesteGrafico", plot);
    // sem bordas no chart
    chart.setBorderVisible(false);

       // pega a legenda
       LegendTitle Legenda = ((LegendTitle) chart.getLegend());
       // posicao
       Legenda.setPosition(RectangleEdge.TOP);
       // cor de fundo
       Legenda.setBackgroundPaint(new Color(0,0,0,0.0f));
       // seta o alinhamento
       Legenda.setVerticalAlignment(VerticalAlignment.CENTER);

       // para remover legenda
       //      chart.removeLegend();

    // OS ITENS COMENTADOS NA FRENTE SÃO OS VALORES PADRÃO
    // largura das barras
    categoryAxis.setCategoryMargin(0.2); // 0.2
    // se mostra os valores da categoria
    categoryAxis.setTickLabelsVisible(true); // true
    // seta o fundo como transparente
    chart.setBackgroundPaint(new Color(0,0,0,0.0f));
    // tira o anti aliasing da pagina
    chart.setAntiAlias(false);

    return chart;
}

valeu pelas dicas jônatas...ajudou pra caramba mano
abraços

J

Ótimo Mateus!

Só não esqueça de colocar o assunto como RESOLVIDO, e assim contribuir no fórum.

Att.

M

o tópico não é meu…acho que não dá pra alterar neh!!! rs…

abraços

H

efukuda:
Como eu faço para criar um relatório com JasperReports dinâmico, ou seja,
eu criar o xml via código.
O usuário irá escolher os campos que vão aparecer. Eu sei que se eu colocar dois fields e não passar nenhum parâmetro não irá aparecer. Mas eu preciso distribuir estes campos de uma forma que não fiquem espaços em branco no meio do relatório. Para isso que precisaria criar o relatório do zero, ou seja, precisaria criar o xml da forma que eu quiser via código.

Ou se existe algum outro jeito de eu fizer isso, ou alguma outra idéia de como eu posso fazer este relatório de uma forma que os campos fiquem bem distribuídos.

Obrigado

Ae kra…acessa esse link…é do Dynamic Jasper…lá eles tem um exemplo legal…tambem tava precisando e achei…vem disponivel com um exemplo e tem as APIS para baixar…e as bibliotecas tbm…flw

http://dynamicjasper.sourceforge.net/

E

Pessoal desculpa, vim pedir ajuda, depois de tanto tempo, porem é o único post que achei na internet sobre este assunto

Bom,l estou fazendo um relatorio dinamicamente com o JasperReport mais não aparece nada

Veja o código

JasperDesign

private JasperDesign getJasperDesign(List<JFreeChart> freesCharts)  
            throws JRException {  
  
        JasperDesign design = new JasperDesign();  
  
        design.setName("RelatorioGraficoSimilaridade");  
        design.setPageWidth(1100);  
        design.setPageHeight(600);  
        design.setColumnCount(1);  
        design.setColumnWidth(540);  
        design.setColumnSpacing(0);  
        design.setLeftMargin(0);  
        design.setRightMargin(0);  
        design.setTopMargin(0);  
        design.setBottomMargin(0);  
  
        JRDesignBand titulo = new JRDesignBand();  
        titulo.setHeight(70);  
        JRDesignStaticText staticText = new JRDesignStaticText();  
        staticText.setX(170);  
        staticText.setY(18);  
        staticText.setWidth(300);  
        staticText.setHeight(32);  
        staticText.setFontName("Tahoma");  
        staticText.setPdfFontName("Helvetica-Bold");  
        staticText.setFontSize(24);  
        staticText.setBold(true);  
        staticText.setHorizontalAlignment(HorizontalAlignEnum.CENTER);  
        staticText.setText("Relatório Grafico Similaridade");  
        titulo.addElement(staticText);  
        design.setTitle(titulo);  
  
        JRDesignBand colunaCabecalho = new JRDesignBand();  
          
        JRDesignBand detalhe = new JRDesignBand();  
  
        for (int i = 0; i < freesCharts.size(); i++) {  
  
            JRDesignParameter parametro = new JRDesignParameter();  
            String nomeParametro = i + "imagem";  
            parametro.setName(nomeParametro);  
            parametro.setValueClass(java.awt.Image.class);  
            design.addParameter(parametro);  
  
            JRDesignImage image = new JRDesignImage(design);  
            image.setX(100);  
            image.setY(0);  
            image.setHeight(151);  
            image.setWidth(201);  
            JRDesignExpression expression = new JRDesignExpression();  
            expression.setValueClass(Image.class);  
            expression.setText("$P{" + nomeParametro + "}");  
            image.setExpression(expression);  
              
            detalhe.setHeight(200);  
            detalhe.addElement(image);  
  
        }  
  
        design.setColumnHeader(colunaCabecalho);  
        design.setDetail(detalhe);  
  
        return design;  
    }

gerarRelatorio

public void gerarRelatorio() {  
    ServletOutputStream ouputStream = null;  
    List<JFreeChart> freesCharts = this.gerarGraficos(); (Obs: este metodo gera as imagens corretas pois ja fiz teste unitario)  
    try {  
        JasperDesign desenho = getJasperDesign(freesCharts);  
        JasperReport relatorio = JasperCompileManager.compileReport(desenho);  
        Map<String,Object> parametro = new HashMap<String,Object>();  
        for (int i = 0 ; i < freesCharts.size(); i++) {  
            Image imagem = freesCharts.get(i).createBufferedImage(200, 150);    
            String nomeParametro = i+"imagem";  
            parametro.put(nomeParametro, imagem);    
        }  
        JasperPrint relatorioFinal = JasperFillManager.fillReport(relatorio, parametro);  
        FacesContext facesContext = FacesContext.getCurrentInstance();  
        HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();  
        response.setContentType("application/pdf");  
        response.addHeader("Content-Disposition","attachment; filename=RelatorioGraficoSimilaridade.pdf");  
        ouputStream = response.getOutputStream();  
        JRPdfExporter exporterPdf = new JRPdfExporter();  
        exporterPdf.setParameter(JRPdfExporterParameter.JASPER_PRINT, relatorioFinal);  
        exporterPdf.setParameter(JRPdfExporterParameter.OUTPUT_STREAM, ouputStream);  
        exporterPdf.exportReport();  
        facesContext.responseComplete();  
        ouputStream.flush();  
          
  
    } catch (IOException ex) {  
        ex.printStackTrace();  
    } catch (JRException ex) {  
        ex.printStackTrace();  
    } finally {  
        if (ouputStream != null) {  
            try {  
                ouputStream.close();  
            } catch (IOException ex) {  
                ex.printStackTrace();  
            }  
        }  
    }  
}

Pessoal o relatório apenas gera um folha em branco , nem o título ele está gerando, alguem sabe o que pode ser?

Desta ja agradeço

Criado 21 de dezembro de 2006
Ultima resposta 18 de nov. de 2010
Respostas 20
Participantes 8