Ejemplo1: ejecutar un reporte basado en una plantilla

Bueno, no voy a comenzar con teoría, eso lo pueden encontrar en la página de JasperForge(JasperReports).

Este primer ejemplo, implementa una pequeña ventana en la cual ejecutaremos un reporte basado en una plantilla (ya se, dije que el tutorial sería sobre implementación de reportes con el API), pero me parece un buen punto de partida ver código sobre como podemos cargar una plantilla, compilarla, llenarla y finalmente exportarla a algún formato. Cabe resaltar que pondré fragmentos reducidos del código de ejemplo para abreviar, el código completo pueden verlo descargando el ejemplo al final de la página.

Para ejecutar el ejemplo, hice un script de Ant, así que solo deben entrar a la carpeta donde está el script (build.xml en la raiz) y ejecutar el comando “ant”. Para los que usen algún IDE, pueden configurar el proyecto, las librerías necesarias están en la carpeta “lib” y la clase principal es: “Main.java”. 

Es importante aclarar que en el archivo “build.properties” está la ruta a la plantilla que se ejecutará, si por alguna razón surge un error, corrijan la ruta a la plantilla en ese archivo.

Vamos a lo interesante, la clase que hace todo el trabajo referente al reporte es: “HelloWorldReportExecutor”, en esta clase tenemos el código para las diferentes tareas, analicemos las más importantes:

public String executeReport(){
   JasperDesign jasperDesign=loadTemplate();
   setTempDirectory();
   JasperReport jasperReport=compileReport(jasperDesign);
   JasperPrint jasperPrint=fillReport(jasperReport);
   String res=exportReport(jasperPrint);
   return(res);
}

Ahí podemos ver los pasos para ejecutar nuestro reporte.

Primero cargamos la plantilla, es decir se crea una estructura “JasperDesign” que es el diseño del reporte que representa nuestra plantilla, veamos dos líneas del método “loadTemplate”:

   File templateFile=new File(templatePath);
   JasperDesign jasperDesign= JRXmlLoader.load(templateFile);

Como se puede ver, primero creamos un objeto “File” con la ruta del archivo plantilla, y usamos la clase “JRXmlLoader” para cargar la plantilla. El objeto de clase “JasperDesign” contiene todas las configuraciones definidas en la plantilla XML, es como tener la plantilla en una estructura de objetos, en futuros ejemplos, crearemos esa estructura mediante el API de JasperReports.

El segundo paso es compilar el reporte (antes de eso se define un directorio donde se guardará cierta información temporal del proceso, no es un paso en si). Veamos el siguiente fragmento:

   JasperReport jasperReport= JasperCompileManager.compileReport(jasperDesign);

La clase “JasperCompileManager” nos ayuda a compilar nuestro diseño, si tenemos algún error de diseño en la plantilla, aquí podremos conocer dicho error. El objeto de tipo “JasperReport” es una estructura muy similar al “JasperDesign”, pero en este caso, contiene la estructura del reporte ya compilado y validado.

Con nuestro objeto “jasperReport”, ya podemos llenar el reporte con datos, esto se hace mediante:

JasperPrint jasperPrint =JasperFillManager.fillReport(
                                jasperReport,
                                new HashMap(),
                                new JREmptyDataSource());

La clase “JasperFillManager” nos ayuda a llenar el reporte con la información que este requiere, recibe como parámetros: la estructura del reporte compilado, un mapa o diccionario con los parámetros que requiere el reporte, y una fuente de datos o “DataSource” (nuestro ejemplo no necesita datos, por eso usamos una instancia de “JREmptyDataSource”). En el mapa de parámetros, podemos proveer al reporte con los valores de los parámetros que necesita (especialmente los $P{} que podamos necesitar en la plantilla).

El objeto de tipo “JasperPrint” es otra estructura que almacena el reporte mas sus datos, de manera que está lista para ser mostrada, o almacenada o exportada según se requiera.

Entonces veamos el último paso, cómo exportar el reporte a algún formato:

JRAbstractExporter exporter=new JRRtfExporter();
exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
exporter.setParameter(JRExporterParameter.CHARACTER_ENCODING, "UTF-8");
StringBuffer stringBuffer=new StringBuffer();
exporter.setParameter(JRExporterParameter.OUTPUT_STRING_BUFFER, stringBuffer);
...
exporter.exportReport();

Primero instanciamos el exportador que vamos a usar, en este caso “JRRtfExporter”, es decir que queremos exportar al formato Rtf. Como la mayoría debe saber, tenemos varios exportadores, por ejemplo a Pdf, Xls, Html, etc.

Luego, le damos al exportador algunos parámetros de configuración, como la estructura que queremos exportar (instancia de “JasperPrint”), la codificación que queremos que use, y el contenedor del resultado (en este caso quiero que se almacene el resultado en un StringBuffer) para el cual existen varias opciones.

Luego, ejecutando el método “exportReport” ya tendremos nuestra instancia de “StringBuffer” con el reporte exportado en el formato Rtf, el cuál mostraremos en el campo de texto de nuestra aplicación de ejemplo.

Bueno, ya tenemos nuestro primer ejemplo, al ejecutarlo podemos ver el resultado generado por nuestra plantilla (bueno, más unos símbolos extraños, que creo son porque el componente de Swing que usé no reconoce todo el contenido Rtf del resultado).

Y voilà, aquí termina este primer ejemplo, espero sea de utilidad, cualquier comentario o pregunta, no duden en escribir.

Gracias por leer.

Aquí está el código del ejemplo, ya lo tengo en sourceforge: Ejemplo

17 comentarios el “Ejemplo1: ejecutar un reporte basado en una plantilla

  1. Hi Burriquin,

    (I like your name, I suppose it is an Spanish name). Would you please write the tutorial in English?… I don’t understand Spanish well.

    Thank you in advance,
    marcelo

  2. Hola!!!! Me parece muy bueno tu tutorial, pero quisiera que me dieras un poco de ayudita con algo que me esta dando problemas….

    En mi proyecto cuando quiero compilar mi reporte me da un error:

    GRAVE: Error in compiling the report…. Error compiling report java source files : C:\Documents and Settings\maria.estevez.CINET\Warehouse WorkSpace\ReportGenerator\report32name_1243999075453_676167.java

    No entiendo de donde saca ese “report32name_1243999075453_676167.java “. Si me bajo el código que dejaste en esta página me da el mismo error pero el report32name lo cambia por HelloReportExecutor.

    De verdad no entiendo en donde está dando el error.. Si me puedes echar un manito con eso por fa🙂

  3. Bueno, ese archivo .java parece tener un nombre generado, a lo mejor es un archivo temporal que se genera en el proceso de compilación, pero con lo poco que pusiste, pues no puedo ayudarte mucho.

    A lo mejor podría ayudarte si pones toda la pila de mensajes de la excepción, también puedes encontrar ayuda en el foro de JasperReports, por ejemplo aquí encontré un post, puede que este sea tu problema:
    http://jasperforge.org/plugins/espforum/view.php?group_id=102&forumid=103&topicid=24736

    Es decir, podrías intentar añadir la librería jdt-compiler a tu proyecto, por favor, me avisas si te ayuda.

  4. Hola Alvaro! Gracias por la ayuda, con lo que me dijiste funcionó bien. Y por cierto, también te agradezco por la dirección del foro me fue muy útil para entender cosas que aun no tenia claras…..
    🙂

  5. Buenas tardes necesito ayuda urgente con el jasperreport. Actualmente estoy trabajando en un proyecto en el género un reporte en pdf perfectamente desde java, pero por nuevo requerimiento este no reporte no debe ser visualizado si no debe ir directamente a la impresora.

    saludos y gracias de antemano

  6. Hola, bueno, primeramente me gustaría saber si estás trabajando en una aplicación de escritorio o en una aplicación web.

    Si es de escritorio, puedes revisar el ejemplo que viene en el proyecto de JasperReports, en la carpeta demo/printService. Este post en el foro de Jasper te puede ayudar.
    http://jasperforge.org/plugins/espforum/view.php?group_id=102&forumid=103&topicid=123

    Si es aplicación web, es muy difícil que se pueda, puesto que te mostraría el diálogo de la impresora que está en el servidor.

  7. Hola. Tengo un error hago lo mismo que esta explicado aca importo todo pero cuando lo ejecuto me da un error esto
    try{
    File templateFile = new File(“/org/jurgenramirez/taller/reportes/BitacoraEmpleado.jrxml”);

    JasperDesign dis = JRXmlLoader.load(templateFile);
    JasperReport rep = JasperCompileManager.compileReport(dis);
    JasperPrint imp = JasperFillManager.fillReport(rep, null, Conexion.getInstancia().getConexion());
    JasperViewer.viewReport(imp,false);
    }catch(JRException e){
    e.printStackTrace();
    }catch(NullPointerException e){
    e.printStackTrace();
    }
    El error me lo da en la siguiente linea de codigo JasperDesign dis = JRXmlLoader.load(templateFile);
    El error es el siguiente:
    java.lang.RuntimeException: java.lang.NoClassDefFoundError: org/apache/commons/digester/Digester

    at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:238)
    at com.sun.glass.ui.View.handleMouseEvent(View.java:493)
    at com.sun.glass.ui.View.notifyMouse(View.java:871)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.access$100(WinApplication.java:29)
    at com.sun.glass.ui.win.WinApplication$2$1.run(WinApplication.java:62)
    at java.lang.Thread.run(Unknown Source)
    Caused by: java.lang.NoClassDefFoundError: org/apache/commons/digester/Digester
    at org.jurgenramirez.taller.manejadores.Report.reporte(Report.java:22)
    at org.jurgenramirez.taller.iu.VentanaAdministrador.handle(VentanaAdministrador.java:240)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:69)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:217)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:170)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:38)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:37)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:53)
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:28)
    at javafx.event.Event.fireEvent(Event.java:171)
    at javafx.scene.Node.fireEvent(Node.java:5982)
    at javafx.scene.control.Button.fire(Button.java:179)
    at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:189)
    at com.sun.javafx.scene.control.skin.SkinBase$4.handle(SkinBase.java:336)
    at com.sun.javafx.scene.control.skin.SkinBase$4.handle(SkinBase.java:329)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:64)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:217)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:170)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:38)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:37)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:53)
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:33)
    at javafx.event.Event.fireEvent(Event.java:171)
    at javafx.scene.Scene$MouseHandler.process(Scene.java:2897)
    at javafx.scene.Scene$MouseHandler.process(Scene.java:2691)
    at javafx.scene.Scene$MouseHandler.access$1300(Scene.java:2657)
    at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1281)
    at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:1915)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:215)
    … 6 more
    Caused by: java.lang.ClassNotFoundException: org.apache.commons.digester.Digester
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    … 47 more
    He agregado todas las librerias a el claspath no se que pueda ser?

  8. Según el error que muestras, te falta la librería Digester (commons-digester-1.7.jar). Yo creo que tu problema es al ejecutar el programa, si está usando un IDE, tienes que configurarlo para que apunte a las librerías (en el ejemplo, las librerías están en la carpeta “lib”), sino fíjate en archivo de ant que viene con el ejemplo.

  9. Donde encuentro el archivo HelloWorldReport.jrxml porque al ejecutar el ejemplo 1 me dice que no encuentra ese archivo.

  10. Gracias por avisarme. Ya subí una versión corregida del ejemplo, pero si quieres una solución rápida, pues creas una carpeta “reports” en la raiz del proyecto, y le añades algún template de reporte de JasperReports sencillo.

  11. Hola, que tal!? Tengo un problemita y quizá puedan ayudarme. Estoy creando un pdf con un template con jasperreports. Pero lo que preciso es que a veces ese template se repita varias veces en el mismo documento pdf. Alguno sabe como hacer algo como esto?

  12. Si es un bloque que se repite por cada fila de datos, podrías ponerlo en la banda Detail como un subreporte.
    Si es un bloque que se repite con los mismos datos (por ejemplo una vez implementé un recibo de compra, que tenía que imprimirse dos veces en la hoja) pues puedes poner todo el contenido del template dos veces en (encerrado en un frame), o como antes, podrías usar un subreporte y copiar el mismo subreporte las veces que necesitas.

  13. En realidad puede repetirse n veces, por lo que voy a crear una clase para tener un listado, y que este se repita la cantidad de veces necesarias al igual que el template (img). Como bien decías voy a crearlo en el detail para ver si así funciona ok.
    Les comento como salio la prueba.
    Gracias por responder!

  14. Hola que tal, una consulta, tengo una aplicación de escritorio en java, y mando a imprimir un reporte sin que se visualice por pantalla, mi problema es que este reporte no ocupa toda la hoja solo la mitad y yo quiero que cuando termine de imprimir pueda imprimir en esa misma hoja el siguiente reporte, pero lo que hace actualmente la impresora es que cuando termina de imprimir da un salto de pagina , como puedo hacer para que imprima continuo y no vaya a la siguiente hoja?

  15. Hola alvaro, mi problema es similar al de ESPERANZA pero el link que dejaste esta caido crees que pudieras ayudarme

  16. Hola Irwin, mira el problema de Esperanza era que le faltaba añadir una librería para que se pueda compilar su reporte (jdt-compiler), a lo mejor tu caso es el mismo y te falta añadir una librería a tu proyecto. Saludos.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s