domingo, 8 de febrero de 2009

Creación de Reportes con JasperRepots y iReports - Parte 1: Reportes con Conexión a Base de Datos

En un post anterior hablé un poco de las ventajas que tenemos al crear reportes con el API JasperReports y la herramienta iReport.

Ahora veremos unos ejemplos de cómo usarlos en nuestras aplicaciones Java. Dividiré estos ejemplos en varios post dedicando cada uno a una forma muy particular de la creación de reportes.

Para estos ejemplos usaremos las últimas versiones de ambas herramientas (que en esta actualización son las 3.7.6)

Lo primero que haremos es bajar el JasperReports y iReport. Este último lo usaremos en su faceta de aplicación standalone y no como plugin para NetBeans. Esto por aquellos que nos les guste usar el NetBeans.

Como ya había dicho: La última versión de iReport está basada en la plataforma de NetBeans por lo que, como pueden observar en la imagen siguiente, las interfaces de ambos son muy parecidas.



En este primer post veremos cómo crear reportes haciendo uso de una conexión a la base de datos directamente desde nuestro reporte.

Lo primero que haremos es crear una base de datos con tablas y datos de pruebas para poder tener algo interesante que ver en nuestros reportes. En este caso usaré MySQL versión 5.1, el cual pueden descargar desde su página oficial. Usando el conector para Java versión 5.1.13 que pueden descargar desde la página de MySQL. Pero cualquier base de datos que les guste funcionará para nuestros ejemplos.

La base de datos que usaré se llama "pruebaReportes" y contiene la tabla "participantes". Este es el script para la creación de esta tabla:


CREATE TABLE 'participantes' (            
                'ID' bigint(21) NOT NULL,               
                'NOMBRE' varchar(100) NOT NULL,         
                'USERNAME' varchar(100) NOT NULL,       
                'PASSWORD' varchar(100) NOT NULL,       
                'COMENTARIOS' varchar(100) default NULL,
                PRIMARY KEY  ('ID')                     
              ) ENGINE=InnoDB DEFAULT CHARSET=latin1


Y este es el script para poblar la tabla anterior:


insert  into 'participantes'('ID','NOMBRE','USERNAME','PASSWORD','COMENTARIOS') values (1,'Participante 1','par1user','part1pass','comentarios participante 1');
insert  into 'participantes'('ID','NOMBRE','USERNAME','PASSWORD','COMENTARIOS') values (2,'Participante 2','par2user','part2pass','comentarios participante 2');
insert  into 'participantes'('ID','NOMBRE','USERNAME','PASSWORD','COMENTARIOS') values (3,'Participante 3','par3user','part3pass','comentarios participante 3');
insert  into 'participantes'('ID','NOMBRE','USERNAME','PASSWORD','COMENTARIOS') values (4,'Participante 4','par4user','part4pass','comentarios respecto al participante 4');
insert  into 'participantes'('ID','NOMBRE','USERNAME','PASSWORD','COMENTARIOS') values (5,'Participante 5','par5user','part5pass','sin comentarios para el participante 5');
insert  into 'participantes'('ID','NOMBRE','USERNAME','PASSWORD','COMENTARIOS') values (6,'Participante 6','par6user','part6pass',NULL);
insert  into 'participantes'('ID','NOMBRE','USERNAME','PASSWORD','COMENTARIOS') values (7,'Participante 7','par7user','part7pass','comentatios participante 7');
insert  into 'participantes'('ID','NOMBRE','USERNAME','PASSWORD','COMENTARIOS') values (8,'Participante 8','par8user','part8pass','comentarios participante 8');
insert  into 'participantes'('ID','NOMBRE','USERNAME','PASSWORD','COMENTARIOS') values (9,'Participante 9','par9user','part9pass','comentarios participante 9');
insert  into 'participantes'('ID','NOMBRE','USERNAME','PASSWORD','COMENTARIOS') values (10,'Participante 10','par10user','part10pass',NULL);


Ahora que tenemos nuestros datos crearemos un "datasource" en iReport para poder acceder a nuestros datos y hacer pruebas directamente, sin necesidad de una aplicación Java (por el momento). Para crear este datasource hacemos clic en el ícono "Report Datasources" ubicado en la barra de herramientas de iReport:



Con lo que se abrirá la ventana de "Connections / Datasources" que en este momento debe contener solo un "Empty datasource" y la conexión a una base de datos de prueba en HSQLDB. Ahora hacemos clic en el botón "New" para crear nuestro nuevo datasource.



En la nueva ventana que se abre seleccionamos "Database JDBC connection" y presionamos el botón "Next". En la siguiente ventana debemos proporcionar algunos datos como el nombre se le dará al datasource y los datos para realizar la conexión de la base de datos. Después de llenar estos datos su ventana debe haber quedado más o menos como la siguiente (recuerden usar el "JDBC Driver" que corresponda al manejador de base de datos que estén usando:



Antes de guardar esta configuración hagan clic en el botón "Test" para probar que todos los datos proporcionados son correctos. Si todo ha salido bien, al hacer clic en el botón "Save" la ventana actual debe cerrarse y nuestro datasource debe estar ahora en la ventana "Connections / Datasources".



Ahora pasaremos a crear nuestro nuevo reporte. Esta será la primer y única ocasión en la que haremos uso del "Report Wizard" para ayudarnos a generar el reporte. Para esto vamos al menú "File -> New...". Con esto se abrirá la ventana de "New File" en la que seleccionaremos el formato de nuestro reporte. En mi caso seleccionaré la plantilla "Wood" aunque pueden seleccionar la que ustedes deseen, y hacemos clic en el botón "Launch Report Wizard"



Este wizard nos ayudará a crear un reporte 100% funcional en 6 pasos (en realidad 5 ya que empezamos directamente en el paso 2) que podremos ver desde el mismo iReport sin necesidad de escribir una solo línea de código Java. Estos 7 pasos son:

  1. Selección de la ubicación en la que se guardará nuestro reporte.
  2. Selección del datasource e introducción del query para obtener los datos que nos interesan.
  3. Selección de los datos que queremos mostrar en el reporte.
  4. Creación de grupos para el reporte (se explicará en un post posterior).
  5. Selección del layout o acomodo de los datos en el reporte
  6. Felicitación por tenerminar nuestro reporte =D.

Los pasos interesantes son el 3 y el 4, así que será en estos en los que nos enfocaremos más.

El paso 1 se realiza de forma automática, así que no tenemos mucho que hacer en él. En el paso 2 (en donde comenzamos) seleccionamos el directorio en el que queremos guardar nuestro reporte y el nombre que tendrá.

Nota: La extensión de documentos de reportes generados por JasperReports es ".jrxml" que significa "jasper reports xml", y es un documento xml que contiene los datos para generar un archivo compilado (".jasper") que es el que usaremos principalmente en nuestras aplicaciones Java (aunque también podriamos optar por compilar nuestro archivo ".jrxml" desde la misma aplicación Java y así generar el archivo ".jasper" correspondiente).

En este momento no importa mucho en donde guardemos el archivo que se generará, ya que posteriormente tendremos que moverlo para que nuestra aplicación java pueda encontrarlo. Por mi parte llamaré al archivo "reporte1".

Hacemos clic en el botón "Next" para continuar con el paso 3. En este paso debemos seleccionar el datasource desde el que los datos del reporte serán tomados. Por default está seleccionado el "Empty datasource". Así que nosotros seleccionamos el datasource "Conexion MySQL Pruebas" (el datasource que creamos anteriormente).

Al hacer el cambio del datasource veremos que aparece un textarea con el título "Query(SQL)" y en la parte inferior debemos tener un mensaje de error que dice "Invalid query".



Esto ocurre porque, efectivamente, en el textarea no tenemos una consulta válida (de hecho no tenemos ninguna). Por lo que ahora corregiremos eso. Para esto tenemos 3 opciones:

  1. Escribir una consulta nosotros mismos de forma directa.
  2. Cargar una consulta que tengamos guardada en algún archivo .sql o .txt.
  3. Crear una consulta usando el "diseñador de consultas".

Nosotros haremos uso del diseñador de consultas. Hacemos clic en el botón "Design query" con lo que se abrirá una nueva ventana que está dividida en tres secciones.



La primer sección es la de la estructura de la consulta. Aquí básicamente podremos cambiar entre las sentencias que estamos editando (SELECT, WHERE, ORDER BY, etc.). La segunda sección es la de los elementos de nuestra base de datos (tablas, vistas, y temporales locales). Aquí podremos seleccionar los elementos de los que queremos obtener datos para la consulta. Finalmente la tercer sección nos muestra los elementos que hemos seleccionado de la segunda sección para que podamos seleccionar los datos a obtener.

La consulta que haremos será para obtener todos los datos de la tabla "participantes", con excepción del "ID". Para esto hacemos doble clic sobre el nombre de la tabla "participantes" en la segunda sección de la ventana que tenemos abierta. Con esto aparecerá en la tercer sección otra ventana con el título "participantes" y un conjunto de checkboxes, cada uno con un campo de nuestra tabla. Para generar la consulta que nos interesa solamente seleccionamos todos los checkboxes (con excepción del "ID") y veremos que la consulta se genera en la primer sección. Ya solo damos clic en el botón "OK".



Con esto ya tendremos nuestra consulta en el textarea correspondiente y podemos continuar con el paso 4, para lo que hacemos clic en el botón "Next".

En este paso solo tenemos que seleccionar cuáles campos del query generado en el paso anterior queremos que se muestren en el reporte. Como nosotros queremos que se muestren todos pasamos todos los campos del lado izquierdo al lado derecho y hacemos clic en el botón "Next".



Ahora en el paso 5 debemos seleccionar cómo queremos que los datos sean agrupados. Esto lo explicaré en algún otro post, pero por el momento dejemos todo en blanco y demos clic en el botón "Next".

El último paso es el solamente una felicitación por haber creado un nuevo reporte ^-^.



Ahora hacemos clic en el botón "Finish" y ya podremos ver la plantilla de nuestro reporte.



Si queremos ver como se verá el reporte final, en este caso, podemos ver un preview con los datos reales si cambiamos a la vista de "preview" en la ventana del editor.



Al hacer clic en la pestaña de "preview", nuestro reporte se compilará y se mostrará. En este caso el reporte puede ser pre-visualizado porque las siguientes condiciones se cumplen:

  • Tenemos una base de datos poblada (esto es muy importante, ya que si no tiene datos obtendremos un mensaje de error).
  • Tenemos un datasource configurado para esta base de datos.
  • Nuestro reporte hace una consulta directa a esta base de datos a través del datasource anterior.
  • El reporte está preparado para mostrar los datos recuperados anteriormente.

Como veremos en los siguientes posts, podría ser que no todas estas condiciones se cumplan al mismo tiempo, por lo que tendremos problemas para ver los datos en el preview del reporte.

Algo importante que ocurre al hacer este preview es que el reporte se compila generando el archivo "reporte1.jasper" el cual es el archivo que usaremos desde la aplicación Java que crearemos en un momento.

Si queremos compilar nuestro reporte de forma manual podemos hacer clic en el botón "Compile Report" de la vista de diseño:



Haremos algunas modificaciones para que este reporte se vea un poco mejor: primero cambiaremos el título que dice "Wood Title" por "Reporte de Participantes", cambiamos el color de texto a negro, y eliminamos el fondo y el subtitulo que tiene.

Además cambiamos el título de cada una de las columnas por algo más claro. Por ejemplo, podemos cambiar el título de la columna "participantes_USERNAME" a "Usuario", "participantes_NOMBRE" a "Nombre", etc.

Al final mi reporte queda de esta forma:



Con este preview:



Ahora que tenemos un reporte que nos agrada (o al menos que no se ve tan mal) veremos cómo generar este reporte desde una aplicación Java.

Nota: Hay algunas notaciones usadas en la plantilla del reporte que tal vez no comprendan como $F{participantes_USERNAME} y $V{PAGE_NUMBER}. Esta es una sintaxis especial que usa JasperReports para definir campos de objetos y variables, respectivamente. Existe otro tipo de dato que se usa llamado propiedades ($P{propiedad}). Como todo esto fue colocado por el wizard no lo explicaré hasta el siguiente post, por ahora solo confíen en que deben estar ahí.

Lo primero que haremos es crear un nuevo proyecto en NetBeans. Para esto vamos al menú "File -> new Project...". En la ventana de nuevos proyectos seleccionamos la categoría "Java" y de tipo de proyecto seleccionamos "Java Application" y hacemos clic en el botón "Next". En la siguiente ventana introducimos el nombre de nuestro proyecto y dejamos seleccionada la opción "Create Main Class" y "Set as Main Project".



Hacemos clic en el botón "Finish" para que nuestro proyecto se genere. Lo que haremos a continuación es crear una biblioteca que contenga los archivos jars básicos necesarios de JasperReports. De esta forma no tendremos que agregar cada uno de los jars cada vez que necesitemos usar JasperReports en un proyecto. Además si actualizamos la versión del API que usamos, solo debemos actualizar esta biblioteca.

Para crear nuestra biblioteca vamos al menú "Tools -> Libraries":



Con esto se abrirá la ventana del "Library Manager". En esta ventana hacemos clic en el botón "New Library":



En la ventana que se abre escribimos el nombre de la nueva biblioteca (en mi caso será "JasperReports") y en el tipo de la biblioteca seleccionamos la opción "Class Libraries".



Al hacer clic en el botón "OK" regresaremos al "Library Manager" y tendremos nuestra nueva biblioteca creada. Pero aún nos hace falta agregar los archivos jars que conformarán esta biblioteca. Nos aseguramos que la pestaña "Classpath" esté seleccionada y hacemos clic en el botón "Add Jar/Folder" situado a la derecha. Se abrirá un cuadro de dialogo para que seleccionemos los jars que queremos agregar.



Navegamos hasta el directorio en el que tenemos los jars de JasperReports que bajamos anteriormente. Para que los ejemplos que haremos más adelante (en los siguientes posts) funcionen, debemos agregar a la biblioteca los siguientes jars:

  • jasperreports-3.7.6.jar
  • jasperreports-3.7.6-javaflow.jar
  • jasperreports-fonts-3.7.6.jar
  • commons-beanutils-1.8.0.jar
  • commons-collections-2.1.1.jar
  • commons-digester-1.7.jar
  • commons-logging-1.0.4.jar
  • commons-javaflow-20060411.jar
  • groovy-all-1.7.5.jar
  • iText-2.1.7.jar
  • png-encoder-1.5.jar
  • poi-3.6.jar

Algunos de estos jars se encuentran en el directorio "dist" y otros en el directorio "lib" del archivo .zip de JasperRepots que bajamos anteriormente.

Hacemos clic en el botón "Add Jar/Folder" y con esto tendremos lista nuestra biblioteca "JasperReports" para agregarla a nuestro proyecto.



Hacemos clic en el botón "OK" para regresar al ambiente de trabajo.

Ahora hacemos clic derecho en el nodo "Libraries" de la ventana "Projects". Con esto se abrirá un menú contextual con 4 opciones, seleccionamos la opción "Add Library..."



En la ventana que se abre seleccionamos la biblioteca que creamos anteriormente ("JasperReports") y hacemos clic en el botón "Add Library". Al hacer esto veremos se agregar al nodo "Libraries" de nuestro proyecto todos los jars que tiene nuestra biblioteca.

Nota: Si no crearon la biblioteca como se indica en pasos anteriores pueden agregar cada uno de los jars manualmente seleccionando la opción "Add JAR/Folder..." del menú contextual



¿Recuerdan que cuando vimos el preview del reporte que creamos en iReports se generó un archivo "reporte1.jasper"? Tomamos este archivo y lo colocamos en el directorio raíz del proyecto de NetBeans que acabamos de crear (la raíz del proyecto es el directorio en el que se encuentran los subdirectorios "nbproject", "src", entre otros).



Ahora veremos el código para generar el reporte en varios formatos.

Lo primero es crear una conexión a la base de datos que creamos anteriormente. Si no saben cómo crear una conexión JDBC desde Java, pueden ver este artículo. Si recuerdan nuestra base de datos se llama "pruebareportes". Por lo que el código para generar la conexión en el siguiente:


Class.forName("com.mysql.jdbc.Driver"); 
Connection conexion = DriverManager.getConnection("jdbc:mysql://localhost:3306/pruebareportes", "usuario", "password");


Nota: No olviden agregar el jar del driver de MySQL que bajamos anteriormente (mysql-connector-java-5.1.13-bin.jar) al proyecto al nodo "Libraries" de la ventana "Project" usando la opción "Add JAR/Folder" o también pueden agregar la biblioteca "MySQL JDBC Driver" que ya trae incluido el NetBeans, de la misma forma que agregamos la de JasperReports.

Seguramente en este momento el NetBeans les está marcando un error en estas dos líneas que hemos agregado. Esto es porque al tratar de hacer la conexión es posible que ocurra un error, y por lo tanto es posible que se lance una excepción de tipo "java.sql.SQLException". Para solucionar esto pueden hacer dos cosas. La primera es rodear estas líneas (y las siguientes que crearemos) en una clausula try/catch. La segunda opción (la que yo usaré) es agregar la clausula throws Exception en el método main:


public static void main(String[] args) throws Exception
{
        Class.forName("com.mysql.jdbc.Driver");
        Connection conexion = DriverManager.getConnection("jdbc:mysql://localhost:3306/pruebareportes", "root", "123");
}


Pueden probar que la conexión se realiza correctamente presionando F6 o haciendo clic en el botón "Run Main Project". Si la conexión se realiza correctamente veremos el mensaje


run: 
BUILD SUCCESSFUL (total time: 0 second)


En la ventana "Output". De lo contrario verán el error el en stacktrace de la excepción que se lanzó. Una vez que la conexión se realice exitosamente podremos proseguir con los pasos restantes.

Lo siguiente que debemos hacer es cargar el archivo ".jasper" generado anteriormente y colocarlo en un objeto "net.sf.jasperreports.engine.JasperReport". Para esto hacemos uso de la clase de utilidad "net.sf.jasperreports.engine.util.JRLoader":


JasperReport reporte = (JasperReport) JRLoader.loadObject("reporte1.jasper");


Nota: Podemos cargar el archivo de esta forma gracias a que colocamos el archivo "reporte1.jasper" en la raíz del proyecto. Si lo colocaron en otra ubicación será necesario que pasen como parámetro al método "loadObject" la url absoluta en la que se encuentré el archivo.

Ahora el objeto "reporte" contiene la definición del reporte, pero aún hace falta que llenemos este reporte con los datos que obtendrá de la base de datos. Para esto usamos la clase "net.sf.jasperreports.engine.JasperFillManager". Esta clase tiene un método estático, "fillReport", que nos permite llenar el reporte con datos obtenidos de distintas fuentes de datos (una de estas fuentes es la sentencia SQL que escribimos al generar el reporte con el wizard en iReports y la conexión que usaremos en un momento, veremos qué otras fuentes de datos existen y cómo usarlos en los siguientes posts). En este caso la fuente de datos es la conexión directa a la base de datos que creamos anteriormente (el objeto conexion):


JasperPrint jasperPrint = JasperFillManager.fillReport(reporte, null, conexion);


Pasamos "null" como segundo parámetro porque no estamos pasando ningún parámetro al reporte (esto también lo veremos después).

El objeto "JasperPrint" que obtenemos como resultado de la invocación del método "fillReport" es la representación de nuestro reporte (ahora con datos) que podemos mandar a imprimir, mostrar en pantalla (si estamos usando una aplicación swing o awt), o, como en este caso, guardarlo en un archivo.

Si están haciendo una aplicación swing y quieren mostrar este reporte directamente en un componente pueden pasar el objeto "JasperPrint" que acabamos de crear como parámetro a un nuevo objeto "net.sf.jasperreports.view.JasperViewer", el cual es un componente swing, y agregar este último a un panel.

Para guardar este reporte a un archivo debemos usar un "net.sf.jasperreports.engine.JRExporter". "net.sf.jasperreports.engine.JRExporter" es una interface, y las clases que la implementan nos permiten generar el reporte en distintos formatos de una forma sencilla. Veremos cómo generar los reportes en los siguientes formatos:

  • PDF
  • HTML
  • CSV
  • RTF
  • TXT
  • XLS
  • XML
  • XLSX
  • DOCX
  • PPTX

Entre muchos otros.

Primero declaramos una referencia a un objeto de tipo "JRExporter" de la siguiente forma:

JRExporter exporter = 


Será esta referencia la que usaremos de ahora en adelante. Para que nuestro reporte sea guardado en formato PDF creamos un objeto de tipo "net.sf.jasperreports.engine.export.JRPdfExporter" y lo asignamos a nuestra referencia exporter:


JRExporter exporter = new JRPdfExporter();


Ahora, las siguientes líneas son comunes no importando el formato en el que vaya a quedar nuestro reporte:


exporter.setParameter(JRExporterParameter.JASPER_PRINT,jasperPrint); 
exporter.setParameter(JRExporterParameter.OUTPUT_FILE,new java.io.File("reportePDF.pdf"));
exporter.exportReport();
La primer línea asigna a nuestro objeto "exporter" el "jasperPrint" (el reporte con datos) que creamos anteriormente. La segunda línea le dice al "exporter" cuál será el nombre del archivo generado (en este caso "reportePDF.pdf"). Recuerden cambiar el nombre y la extensión del archivo cada vez que cambiemos de formato.

La última línea es la que realiza el proceso de exportación.

Si ahora ejecutamos nuestra aplicación veremos que en el directorio raíz del proyecto se ha creado un archivo llamado "reportePDF.pdf":



Con el siguiente contenido:



Por lo que nuestra prueba ha sido exitosa ^-^.

Ahora, para que nuestro reporte sea exportado a formato HTML cambiamos la línea:


JRExporter exporter = new JRPdfExporter();


por


JRExporter exporter = new JRHtmlExporter();


y el nombre del archivo de "reportePDF.pdf" a "reporteHTML.html". Al ejecutar nuevamente nuestra aplicación tendremos veremos que se genera el archivo "reporteHTML.html" en el directorio raíz de la aplicación:



Con el siguiente contenido:



Como pudimos ver, con un par de modificaciones pudimos hacer que nuestro reporte se generara en un formato completamente distinto. Con el resto de los formatos es igual de simple. Usamos las siguientes clases para generar los reportes en los siguientes formatos:

  • PDF: net.sf.jasperreports.engine.exportJRPdfExporter
  • HTML: net.sf.jasperreports.engine.exportJRHtmlExporter
  • CSV: net.sf.jasperreports.engine.exportJRCsvExporter
  • RTF: net.sf.jasperreports.engine.exportJRRtfExporter
  • XLS: net.sf.jasperreports.engine.exportJRXlsExporter
  • XML: net.sf.jasperreports.engine.exportJRXmlExporter
  • TXT: net.sf.jasperreports.engine.exportJRTextExporter
  • XLSX: net.sf.jasperreports.engine.export.ooxml.JRXlsxExporter
  • DOCX: net.sf.jasperreports.engine.export.ooxml.JRDocxExporter
  • PPTX: net.sf.jasperreports.engine.export.ooxml.JRPptxExporter

Entre muchos otros ^_^

Para generar archivos .txt tendrán que agregar, además, estas dos líneas:


exporter.setParameter(JRTextExporterParameter.CHARACTER_WIDTH, 12);//text exporter
exporter.setParameter(JRTextExporterParameter.CHARACTER_HEIGHT, 12);//text exporter


Este es el código de la clase "Main":


public class Main
{
    /**
     * @param args argumentos recibidos por la linea de comandos
     */
    public static void main(String[] args) throws Exception
    {
        Class.forName("com.mysql.jdbc.Driver");
        Connection conexion = DriverManager.getConnection("jdbc:mysql://localhost:3306/pruebareportes", "usuario", "password");

        JasperReport reporte = (JasperReport) JRLoader.loadObject("reporte1.jasper");
        JasperPrint jasperPrint = JasperFillManager.fillReport(reporte, null, conexion);

        JRExporter exporter = new JRPdfExporter();
        
        exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
        exporter.setParameter(JRExporterParameter.OUTPUT_FILE, new java.io.File("reportePDF.pdf"));
        exporter.exportReport();
    }
}


Espero que este post, aunque algo largo, les sea de mucha utilidad. El los post siguientes ampliaré un poco la forma en la que es posible trabajar con JasperRepots.

No olviden dejar sus dudas, comentarios y sugerencias.

Saludos.

Descarga los archivos de este tutorial desde aquí:

Entradas Relacionadas:

64 comentarios:

  1. Locazo man, gracias por esta informacion.
    Ojala hubiera mas gente con ganas de enseñar...
    Sabes tengo una duda, necesito crear un reporte de cronograma de pagos, los unicos parametros enviados al reporte son el Monto de desembolso, la tasa de interes y el periodo. En mi aplicacion Swing esto lo genero con un for, pero no se como hacerlo en el ireport.

    Agradeceria cualquier ayuda de antemano.

    ResponderEliminar
  2. muy buena la ayuda, pero tuve un problema al seguir tu secuencia, cree el reporte y todo corre perfecto, pero el netbeans no lo abre, me sale un error en esta linea

    JasperReport reporte = (JasperReport) JRLoader.loadObject("reporte1.jasper");

    si me podrias ayudar a saber maso a q se debe porfa

    ResponderEliminar
  3. Claro que si, pero ¿podrías darme más información sobre el error que te da?. ¿No encuentra el archivo o algo así?. Si este es el caso, debes revisar en qué directorio estas colocandolo. Debe estar a la misma altura que el directorio src, nbproject, test, build.xml, etc.

    Si está en ese directorio y aún así te da el error, prueba colocando la ruta completa al archivo. Por ejemplo: "C:\Pruebas\JasperReports\reporte1.jasper".

    Espero que esto resuelva tu problema, sino no te preocupes, yo te ayudo hasta que quede resuelto.

    Saludos.

    ResponderEliminar
  4. amigo necesita algo de ayuda esta excelente tu tutorial de verdad tenia rato buscando esto, ahora me da un error mi codigo y es este
    Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at net.sf.jasperreports.engine.JRPropertiesMap.readObject(JRPropertiesMap.java:185)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.j

    por favor en lo que me puedas ayudar te agradezco

    ResponderEliminar
  5. Claro. El error es poco descriptivo. Hay algo que no se está instanciando. ¿Podrías decirme en qué línea te da el error?, o ¿puedes publicar tu código en algún lado?

    ResponderEliminar
  6. WOW No tengo palabras para describir lo excelente que está este tutorial. Muchisimas gracias. Pero tengo unas cuantas dudas espero que me puedas ayudar. Estoy haciendo una aplicación Web con java y mysql, en Java tengo mis JSP, Beans, Servlets y clases aparte donde tengo mis métodos de consulta, lo describo porque no se que se necesite, mi pregunta es si se maneja esto de forma diferente por ser aplicación web, si es así me podrías decir en que cambia o como podría hacer para que estos reportes se muestren en los jsp e imprimir desde ahí
    Y otra vez mil gracias tiene como tres semanas que busco algo así para mi trabajo

    ResponderEliminar
  7. Hola, antes que nada muchas gracias. Que bueno que esto te ha servido.

    Respondiendo a tu pregunta: en este otro tutorial puedes encontrar cómo llenar un reporte sin necesidad de una conexión a base de datos, por si te puede servir

    http://javatutoriales.blogspot.com/2009/03/creacion-de-reportes-con-jasperrepots-y.html

    y en este, puedes encontrar cómo hacerlo usando Servlets:

    http://javatutoriales.blogspot.com/2009/04/creacion-de-reportes-con-jasperrepots-y.html

    Y bueno, solo siguiendo las reglas de un buen diseño, te recomiendo que lo separes en capas, que tengas una capa para tu acceso a datos (DAOS), tal vez una capa de servicios, que mande llamar a estos DAOs y, finalmente, que este servicio lo mandes llamar desde tu Servlet.

    Espero que sea lo que estas buscando.

    Saludos.

    ResponderEliminar
  8. Muchas gracias por las soluciones y por las recomendaciones, de hecho tengo daos donde tengo mis métodos y los llamo desde el servlet pero siempre que le pregunto a alguien como hacer algo de esta aplicacion le digo que tengo mis daos y me preguntan que es eso, pero bueno fuera de esto se ve que sabes mucho de esto y yo soy principiante, me encargaron una aplicacion en la cual el login debe revisar que se encuentre el usuario y la contraseña en la BD y tambien debe validar que nivel de usuario tiene para ver a cuales paginas puede accesar tendrias algun ejemplo o algo asi de como debe ir el metodo en el dao? Por cierto no se si estuvo mal puesta la pregunta aquí ya que este tutorial es de ireports si me equivoqué me podrías decir cual es la forma correcta? Gracias

    ResponderEliminar
  9. Hola, de nada, es un placer ayudar.

    Mira con respecto a lo de las preguntas, pues creo que si están mal puestas aqui, pero bueno, en realidad no hay otro lugar en las que la puedas poner, así que creo que por el momento puedes seguir poniendolas aquí.

    Y con respecto a lo otro lo más fácil es, aunque suene redundante, lo hagas lo más simple posible. Me explico:

    Si tus usuarios van a tener un rol o un nivel de usuario, este nivel debe estar almancenado en la base de datos en una tabla USUARIOS. Esta tabla además de este nivel debería tener, entre otros datos importantes para el negocio, el nombre de usuario (USERNAME) y la contraseña (PASSWORD). Además deberías tener una clase Java que refleje estos mismos datos como atributos, y con sus respectivos setters y getters. Bien esto es el modelo de negocio.

    Ahora, si lo que te interesa recuperar desde tus DAOs es presisamente este usuario (para poder revisar su nivel) en base a su nombre de usuario y contraseña, el método de tu DAO puede ser más o menos así:

    class UsuariosDAO
    {
    public Usuario buscaUsuario(String Username, String password) tthrows ExcepcionDeBaseDeDatos
    {
    //Tu implementación va aqui
    }
    }

    Donde si el usuario existe (el nombre de usuario y la contraseña se encuentran en la base de datos y son válidos) recuperas el usuario correspondiente y puedes hacer algo así para verificar su nivel:

    UsuariosDAO().buscaUsuario().getNivel();

    y en caso de que se encuentre el usuario, regrese un null, con lo cual sabras que el usuario no existe.

    Claro, puedes poner más validaciones para saber cuál fue el error, como que el nombre de usuario no existe. O que el nombre de usuario si existe pera la contraseña es incorrecta. Y puedes regresar el error en forma de excepción, o lo que se te ocurra.

    Bueno, espero que esto te ayude con lo que estas haciendo.

    Saludos.

    ResponderEliminar
  10. Te felicito! Por fin un tutorial de Jasper Reports como la gente!!

    ResponderEliminar
  11. Con respecto a la nota de como compilar el template podes usar esto:

    File reportFile = new File(template.jrxml);
    JasperDesign design = JRXmlLoader.load(reportFile);
    JasperReport report = JasperCompileManager.compileReport(design);

    El template con iReport se guarda como un .jrxml, despues con este código obtenes el jrxml compilado.

    Saludos

    ResponderEliminar
  12. Hola buen dia;
    Te felicito por tu excelente tutorial, tengo un error en mi aplicacion en estas lineas:


    JRExporter exporter= new JRPdfExporter(); este es el error "Exception in thread "main" java.lang.NoClassDefFoundError: com/lowagie/text/pdf/FontMapper"

    ResponderEliminar
  13. Hola, gracias por las felicitaciones.

    En cuanto al error que te sale, esa clase (com/lowagie/text/pdf/FontMapper) se encuentra en el jar iText-2.1.0.jar. Debe ser que falta que incluyas el jar en el classpath de tu proyecto.

    Saludos

    ResponderEliminar
  14. hola buen dia;
    jajajaj ya se que paso XD esque nocarge algunas librerias.... jajajja error de noob.

    Eso pasa por no leer y correr antes de gatear :)
    Griacias por tu tutorial :)
    Miguel.

    ResponderEliminar
  15. Hola buenas noches, excelente tuto estaba buscando uno asi tan bueno. muchas gracias por el esfuerzo

    Solo me pasa algo , tengo el siguiente error :
    Podrias por favor ayudarme...
    de antemano gracias.

    Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at net.sf.jasperreports.engine.JRPropertiesMap.readObject(JRPropertiesMap.java:185)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

    ResponderEliminar
  16. Hola. Antes que otra cosa muchas gracias.

    En cuanto al error, podrías subir tu código a algún lado para que lo revise?. Se me ocurre que el error está en el reporte (en la parte de iReport) y no tanto en el código de Java, no te falta algun field o algo por el estilo?.

    Saludos.

    ResponderEliminar
  17. Gracias por tu rapida respuesta, que codigo te subo y donde lo podria subir?

    ResponderEliminar
  18. Sube todo tu proyecto (archivos.java y archivos.jrxml). Si puedes subelo a algun lugar como rapidsare o uploading.com

    También si estas usando una base de datos, los scripts para crear las tablas y llenarlas (en caso de que sean distntos a los que puse aqui).

    Saludos

    ResponderEliminar
  19. Una pregunta, este codigo me exporta mi reporte y luego debo buscar el archivo generado para visualizarlo?

    Gracias..

    ResponderEliminar
  20. Si, el código genera el reporte en el archivo que le pasas como parámetro en la línea

    exporter.setParameter(JRExporterParameter.OUTPUT_FILE, new java.io.File("reportePDF.pdf"));

    Esto lo que hace es que genera el reporte en formato pdf en el mismo directorio en el que está tu archivo.jasper, no abre una ventana para que lo veas ni nada por el estilo, para eso tendrías que estar haciendo una aplicación swing y usar un componetne llamado JasperViewer. Pero en este caso hay que buscar y abrir el archivo a manita.

    ResponderEliminar
  21. Es que es lo que necesito , mi aplicacion es swing y lo que necesito es abrirlo asi, podrias darme una manito, explicando como hacerlo?

    Muchas gracias por tu tieempo y paciencia.

    ResponderEliminar
  22. Ok, entonces el cambio que debes hacer no es muy grande. De hecho ya debes tener la mayor parte. Casi todos los pasos son iguales, con excepción de que si vas a mostrar el reporte en swing, ya no necesitas un JRExporter, ni exportar el reporte.

    Lo que tienes que hacer es eliminar las líneas que dicen:

    JRExporter exporter = new JRPdfExporter();

    exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);

    exporter.setParameter(JRExporterParameter.OUTPUT_FILE, new java.io.File("reportePDF.pdf"));

    exporter.exportReport();

    y reemplazarlas por estas otras:

    JasperViewer jviewer = new JasperViewer(jasperPrint,false);

    jviewer.viewReport(jasperPrint);

    Como JasperViewer extiende de JFrame se muestra en su propia ventana, entonces el código completo del main queda así (perdon por el formato):

    public static void main(String[] args) throws Exception
    {
    Class.forName("com.mysql.jdbc.Driver");
    Connection conexion = DriverManager.getConnection("jdbc:mysql://localhost:3306/pruebareportes", "user", "pass");

    JasperReport reporte = (JasperReport) JRLoader.loadObject("reporte1.jasper");

    JasperPrint jasperPrint = JasperFillManager.fillReport(reporte, null, conexion);

    JasperViewer jviewer = new JasperViewer(jasperPrint,false);
    jviewer.viewReport(jasperPrint);
    }

    y eso es todo =D.

    Espero que sea lo que estas buscando, sino no dudes en seguirme preguntando

    Saludos

    ResponderEliminar
  23. OK muchisimas gracias, voy a probarlo y te cuento . . .

    ResponderEliminar
  24. Hola;
    Disculpa yo enves de usar el List como almacenador de datos use un Vector(v), ahora este vector contiene la info proveniente de una consulta mysql, el error lo tengo al momento de esta linea que me marca nulltype, esta es la linea

    JasperPrint jasperPrint = JasperFillManager.fillReport(reporte, null, v);

    v y v1 son vectores, v el vector donde almaceno info y de esta manera lo cargo:
    While(rs.next());{
    v1.addElement(rs.getString("numerodeparte"));
    v1.addElement(rs.getString("cantidad"));
    v1.addElement(rs.getString("fecha"));
    v1.addElement(rs.getString("recibo"));
    v.add(v1);
    }

    quiero decirte que aun no creo la clase JRDatasource que tu creas en el tutorial que aqui se encargaria de ir al getFieldValue.

    Mi pregunta esta mal la manera de cargar la informacion o necesito usar un List ??


    Gracias.
    Miguel.

    ResponderEliminar
  25. hola;
    Teadjunto el codigo todo lo ago en una sola clase jejej, bueno espero que le entiendas XD

    public class reporte
    {
    Vector v,v1;
    JFrame jf;
    JTextField jtf,jtf1,jtf2,jtf3,jtf4,jtf5;
    JButton btn;

    public reporte()
    {
    }

    public static void main(String[] args)
    {
    reporte rep=new reporte();
    rep.visual();
    rep.datos();
    rep.cargardatosareporte();
    }

    private void datos()
    {
    try {
    Class.forName("com.mysql.jdbc.Driver");
    Connection cn=null;
    Statement st;
    cn=DriverManager.getConnection("jdbc:mysql://localhost/pop","root","carolina");
    st=cn.createStatement();
    ResultSet rs= st.executeQuery("select * from recibo where numerodeparte=212121");
    v=new Vector();
    v1=new Vector();
    while(rs.next())
    {
    v1.addElement(rs.getString("numerodeparte"));
    v1.addElement(rs.getString("cantidad"));
    v1.addElement(rs.getString("fecha"));
    v1.addElement(rs.getString("recibo"));
    jtf.setText(rs.getString("numerodeparte"));
    v.add(v1);
    }
    } catch (SQLException ex) {
    Logger.getLogger(reporte.class.getName()).log(Level.SEVERE, null, ex);
    } catch (ClassNotFoundException ex) {
    Logger.getLogger(reporte.class.getName()).log(Level.SEVERE, null, ex);
    }
    }
    private void visual()
    {
    jf=new JFrame("Tabla"); //creamos la Frame para ser visual
    jf.setBounds(200,200, 515,380);
    jf.getContentPane().setLayout(null);

    jtf=new JTextField(" ");
    jtf.setBounds(1,140,130,20);

    jtf1=new JTextField(" ");
    jtf1.setBounds(1,175,130,20);

    jtf2=new JTextField(" ");
    jtf2.setBounds(1,210,130,20);

    jtf3=new JTextField(" ");
    jtf3.setBounds(1,245,130,20);

    jtf4=new JTextField(" ");
    jtf4.setBounds(1,280,130,20);

    jtf5=new JTextField(" ");
    jtf5.setBounds(1,315,130,20);

    btn=new JButton("Salir");
    btn.setBounds(350,285,110,25);
    btn.addActionListener(new boton()); //EL evento del raton

    jf.getContentPane().add(jtf);
    jf.getContentPane().add(jtf1);
    jf.getContentPane().add(jtf2);
    jf.getContentPane().add(jtf3);
    jf.getContentPane().add(jtf4);
    jf.getContentPane().add(jtf5);
    jf.getContentPane().add(btn);
    jf.setVisible(true);
    }
    private void cargardatosareporte() //cargamos el reporte y le damos datos
    {
    JasperReport reporte = (JasperReport) JRLoader.loadObject("C:/Users/CORORO/reporte.jasper");
    JasperPrint jasperPrint = JasperFillManager.fillReport(reporte, null, v);
    JRExporter exporter = new JRPdfExporter();
    exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
    exporter.setParameter(JRExporterParameter.OUTPUT_FILE, new java.io.File("reportePDF.pdf"));
    exporter.exportReport();
    }

    private class boton implements ActionListener //controlador evento raton
    {

    public void actionPerformed(ActionEvent e)
    {
    if(e.getSource()==btn)
    {
    System.exit(0);
    }
    }

    }
    }

    Gracias.
    Miguel.

    ResponderEliminar
  26. Ok, creo que el problema está en estas dos líneas:

    v.add(v1);

    y

    JasperPrint jasperPrint = JasperFillManager.fillReport(reporte, null, v);

    estas pasando como DataSource un vector lleno de vectores, entonces en el reporte tendrias que volver a sacar los datos de cada uno de los vectores (lo cual no creo que sea tan sencillo).

    En realidad lo que tendrías que hacer en esta parte:

    while(rs.next())
    {
    v1.addElement(rs.getString("numerodeparte"));
    v1.addElement(rs.getString("cantidad"));
    v1.addElement(rs.getString("fecha"));
    v1.addElement(rs.getString("recibo"));
    jtf.setText(rs.getString("numerodeparte"));
    v.add(v1);
    }

    es, en vez de llenar un Vector v1 es crear una clase, Factura (o algo así, depende de lo que estes haciendo) y llenarlo de esta forma:


    while(rs.next())
    {
    Factura f = new Factura();

    f.setNumeroDeParte(rs.getString("numerodeparte"));
    f.setCantidad(rs.getString("cantidad"));
    f.setFecha(rs.getString("fecha"));
    f.serRecibo(rs.getString("recibo"));
    v.add(f);
    }

    el problema está en esta parte.

    Saludos

    ResponderEliminar
  27. hola;
    Si mira lo que deceo es cargar informacion provista desde una base de datos y mostrarla en el reporte, es algo como lo que tu isiste pero lo tuyo son valores fijos yo lo deceo hacer variable, pero segun veo lo que me pusiste segun yo va acrear lo mismo no ?? vaa crear un "v" lleno de vectores [1,2,3,4],[a,s,d,f],..., y colocandolo en la lina del error me dara lo mismo lo que necesito colocar en esa zona es un objeto JRDatasource y en v colocar la info cokmo tu con la variable List.

    Por que vi tu aplicacion y el parametro "p" es la que tiene el vector unitario seva a lista participantes y agega dicho vector cuando tu aplicacion llega a 10 tiene 10 vectores o listas, lo que haces en getfieldvalue es buscarlos por indice con indice participanteactual, y yo lo que ise en la linea

    JasperPrint jasperPrint = JasperFillManager.fillReport(reporte, null, v);

    colocar el vector con toda la info, ahora lo que are es crear la clase y cargar un objeto"b" en ves de el "v" que te coloque haber si asi jununcia jajaja.

    Esque sabes me confunde mucho eso de los setter y getters es algo muy avanzado para mi jajaja yo soy krilin y to goku y pus como XD jajjaa
    voy a intentarle de esa manera.

    Gracias.
    Miguel.

    ResponderEliminar
  28. Hola.

    Bueno en realidad estamos haciendo cosas similares. Yo estoy pasando un Vector (List) lleno de Objetos, y estos objetos están llenos con los valores que se mostrarán en el reporte.

    Lo que tu estás haciendo es pasar una Vector lleno de Vectores.

    Entonces cuando trato de obtener los datos de un objeto dolo tengo que hacer lista.getObjeto(indice1).objeto.ObtenValor();

    tu tendrás que hacer algo como:

    vector1.getObjeto(indice1).getObjeto(indice2).getObjeto(0);

    o algo similar.

    Puedes probar debuggeando tu código, y ver lo que pasa cuando entres al método getFieldValue y ver lo que te digo.

    Saludos

    ResponderEliminar
  29. Hola;
    Te agradesco mucho tu ayuda fuiste muy paciente y te interesaste en resolver la duda.
    si tienes razon es relativamente lo mismo, ya le modifique en esto
    insertardatos p=new insertardatos();

    De esta manera leo los registros, tube que debugear mucho par ver que pasaba, y tienes razon el Vector tiene ensi varios vectores en el dependiendo de la consulta sql. Con esto monitoreo eso:

    v1= (Vector) v.get(indice);
    Object pop1= v1.elementAt(0);
    valor=pop1;

    talves notes que pueda generar error esta linea mas adelante

    int indice=-1; y return ++indice'<'v.size();

    lo ise por que al leer como tiene 2 registros e inicia en 1 el indice por el ++ pues tuve que decrementarlo para que empezara desde cero se supone que deve ser 0 y 1 osea 2 registros pero como empieza en 1 al incrementar como que se amenza el programa o no se pero tube que hacer eso por qu delo contrario solo asia una pasada en ves de hacer 2, pero eso es cuestion de debugearlo, esque ya tengo mucho con esto y yame canse jajajajajajajajja.

    Aqui les dejo el codigo completo por si alguien le pudiera servir.

    quiten las '' las puse por que marcaba error al subir el codigo.
    return ++indice'<'v.size();

    El acerlo visual talves no tenia motivos para el ejemplo, lo que pasa esque sobre esto voy a generar una aplicacion por eso genere los textfields y el boton, nomas quiten el metodo Visual si les causa ruido el codigo.
    public class reporte
    {
    insertardatos p=new insertardatos();
    Vector v,v1,v2;
    JFrame jf;
    JTextField jtf,jtf1,jtf2,jtf3,jtf4,jtf5;
    JButton btn;

    public reporte()
    {
    }

    public static void main(String[] args)
    {
    reporte rep=new reporte();
    rep.visual();
    rep.datos();
    rep.cargarreporte();
    }

    private void datos()
    {
    try {
    Class.forName("com.mysql.jdbc.Driver");
    Connection cn=null;
    Statement st;
    cn=DriverManager.getConnection("jdbc:mysql://localhost/pop","root","carolina");
    st=cn.createStatement();
    ResultSet rs= st.executeQuery("select * from recibo where numerodeparte=212121");
    v=new Vector();

    while(rs.next())
    {
    v1=new Vector();
    v1.addElement(rs.getString("numerodeparte"));
    v1.addElement(rs.getString("cantidad"));
    v1.addElement(rs.getString("fecha"));
    v1.addElement(rs.getString("recibo"));
    jtf.setText(rs.getString("numerodeparte"));
    v.add(v1);
    }
    } catch (SQLException ex) {
    Logger.getLogger(reporte.class.getName()).log(Level.SEVERE, null, ex);
    } catch (ClassNotFoundException ex) {
    Logger.getLogger(reporte.class.getName()).log(Level.SEVERE, null, ex);
    }
    }
    private void visual()
    {
    jf=new JFrame("Tabla"); //creamos la Frame para ser visual
    jf.setBounds(200,200, 515,380);
    jf.getContentPane().setLayout(null);

    jtf=new JTextField(" ");
    jtf.setBounds(1,140,130,20);

    jtf1=new JTextField(" ");
    jtf1.setBounds(1,175,130,20);

    jtf2=new JTextField(" ");
    jtf2.setBounds(1,210,130,20);

    jtf3=new JTextField(" ");
    jtf3.setBounds(1,245,130,20);

    jtf4=new JTextField(" ");
    jtf4.setBounds(1,280,130,20);

    jtf5=new JTextField(" ");
    jtf5.setBounds(1,315,130,20);

    btn=new JButton("Salir");
    btn.setBounds(350,285,110,25);
    btn.addActionListener(new boton()); //EL evento del raton

    jf.getContentPane().add(jtf);
    jf.getContentPane().add(jtf1);
    jf.getContentPane().add(jtf2);
    jf.getContentPane().add(jtf3);
    jf.getContentPane().add(jtf4);
    jf.getContentPane().add(jtf5);
    jf.getContentPane().add(btn);
    jf.setVisible(true);
    }
    private void cargarreporte() //cargamos el reporte y le damos datos
    {
    try {
    JasperReport reporte = (JasperReport) JRLoader.loadObject("C:/Users/CORORO/text.jasper");
    JasperPrint jasperPrint = JasperFillManager.fillReport(reporte, null, p);
    JRExporter exporter = new JRPdfExporter();
    exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
    exporter.setParameter(JRExporterParameter.OUTPUT_FILE, new java.io.File("textpdf.pdf"));
    exporter.exportReport();
    } catch (JRException ex) {
    Logger.getLogger(reporte.class.getName()).log(Level.SEVERE, null, ex);
    }
    }

    private class boton implements ActionListener //controlador evento raton
    {

    public void actionPerformed(ActionEvent e)
    {
    if(e.getSource()==btn)
    {
    System.exit(0);
    }
    }

    }

    private class insertardatos implements JRDataSource
    {
    int indice=-1;

    public insertardatos()
    {

    }


    public boolean next() throws JRException
    {

    return ++indice'<'v.size();

    }

    public Object getFieldValue(JRField arg0) throws JRException
    {
    Object valor = null;
    v1=new Vector();

    if("Nombre".equals(arg0.getName()))
    {

    v1= (Vector) v.get(indice);
    Object pop1= v1.elementAt(0);
    valor=pop1;
    }
    else if("Usuario".equals(arg0.getName()))
    {
    v1= (Vector) v.get(indice);
    Object pop1= v1.elementAt(1);
    valor=pop1;

    }
    else if("Contrasena".equals(arg0.getName()))
    {
    v1= (Vector) v.get(indice);
    Object pop1= v1.elementAt(2);
    valor=pop1;
    }
    else if("Comentarios".equals(arg0.getName()))
    {
    v1= (Vector) v.get(indice);
    Object pop1= v1.elementAt(3);
    valor=pop1;
    }
    return valor;
    }

    }
    }


    Gracias.
    Miguel.

    ResponderEliminar
  30. Por nada Miguel, es un plecer poder ayudar.

    Que bueno que finalmente funciono ^-^.

    Saludos

    ResponderEliminar
  31. Hola Alex buenas noches, otra vez yo sigo con problemas, ya detecte la linea a la cual salta el error y no se me genera la impresion del reporte es esta :

    JasperReport reporte = (JasperReport) JRLoader.loadObject("reporte1.jasper");

    es como si llegara null

    Te agradezco tu colaboracion . . .

    ResponderEliminar
  32. Hola.

    Te has fijado en la salida a ver si te da algún error?.

    Puede ser que llegue null porque no encuentre el archivo. Esto puede ser por dos motivos. El primero es que el nombre esté mal escrito. El segundo puede ser que no esté encontrado el archivo en la ruta especificada.

    Si es la segunda razón puedes pasar la ruta completa en la que se encuentra el archivo .jasper

    JasperReport reporte = (JasperReport) JRLoader.loadObject("C:\...\reporte1.jasper");

    Espero que esto te ayude, saludos.

    ResponderEliminar
  33. Pues te cuento que hize la prueba alterando el nombre del reporte y lo valide

    if (reporte == null)
    {

    System.out.println("No encuentro el archivo del reporte maestro.");
    System.exit(2);
    }

    Y me arroja el error de que no encuentra el archivo, lo que significa que con el nombre real "reporte1.jsp" si lo esta encontrando

    te paso todo el codigo el cual lo modifique par a las validaciones

    try
    {

    String ruta= "D:\\WILSON\\APLICACIONES DE ESCRITORIO CON JAVA\\Poyecto MOD\\Mod\\reporte2.jasper";


    if (ruta == null)
    {
    System.out.println("paso1");
    System.out.println("No se ubica el archivo del reporte .");
    System.exit(2);
    }

    JasperReport masterReport = null;
    System.out.println("paso2");
    try
    {
    System.out.println("paso3");
    masterReport = (JasperReport) JRLoader.loadObject(ruta);
    System.out.println("paso4");
    }
    catch (JRException e)
    {
    System.out.println("paso5");
    System.out.println("Error cargando el reporte : " + e.getMessage());
    System.exit(3);
    }


    System.out.println("paso6");


    JasperPrint jasperPrint = JasperFillManager.fillReport(masterReport,null);
    System.out.println("paso7");
    //Se lanza el Viewer de Jasper, no termina aplicación al salir
    JasperViewer jviewer = new JasperViewer(jasperPrint,false);
    System.out.println("paso8");

    System.out.println("paso9");
    jviewer.setVisible(true);
    System.out.println("paso10");
    }

    catch (Exception j)
    {
    System.out.println("Mensaje de Error : "+ j.getMessage());
    System.out.println("Mensaje de Error : "+ j.getLocalizedMessage());
    }
    }


    me salta el error en el bloque catch (Exception j)

    Mensaje de Error : null

    Agradezco tu valiosa ayuda.

    ResponderEliminar
  34. Ok, creo que ya se cual es el problema. Cuando haces esto:

    JasperPrint jasperPrint = JasperFillManager.fillReport(masterReport,null);

    te falta pasarle un tercer parámetro: tu conexión. Deberia ser algo asi:

    JasperPrint jasperPrint = JasperFillManager.fillReport(masterReport,null, conexion);

    Creo que es ahi donde esta el problema, prueba y si no seguimos buscando

    Saludos

    ResponderEliminar
  35. Ya probe lo de la conexion pero sigue el mismo error

    Gracias . . .

    ResponderEliminar
  36. Ok. Del código que pones no entiendo bien unas cosas, parece como si tuvieras bloques try/catch anidados. Prueba con este y dime si te da alguna excepción en la salida:

    String ruta = "D:\\WILSON\\APLICACIONES DE ESCRITORIO CON JAVA\\Poyecto MOD\\Mod\\reporte2.jasper";


    if (ruta == null)
    {
    System.out.println("paso1");
    System.out.println("No se ubica el archivo del reporte .");
    System.exit(2);
    }

    JasperReport masterReport = null;
    System.out.println("paso2");
    try
    {
    System.out.println("paso3");
    masterReport = (JasperReport) JRLoader.loadObject(ruta);
    System.out.println("paso4");
    } catch (JRException e)
    {
    System.out.println("paso5");
    System.out.println("Error cargando el reporte : " + e.getMessage());
    e.printStackTrace();
    System.exit(3);
    }


    System.out.println("paso6");


    JasperPrint jasperPrint = null;

    try
    {
    JasperFillManager.fillReport(masterReport, null);
    System.out.println("paso7");
    } catch (Exception e)
    {
    e.printStackTrace();
    }
    //Se lanza el Viewer de Jasper, no termina aplicación al salir

    try
    {
    JasperViewer jviewer = new JasperViewer(jasperPrint, false);
    System.out.println("paso8");

    System.out.println("paso9");
    jviewer.setVisible(true);
    System.out.println("paso10");
    } catch (Exception j)
    {
    System.out.println("Mensaje de Error : " + j.getMessage());
    System.out.println("Mensaje de Error : " + j.getLocalizedMessage());
    j.printStackTrace();
    }

    ResponderEliminar
  37. Ahora vuelvo al error del dia de ayer :

    Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at net.sf.jasperreports.engine.JRPropertiesMap.readObject(JRPropertiesMap.java:185)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

    ResponderEliminar
  38. Pero sigue rebentando el el paso3 osea :

    masterReport = (JasperReport) JRLoader.loadObject(ruta);

    ResponderEliminar
  39. Ok, creo que necesitas un poco mas de ayuda. Pueden enviarme tu proyecto al siguiente correo (la parte java y el archivo .jrxml)?:

    programadorjavablog@gmail.com

    ResponderEliminar
  40. Ok gracias ya te envio el correo . . .

    ResponderEliminar
  41. Ok Alex muchas gracias ya lo probe y funciona muy bien , muchas gracias y que excelente blog.


    Samaca

    ResponderEliminar
  42. Hola;
    Hola compaenaro programador, disculpa tendras algun bloc que nos hable de como crear un servlet, ya que tengo alunas dificultades XD.
    jajaja

    Gracias.
    Miguel.

    ResponderEliminar
  43. Hola compañero;

    Pues por el momento lo más cercano que tengo es esto:

    http://javatutoriales.blogspot.com/2009/04/creacion-de-reportes-con-jasperrepots-y.html

    Ya que se usa un servlet para regresar el reporte, tal vez te pueda ayudar para darte una idea. Tal vez en el futuro haga un tutorial sobre servlets

    Saludos.

    ResponderEliminar
  44. Hola Programador java;

    Gracias por los tutoriales, es todo lo que necesitaba, de verdad gracias.

    Una pregunta, ¿como puedo hacer para enviar directamente el reporte a imprimir sin tener que visualizarlo o exportarlo antes?.

    Me explico mejor, tengo un formulario swing don de hay un boton, Imprimir. ¿Cómo seria el método para imprimir el reporte de manera directa?

    ResponderEliminar
  45. Hola;

    Normalmente en Java cuando se quiere imprimir algo se usa un PrinterJob, el cual imprime un objeto que implemente la interface Printable.

    En JasperReports existe una clase llamada JRPrinterAWT que implementa esta interface:

    http://jasperreports.sourceforge.net/api/net/sf/jasperreports/engine/print/JRPrinterAWT.html

    El constructor de esta clase recibe el JasperPrint que se obtiene al llenar el reporte.

    Puedes probar usando este objeto, sería mas o menos algo asi:

    PrinterJob printJob = PrinterJob.getPrinterJob();

    printJob.setJobName("reporte");
    printJob.setPrintable(new JRPrinterAWT(printJob ));

    printJob.print();

    Faltan algunos try y catch, pero es la idea basica.

    Espero que eso te sirva.

    Saludos.

    ResponderEliminar
  46. Hola Alex;

    Gracias por la pronta respuesta, al inicio probe con tu consejo, pero no me salia, me aparecia un error que decia:

    JRPrinterAWT(net.sf.jasperreport.engine.JasperPrint)
    has protected access in net.sf.jasperreport.engine.print,JRPrinterAWT

    no entiendo a q se debe este error, pero iba revisando y encontre otra forma la cual es:

    JasperPrintManager.printReport(jasperPrint, true);

    donde el primer parámetro es el jasperPrint y el segundo te indica si se muestra el cuadro de diálogo de impresión o no.

    Gracias. :)

    ResponderEliminar
  47. Hola;

    Al contrario, muchas gracias a tu por compartir tu solución aquí para que otros podamos aprender de tu experiencia y usarla.

    Saludos y Gracias ^-^

    ResponderEliminar
  48. hola programador Java:

    Tengo varias dudillas:

    Para empezar si puedo correr los reportes de esta manera

    File reportFile = new File(application.getRealPath("reporte//PrimerReporte.jasper"));
    parameters.put("cadena",rutaImagen.getPath());

    byte[] bytes = JasperRunManager.runReportToPdf(reportFile.getPath(),parameters,conexion);

    response.setContentType("application/pdf");
    response.setContentLength(bytes.length);
    ServletOutputStream outputStream = response.getOutputStream();
    outputStream.write(bytes,0,bytes.length);

    outputStream.flush();
    outputStream.close();

    y todo muy bien no, esta muy confiado pero le quise poner una imagen y ahi empezo mi sufrimiento por que me sale este error:

    javax.servlet.ServletException: java.lang.NoSuchMethodError: com.lowagie.text.Image.scaledWidth()F
    org.apache.jasper.runtime.PageContextImpl.doHandlePageException(PageContextImpl.java:858)
    org.apache.jasper.runtime.PageContextImpl.handlePageException(PageContextImpl.java:791)
    org.apache.jsp.lanza_jsp._jspService(lanza_jsp.java:99)
    org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:97)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:332)
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:314)
    org.apache.jasper.servlet.JspServlet.service(JspServlet.java:264)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:368)

    y tengo entendido que es por el itext.jar pero ya le puse la version 1.3.1 y la 2.1 y no kiere me sigue saliendo el mismo error. Bueno, navegando por la red me encontre con tu solucion y me encuentro con dos cosas:

    1. La primera no me marca ningun error ni nada solo que no me genera el PDF de salida, lo busco por todos lados y no esta. No se si sera por que bueno al principio me marcaba un error de que no encontraba el archivo compilado jasper asi que para que lo encontrara puse la sigueinte instruccion:

    File reportFile = new File(application.getRealPath("reporte//ReporteWeb.jasper"));
    JasperReport reporte = (JasperReport)JRLoader.loadObject(reportFile.getPath());

    y ya lo encuentra y no marca error solo que te digo que no me general el PDF.

    2. Y el segundo punto es que por ejemplo si cambio de archivo com´pilado por ejemplo ReporteWeb.jasper a PrimerReporte.jasper me sale el sigueinte error:

    java.lang.NullPointerException
    net.sf.jasperreports.engine.JRPropertiesMap.readObject(JRPropertiesMap.java:185)
    sun.reflect.GeneratedMethodAccessor102.invoke(Unknown Source)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    java.lang.reflect.Method.invoke(Method.java:597)
    java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:974)
    java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1849)
    java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1753)
    java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
    java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1947)
    java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1871)
    java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1753)
    java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
    java.io.ObjectInputStream.readArray(ObjectInputStream.java:1667)
    java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1323)
    java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1947)
    java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1871)
    java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1753)
    java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
    java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1947)
    java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1871)
    java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1753)
    java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
    java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
    net.sf.jasperreports.engine.util.JRLoader.loadObject(JRLoader.java:88)
    net.sf.jasperreports.engine.util.JRLoader.loadObject(JRLoader.java:64)
    org.apache.jsp.lanza_jsp._jspService(lanza_jsp.java:87)
    org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:97)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:332)
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:314)
    org.apache.jasper.servlet.JspServlet.service(JspServlet.java:264)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:717)


    Agradezco eormemente de antemano tus comentarios y ayuda. Gracias

    ResponderEliminar
  49. holaaaaaaaaaaa!!!! =) =) =)

    soy yo otra vez el ultimo que escribio, oye ya me acaba de generar el PDF de salida, solo que en la instruccion que propones para poner el nombre del archivo de salida tuve que ponerle otros contructor File para la ruta, ahora solo mi duda es como le ingreso una image =( =( me sigue marcando el mismo error

    ResponderEliminar
  50. Hola;

    Que buen que ya te funconó al menos la primer parte.

    Si no me equivoco estas haciendo una aplicación web cierto?. Si es así también puedes revisar este tutorial:

    http://javatutoriales.blogspot.com/2009/04/creacion-de-reportes-con-jasperrepots-y.html

    En cuanto a la imagen ocurre lo mismo: debes darle la ruta absoluta de en dónde se encuentra. Si estas haciendo una aplicación standalone debes darle la ruta absoluta de directorios, por ejemplo: c:\documentos\imagenes\imagen.gif.

    Si estas haciendo una apliación web debes darle la url absoluta de una ubicación que pueda recuperar y que sea accesibe via Internet, por ejemplo: http://miServidor/aplicacion/imagenes/imagen.gif.

    Esto debes indicarlo en la ruta de tu elemento Image en iReport.

    Espero que esto te ayude, suerte con tu proyecto. Si no te funciona o tienes más preguntas no dudes en consultarme.

    Saludos.

    ResponderEliminar
  51. Hola Alex,
    Chvr por los reportes, te felicito, me sacaste de tantas dudas que no se resuelven así no mas,
    una pregunta,¿Como hago para usar una clase que me sirva para formatear campos de un reporte?

    Por ejemplo tengo un reporte que me muestra resultados numéricos y fechas, y quiero formatearlos de acuerdo a mi propio patron (osea sin usar la propiedad Pattern de los campos),
    he oido de la propiedad "Scriptled class" donde se le indica una clase (.java), pero la verdad no tengo ni idea de como usarlo.

    Espero haber explicado claramente mi problema, si alguien puede ayudarme, se lo agradecería mucho.

    Gracias...

    ResponderEliminar
  52. Hola!! primero que nada felicitarlo por el aporte realmente bueno.

    Mira tengo el siguiente problema la aplicación me marca este error cuando llega a la linea: JasperPrint print= JasperFillManager.fillReport(reprote, null, clientes.getConexion());

    El error:

    Exception in thread "AWT-EventQueue-0" java.lang.NoClassDefFoundError: org/springframework/core/io/Resource
    at java.lang.Class.forName0(Native Method) y el resto de la cola del error.

    Estuve viendo que algunos también le dio problemas en esa parte si me pudieras ayudar le agrade seria mucho.

    ResponderEliminar
  53. Hola, supongo que estas usando Spring para desarrollar tu aplicación, ya que JasperReports no usa ninguna clase de Spring.

    Prueba agregar el jar de Spring para la versión que estes usando a las librerias de tu aplicación.

    Saludos

    ResponderEliminar
  54. mmm disculpa la ignorancia pero no se para que podría estar usando el spring(no se para que sirve), estoy usando netbeans y el pluging para usar el ireport en el, ya ya hice el archivo .jasper y todo bien hasta hay pero luego como te comente me salta el error, si me pudieras orientar un poco al respecto o si te puedo enviar el proyecto para ver si puedes llegarle mas preciso al error?

    ResponderEliminar
  55. Si, enviame el proyecto a este correo para que lo revise

    programadorjavablog@gmail.com

    Saludos

    ResponderEliminar
  56. ok, pura vida!!!

    Ya le agregue la librería que le faltaba y ya me tira el reporte, pero sin embargo en la pestaña de la salida cuando un corre la aplicación en el netbeans me tira esto:

    21/06/2009 08:38:00 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
    INFO: Loading XML bean definitions from URL [jar:file:/D:/Archivos%20de%20programa/NetBeans%206.5/ireport/modules/ext/jasperreports-chart-themes-3.5.2.jar!/net/sf/jasperreports/chartthemes/spring/beans/chartThemesBeans.xml]
    21/06/2009 08:38:01 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
    INFO: Loading XML bean definitions from URL [jar:file:/D:/Archivos%20de%20programa/NetBeans%206.5/ireport/modules/ext/jasperreports-chart-themes-3.5.2.jar!/net/sf/jasperreports/chartthemes/spring/beans/defaultChartPropertiesBean.xml]
    21/06/2009 08:38:01 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions

    y más de lo mismo, eso es un error o...?

    ResponderEliminar
  57. Pues si es un error, pero parece ser más bien del plugin de iReport, no de tu aplicación.

    Algunas veces ocurren ese tipo de errores con los plugins que no se bajan directamente con el asistente del NetBeans. Yo también tuve problemas con ese mismo plugin (de hecho nunca pude instalarlo bien) por eso uso el iReport como aplicación standalone.

    Saludos

    ResponderEliminar
  58. Buenas Tardes he hecho un reporte de prueba en el pluing de IREPORT, en netbeans 6.5, lo compilo y bien, pero no he podido deslegarlo (Ejecutarlo en mi aplicacion). Ademas tiene todas la bibliotecas de jasperreport, y ireport y no se como hacer para ejecutarlo..tengo dos semanas en ello y nada, si hay un jenio de jenios que pueda ayudarme se lo agradeseria en el alma

    ResponderEliminar
  59. Hola, pues lo unico que tienes que hacer es asegurarte de poner el archivo .jasper generado en la raíz del proyecto de NetBeans en el que quieres generar el reporte.

    ¿Estas recibiendo algún error o algo por el estilo?

    ResponderEliminar
  60. Hola espero me puedan ayudar tengo que hacer la impresion de un reporte pero directo sin vizualizarlo el problema es que utilizo JSF y lo descargo sin problemas ya sea en html, pdf , word, xls, pero no puedo mandarlo a imprimir uso algo asi espero me puedan ayuda

    HttpServletResponse response =(HttpServletResponse)faces.getExternalContext().getResponse();
    // Some additional setup parameters
    response.setContentType("text/html");
    response.setHeader("Content-disposition",
    "attachment; filename=Prueba.doc");
    ServletOutputStream out;
    out = response.getOutputStream();

    in = new BufferedReader(new FileReader(strFile));

    String linea = "";
    Utilerias utilerias = new Utilerias();

    while ((linea = in.readLine()) != null){

    out.write(linea.getBytes());
    System.out.println(linea);

    }
    out.flush();
    in.close();

    ResponderEliminar
  61. Hola Alejandra.

    Pues normalmente en web cuando quieres imprimir algo usas el método de javascript window.print(). Pero esto imprime la página que estes visualizando (así que tendrías que mostrar el reporte). Por por otro lado si quieres imprimir un reporte de JasperReports puedes usar este:

    JasperPrintManager.printReport(jasperPrint, true);

    Donde el booleano indica si se debe mostrar o no el cuadro de dialogo. El problema con esto es que se ejecutará en el servidor donde vive tu aplicación, no en tu cliente.

    No estoy seguro si puede hacerse lo que quieres, perdona.

    De todas formas investigaré a ver si logro encontrar algo.

    Saludos.

    ResponderEliminar
  62. Este comentario ha sido eliminado por el autor.

    ResponderEliminar
  63. buenas tardes.

    primero que nada muchas felicidades por el tutorial me esta ayudando mucho.

    me podrias ayudar a saber porque me marca el siguiente error:

    exception

    javax.servlet.ServletException: Servlet execution threw an exception
    org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:362)


    root cause

    java.lang.NoSuchMethodError: com.lowagie.text.pdf.PdfWriter.setRgbTransparencyBlending(Z)V
    net.sf.jasperreports.engine.export.JRPdfExporter.exportReportToStream(JRPdfExporter.java:484)
    net.sf.jasperreports.engine.export.JRPdfExporter.exportReport(JRPdfExporter.java:362)
    pruebas.jasperreports.web.ServletReporte.processRequest(ServletReporte.java:40)
    pruebas.jasperreports.web.ServletReporte.doGet(ServletReporte.java:47)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:689)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
    org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:362)


    note The full stack trace of the root cause is available in the Apache Tomcat/5.5.9 logs.

    gracias y saludos.

    ResponderEliminar
  64. Hola txalex. Muchas gracias por tus comentarios.

    Tu problema puede deberse a que estas usando una versión antigua, ya sea de JasperReports o de iText(que es la librería que usa para la conversión) a PDF.

    Saludos

    ResponderEliminar