Compilar reportes de iReport desde Java

   Hace algún tiempo explicaba como enlazar los reportes de ireport en java, pero lo hacia utilizando un archivo compilado que generaba el iReport cuya extensión es ".jasper", hasta ahora todo bien, el problema viene cuando modificamos nuestro reporte, puesto que debemos compilarlo y así tener una vez más el archivo jasper actualizado, llegando a ocupar en nuestra carpeta de reportes, no solo el "jrxml" que es el archivo xml del reporte, sino también los ".jasper".

   Esto tiende a ser un poco molesto ya que tendremos 2 archivos por cada reporte y la verdad no es nada cómodo el entrar a la carpeta de reportes cuando se tienen mas de 200. Entonces la solución es utilizar el xml del reporte directamente.

   No explicare mucho ya que todo esta explicado en las siguientes entradas:


   Entonces nuestro código sería el siguiente:
String archivo = "Mi_Reporte.jrxml";
JasperReport masterReport= JasperCompileManager.compileReport(archivo);
JasperPrint jasperPrint= JasperFillManager.fillReport(masterReport,parametros,conexionSQL);
JasperViewer jviewer= new JasperViewer(jasperPrint,false);

   Explicando cada cosa tenemos que:

   - archivo: variable de la ruta donde se ubica el archivo "jrxml".

   - masterReport: utilizamos el compilador interno para que el mismo método se encargue de compilar y generar la vista, en vez de cargar la hecha como lo hacíamos antes.

   - jasperPrint: con esto enviamos por pantalla el resultado de la compilación, utilizando el reporte maestro, los parámetros y los datos de la conexión con la base de datos SQL, en caso de no usar nada de eso simplemente colocamos null en cada opción (por decirlo así).

   - jViewer: mostramos finalmente el reporte en vez de imprimirlo directamente, esto ayuda al usuario en caso de querer guardarlo y no gastar papel (ayudemos al planeta de vez en cuando, vale!?).

   Entonces sabiendo todo esto, nuestra clase queda de la siguiente manera:
package reporte;

import java.util.HashMap;
import java.util.Map;
import javax.swing.JOptionPane;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.view.JasperViewer;

public class IniciarReporte {

    public void Imprimir(){
        try{
            String archivo = "Mi_Reporte.jrxml";
            if(archivo == null){
                JOptionPane.showMessageDialog(null,"Error al cargar reporte",
                        "Generar Reporte",JOptionPane.ERROR_MESSAGE);
            } JasperReport masterReport= null;
            try {
                masterReport= JasperCompileManager.compileReport(archivo);
            } catch (JRException e) {
                JOptionPane.showMessageDialog(null,"Error al compilar reporte",
                        "Generar Reporte",JOptionPane.ERROR_MESSAGE);
            } Map parametros= new HashMap();
            parametros.put("parametro1", valorparametro1);
            JasperPrint jasperPrint= JasperFillManager.fillReport(masterReport,parametros,conexionSQL);
            JasperViewer jviewer= new JasperViewer(jasperPrint,false);
            jviewer.setVisible(true);
        }catch (Exception ex){
            JOptionPane.showMessageDialog(null,"Un mensaje de error que puedes personalizar si quieres",
                "Generar Reporte",JOptionPane.ERROR_MESSAGE);
        }
    }
}

21 Comentarios

Escribir Comentario
28 de noviembre de 2012, 21:13 delete

Hola carlitox muy interesante tu aporte de verdad muchas gracias me es muy útil, pero me gustaría saber como puedo concatenar digamos, más de dos reportes compilados y presentarlos en uno solo PDF?
Hago algo parecido a esto y le concateno una variable que guarda el nombre del reporte:

jasperDesign = JRXmlLoader.load("C:/algo/"+nomrepor+".jrxml");
jasperReport = JasperCompileManager.compileReport(jasperDesign);
jasperPrint = JasperFillManager.fillReport(jasperReport,parameters,conn);
response.setContentType("application/pdf");
JasperExportManager.exportReportToPdfStream(jasperPrint,servletOutputStream);
servletOutputStream.flush();
servletOutputStream.close();

Ojala sirve de algo, gracias de antemano un saludo

Responder
avatar
28 de noviembre de 2012, 21:26 delete

En esta entrada explico lo básico utilizando el archivo ya compilado (.jasper) en vez de compilarlo en tiempo real (.jrxml)... Así que para lo que quieres primero tienes que hacer el método como en la siguiente entrada:

http://carlitoxenlaweb.blogspot.com/2012/10/compilar-reportes-de-ireport-desde-java.html

Para utilizar el método con "N" número de reportes, agrega una variable del tipo string y hazlo como lo estas haciendo:

void imprimir(string nombre_rpt){
jasperDesignRpt = "C:/algo/"+nombre_rpt+".jrxml";
}

Ahora lo que te toca hacer es crear un subreporte dentro del reporte, y luego pasarlo por parametro para saber que subreporte imprimir. Ahora lo que te recomiendo es que no uses rutas absolutas, sino que tomes por variables del sistema el directorio donde se ejecuta tu app y la utilces junto con la variable, espero se entienda, sino me comentas para hacer una entrada de ello.... Saludos!!

Responder
avatar
marlboro
AUTOR
28 de noviembre de 2012, 22:04 delete

Oye gracias por tomarte el tiempo de responder, con lo que me has comentado me das un nuevo panorama para seguir investigando, pero no me caería nada mal que hicieras una entrada de este tema! veras en realidad lo que en estos momentos trato de hacer es generar el mismo reporte varias veces pero concatenando los distintos resultados compilados según los parámetros que reciba el reporte, nuevamente gracias por tomarte el tiempo tendré muy en cuenta lo que escribiste, saludos desde México.

Responder
avatar
28 de noviembre de 2012, 22:15 delete

Ya entendi lo que quieres, pero con un subreporte no lo puedes lograr ya que el toma las variables que una vez enviaste, no puedes enviar varias variables, generar varios reportes y luego enviarlos, pero lo que si puedes hacer es generar los reportes y guardarlos en pdf individual, luego con un puente de cualquier manejador de pdf los unes, como por ejemplo el PDFCreator... Es lo mas sencillo que se me ocurre!!

Responder
avatar
marlboro
AUTOR
29 de noviembre de 2012, 0:04 delete

Ok carlitos, esa me parece la solucion mas rápida por el momento, encontre algo sobre una librería para unir los PDF llamada itext http://itextpdf.com/ por si te interesa, de todas maneras en cuanto obtenga algún avance lo comparto contigo, gracias y sigue posteando buenas ideas! que son de gran ayuda para uno que otro despistado como yo haha! xD!

Responder
avatar
CHFOP
AUTOR
19 de junio de 2013, 8:15 delete

hola
muchas gracias por tu aporte, tengo un problema lo que pasa es que estoy tratando de abrir un reporte que contiene un subreporte pero me arroja el siguiente error

jun 19, 2013 7:10:28 AM net.sf.jasperreports.engine.fill.JRFillSubreport prepare
SEVERE: Fill 1898351998: exception
java.lang.NullPointerException
at java.lang.Class.isAssignableFrom(Native Method)
null
at net.sf.jasperreports.engine.fill.JRFillTextField.getFormat(JRFillTextField.java:706)
at net.sf.jasperreports.engine.fill.JRFillTextField.evaluateText(JRFillTextField.java:394)
at net.sf.jasperreports.engine.fill.JRFillTextField.evaluate(JRFillTextField.java:368)
at net.sf.jasperreports.engine.fill.JRFillElementContainer.evaluate(JRFillElementContainer.java:258)
at net.sf.jasperreports.engine.fill.JRFillBand.evaluate(JRFillBand.java:499)
at net.sf.jasperreports.engine.fill.JRVerticalFiller.fillColumnBand(JRVerticalFiller.java:2033)
at net.sf.jasperreports.engine.fill.JRVerticalFiller.fillDetail(JRVerticalFiller.java:760)
at net.sf.jasperreports.engine.fill.JRVerticalFiller.fillReportStart(JRVerticalFiller.java:270)
at net.sf.jasperreports.engine.fill.JRVerticalFiller.fillReport(JRVerticalFiller.java:128)
at net.sf.jasperreports.engine.fill.JRBaseFiller.fill(JRBaseFiller.java:946)
at net.sf.jasperreports.engine.fill.JRBaseFiller.fill(JRBaseFiller.java:845)
at net.sf.jasperreports.engine.fill.JRFillSubreport.fillSubreport(JRFillSubreport.java:609)
at net.sf.jasperreports.engine.fill.JRSubreportRunnable.run(JRSubreportRunnable.java:59)
at net.sf.jasperreports.engine.fill.JRThreadSubreportRunner.run(JRThreadSubreportRunner.java:205)
at java.lang.Thread.run(Thread.java:722)

estoy llamando el reporte de la siguiente forma


try{
Map parametros = new HashMap();
parametros.put("logo", System.getProperty("user.dir")+"\\LOGOFACTURA.jpg");
parametros.put("fte", ""+fte.getSelectedItem());
parametros.put("fechaini", String.valueOf(sdf.format(fecini.getDate())));
parametros.put("fechafin", String.valueOf(sdf.format(fecfin.getDate())));
parametros.put("factura", "500");

JasperReport factura = JasperCompileManager.compileReport("facturacit.jrxml");
JasperPrint print = JasperFillManager.fillReport(factura,parametros, conexion);
JasperViewer visor = new JasperViewer(print,false) ;
visor.setVisible(true) ;
visor.setDefaultCloseOperation( javax.swing.JFrame.DISPOSE_ON_CLOSE );



JasperReport cita = JasperCompileManager.compileReport("detalladocitas.jrxml");
JasperPrint print1 = JasperFillManager.fillReport(cita,parametros, conexion);
JasperViewer visor1 = new JasperViewer(print1,false) ;
visor1.setVisible(true) ;
visor1.setDefaultCloseOperation( javax.swing.JFrame.DISPOSE_ON_CLOSE );


/*JasperReport facturadet = JasperCompileManager.compileReport("detalladofacturaproc.jrxml");
JasperPrint print1 = JasperFillManager.fillReport(facturadet,parametros, conexion);
JasperViewer visor1 = new JasperViewer(print1,false) ;
visor1.setVisible(true) ;
visor1.setDefaultCloseOperation( javax.swing.JFrame.DISPOSE_ON_CLOSE );*/
}
catch(Exception e){
Logger.getLogger(procedimientosmanual.class.getName()).log(Level.SEVERE, null, e);
System.out.println(e.getMessage());
}

de antemano muchas gracias

Responder
avatar
19 de junio de 2013, 8:28 delete

Hola, al parecer el problema esta en el subreporte, recuerda que debes agregarlo al reporte padre junto con un "dataset" para que este haga las consultas necesarias y las pase por parametros al reporte hijo....

Responder
avatar
CHFOP
AUTOR
19 de junio de 2013, 14:08 delete

muchas gracias por responder, el problema es que cuando lo ejecuto desde el netbeans puedo ver el reporte, pero cuando lo ejecuto desde la aplicacion no sale el reporte

Responder
avatar
19 de junio de 2013, 15:00 delete

Enviame al correo los fuentes, han de ser las rutas, para evitarte dolores de cabeza en esa parte utiliza tambien en la configuración de la ruta del subreporte el código de Java, para que tome la ruta relativa de tu proyecto sin indicarsela manualmente.....

Responder
avatar
Anónimo
AUTOR
20 de junio de 2013, 9:59 delete

Sr. Carlos Martinez soy nuevo manejando java y netbeans me gustaría saber como a un jdesktoppane le puedo colocar una barra desplazadora.
Gracias

Responder
avatar
20 de junio de 2013, 11:00 delete

Como estas? la verdad no viene mal utilizar el buscador ubicado en la parte superior a mano derecha....

http://carlitoxenlaweb.blogspot.com/2010/09/panel-con-scroll.html

El principio es el mismo, solo que debes cambiar las variables a para asociarlas al JPanel... Saludos!!

Responder
avatar
CHFOP
AUTOR
20 de junio de 2013, 22:31 delete

try{
Map parametros = new HashMap();
parametros.put("logo", System.getProperty("user.dir")+"\\LOGOFACTURA.jpg");
parametros.put("fte", ""+fte.getSelectedItem());
parametros.put("fechaini", String.valueOf(sdf.format(fecini.getDate())));
parametros.put("fechafin", String.valueOf(sdf.format(fecfin.getDate())));
parametros.put("factura", "500");
//parametros.put("SUBREPORT_DIR", "\\");
System.out.println(parametros);
//parametros.put("factura", nfacut);


//System.out.println( System.getProperty("user.dir")+"\\LOGOFACTURA.jpg");
//parametros.put("logo", System.getProperty("user.dir")+"\\LOGOFACTURA.jpg");

//parametros.put("facturafos", (String) facfos.getText());

JasperReport factura = JasperCompileManager.compileReport("facturacit.jrxml");
JasperPrint print = JasperFillManager.fillReport(factura,parametros, conexion);
JasperViewer visor = new JasperViewer(print,false) ;
visor.setVisible(true) ;
visor.setDefaultCloseOperation( javax.swing.JFrame.DISPOSE_ON_CLOSE );

JasperReport cita = JasperCompileManager.compileReport("detalladocitas.jrxml");
JasperReport cita1 = JasperCompileManager.compileReport("detalladocitas_subreport1.jrxml");
JasperPrint print1 = JasperFillManager.fillReport(cita,parametros, conexion);
JasperViewer visor1 = new JasperViewer(print1,false) ;
visor1.setVisible(true) ;
visor1.setDefaultCloseOperation( javax.swing.JFrame.DISPOSE_ON_CLOSE );


/*JasperReport facturadet = JasperCompileManager.compileReport("detalladofacturaproc.jrxml");
JasperPrint print1 = JasperFillManager.fillReport(facturadet,parametros, conexion);
JasperViewer visor1 = new JasperViewer(print1,false) ;
visor1.setVisible(true) ;
visor1.setDefaultCloseOperation( javax.swing.JFrame.DISPOSE_ON_CLOSE );*/
}
catch(Exception e){
Logger.getLogger(procedimientosmanual.class.getName()).log(Level.SEVERE, null, e);
//System.out.println(e.getMessage());
}

Responder
avatar
CHFOP
AUTOR
20 de junio de 2013, 22:32 delete

hola este es el codigo que usos para llamar el reporte
pero sigue sin mostrar nada

Responder
avatar
22 de junio de 2013, 11:25 delete

Hola, bueno veras, el problema esta en la parte del reporte, cuando utilizas un subreporte debes llamar al hijo desde el padre, y no ambos desde el código.... Es decir, desde la ireport configura el subreporte, a modo que cuando llames al reporte principal desde Java, es mismo código jrxml se encargue de llamar el subreporte asociado al padre, no cargarlo desde el codigo como lo estas haciendo.....

Configura bien la ruta de tu subreporte cambiando por rutas relativas, no absolutas... Prueba y me comentas... Saludos!!

Responder
avatar
24 de julio de 2013, 11:37 delete

Carlitox:

Hola soy Carlos, muchas gracias por compartir tu conocimiento y responder los mails a consultas que realizé y quiero dejar algunos apuntes a alguien que le pueda servir.

1.- si no quieren usar datasource o coneccion a BD y pasar solo los parametros seria de la siguiente forma:

* hacemos el map
Map parameters = new HashMap();
parameters.put("orderNumber",new Long(7000L));
parameters.put("companyFiscalId",new String("11.111.111-1"));
parameters.put("companyFantasyName", new String("Mocosoft"));

InputStream reportStream = new FileInputStream(reporte);
JasperReport report = JasperCompileManager.compileReport(reportStream);
JasperPrint jasperPrint = JasperFillManager.fillReport(report,parameters,new JREmptyDataSource());

el JREmptyDataSource es la clave para esto

2.- si quieren pasar a PDF
JasperExportManager.exportReportToPdfFile(jasperPrint, "C:\\Users\\tiexterno02.ms.cl\\Documents\\hola.pdf");

3.- si quieren cargar datos en un subreporte asociado al maestro

//Crear el mapa de parametros del sunreporte
Map datosSubReporte = new HashMap();
listaSubReporte = new ArrayList();

while (i < 30){
datosSubReporte.put("address", new String ("av. santa maria"));
datosSubReporte.put("totalAmount", new Long(800000L));

listaSubReporte.add(datosSubReporte);
i++;
}

Collection branches = listaSubReporte;
parameters.put("branches", branches);

(el while lo puse para ver si iteraba bien el subreporte).

4.- si quieren compilar sobreportes desde rutas de SO deben colocar lo siguiente:

en el subreport_dir (reporte maestro o principal)





y en el subreportexpresion le pasan el .jasper




espero ayudar con esto

Responder
avatar
28 de enero de 2016, 17:45 delete

Hola una pregunta yo quize modificar un reporte de un proyecto que me pasaron lo compile y al momento de correrlo aparece

mensaje de error:null

Responder
avatar
Alex
AUTOR
7 de septiembre de 2016, 14:56 delete

Buenas tardes, estoy tratando de arrojar un reporte de Factura con subreporte
mi pregunta es como ejecutar el reporte con el subreporte, ya he intentando de muchas formas pero no me esta saliendo, les agradeceria mucho la ayuda.
Este es mi codigo fuente

Responder
avatar
7 de septiembre de 2016, 17:58 delete

Que has intentado? Si utilizas el plugin o el propio IDE entonces verás en el reporte padre la opción Sub-Reporte, cuando la seleccionas te saldrá una ayuda y debes hacer lo siguiente:

1. Usar un reporte existente (ya lo tienes creado y en la misma ruta/carpeta de tu reporte padre)
2. Usar la misma conexión (en caso de que estés haciendo consulta a la misma Base de Datos)
3. Ahora viene la pantalla de parámetros, aquí vas a asignar el campo que viene desde el reporte padre si es que lo necesitas. Por ejemplo, si vas a filtrar el sub-reporte por nombre entonces debes crear el parámetro "Nombre" en el reporte hijo, dejando como expresión "Nombre - field", (en las propiedades de ese parámetro debe quedar algo como $F{nombre}).
4. Como lo hemos creado en la misma ruta/carpeta entonces seleccionamos la opción de "Utilizar una referencia a la ruta estática absoluta" (Use a static absolute path reference).

Con esto ya deberías tener tu sub-reporte funcionando sobre el reporte maestro o padre.

Responder
avatar
Unknown
AUTOR
4 de junio de 2017, 1:43 delete

consulta, necesito hacer original y duplicado de un reporte, he intentado de todo pero no me sale. alguna sugerencia?? ayuda!!

Responder
avatar
5 de junio de 2017, 18:36 delete

Pudieras simplemente guardar 2 veces el archivo, o al momento de generarlo (jasperPrint) mostrar por pantalla el original dejando una copia en otro lugar, si lo que quieres es que se muestre que uno es original y otro copia entonces genera 2 veces el mismo reporte enviando como parametro que tipo es cada uno.

Responder
avatar

Lamentablemente hay muchos usuarios en la red que han llegado al blog para escribir obscenidades, así que la moderación se hace necesaria. Recuerda utilizar un lenguaje correcto y espera a que sea aprobado.

Si necesitas publicar código haz click en "Conversión" para hacerlo legible.
ConversiónConversión EmoticonEmoticon