Vous êtes sur la page 1sur 87

Creación de Reportes con JasperRepots y iReports -

Parte 1: Reportes con Conexión a Base de Datos


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.

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();
}
}
Creación de Reportes con JasperRepots y iReports -
Parte 2: Uso de DataSources Personalizados
Ahora veremos cómo generar nuestros reportes sin hacer uso de una conexión. Esto puede ser
muy útil en los casos en los que ya tengamos los datos en memoria y no necesitemos realizar una
conexión a la base de datos; o en el caso en que, por alguna razón ajena a nosotros, no podamos
obtener la conexión.

Para poder hacer esto se nos proporciona una interface:


"net.sf.jasperreports.engine.JRDataSource". Esta interface tiene solo dos métodos:

 getFieldValue(JRField jrField)
 next()

Creamos un nuevo proyecto en NetBeans (menú "File -> New Project..."). En la ventana
de nuevos proyectos seleccionamos la categoría "Java" y como 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 las opciones "Create Main Class" y "Set
as Main Project".

Para que podamos pasar datos a nuestro reporte es necesario que utilicemos un datasource. En el
ejemplo anterior veíamos que el datasource que usábamos era la base de datos y la conexión a la
misma. En esta ocasión el datasource será una de nuestras clases. Esta clase deberá implementar
la interface "JRDataSource" y contendrá la lógica para pasar los datos correspondientes a
nuestro reporte.

Creamos una nueva clase haciendo clic derecho sobre el nodo "Source Packages" de la ventana
"Projects", o sobre el paquete que ya tenemos creado, y en el menú contextual que se abre
seleccionamos la opción "New -> Java Class...".

En la ventana que se abre escribimos como en nombre de la nueva clase "Participante" y


presionamos el botón "Finish". Con esto veremos en la ventana de nuestro editor la nueva clase
"Participante".

Esta clase "Partcipante" representará los datos que se mostrarán en el reporte, tal como en el
ejemplo anterior cada uno de los registros de la tabla "participantes" representaba una fila en
el reporte final, cada objeto participante que creemos representará una fila en el nuevo reporte.

Agreguemos los siguientes atributos a nuestra clase:

private int id;

private String nombre;

private String username;

private String password;

private String comentarios;

Además agregamos sus getters y sus setters y dos constructores, uno sin argumentos y uno
que reciba como argumentos todas las propiedades declaradas anteriormente.

Si están utilizando el NetBeans para seguir este tutorial pueden generar tanto los setters y los
getters de forma automática presionando las teclas "Alt + Insert", con lo cual se abrirá un
menú contextual con las opciones necesarias para hacer esto:

Al terminar, su clase debe verse más o menos así:

public class Participante

{
private int id;
private String nombre;
private String username;
private String password;
private String comentarios;

public Participante()
{
}
public Participante(int id, String nombre, String username, String
password, String comentarios)
{
this.id = id;
this.nombre = nombre;
this.username = username;
this.password = password;
this.comentarios = comentarios;
}

public String getComentarios()


{
return comentarios;
}

public void setComentarios(String comentarios)


{
this.comentarios = comentarios;
}

public int getId()


{
return id;
}

public void setId(int id)


{
this.id = id;
}

public String getNombre()


{
return nombre;
}

public void setNombre(String nombre)


{
this.nombre = nombre;
}

public String getPassword()


{
return password;
}

public void setPassword(String password)


{
this.password = password;
}

public String getUsername()


{
return username;
}
public void setUsername(String username)
{
this.username = username;
}
}

Ahora, antes de seguir con nuestro código Java, pasaremos a crear la plantilla de nuestro reporte
con iReport, por lo que abrimos esta herramienta.

En esta ocasión no haremos uso de un wizard para crear el reporte, sino que lo haremos desde
cero, y aprovecharé para explicar algunos conceptos básicos sobre los reportes conforme los
vayamos necesitando.

Para crear el nuevo reporte vamos el menú "File -> New...". En la ventana que se abre
seleccionamos uno de los formatos "Blank" y presionamos el botón "Open this Template":

Después introducimos el nombre del reporte, yo lo llamaré "reporte2.jrxml", y la ubicación en


la que se guardará. Les recomiendo que en esta ocasión guarden el reporte en el directorio raíz del
proyecto de NetBeans que acabamos de crear. Hacemos clic en el botón "Next" y se nos
mostrará un mensaje de felicitación por haber creado un nuevo reporte (^_^!). Cuando presionen el
botón "Finish" verán una hoja dividida en 7 u 8 diferentes porciones horizontales llamadas
bandas.
Cuando generamos nuestro reporte final con datos, cada una de estas bandas se comporta de una
forma distinta. Algunas aparecen solo al principio o al final del reporte, otras aparecen con cada
nueva fila que se le agrega, otras solo al final de los datos, etc.

La plantilla de reportes está dividida en 10 bandas predefinidas. Una banda siempre tiene el mismo
ancho que la página. Sin embargo el alto de algunas de las bandas puede variar durante la fase de
llenado de datos, aún si establecimos un alto en el momento del diseño.

Las bandas existentes son:

 Background
 Title
 Page Header
 Column Header
 Detail 1
 Column Footer
 Page Footer
 Last Page Footer
 Summary
 No Data

Explicaré algunas de estas bandas conforme las vayamos usando en los tutoriales
correspondientes.

Lo primero que haremos es agregar texto a nuestro reporte. En iReport existen dos tipos de
texto: texto estático y texto dinámico (también llamado expresiones). El texto estático es aquel
que no cambia, mientras que las expresiones son como etiquetas que le indican a
JasperReports que debe reemplazarlas por algún valor al momento de generar el reporte final.

Existen 3 tipos de expresiones:

 Campos (fields) representados con "$F{nombre_campo}".


 Variables representadas por "$V{nombre_variable}".
 Parámetros representados por "$P{nombre_parámetro}".

Cada uno de estos tipos de expresiones tiene un uso particular:

Los campos ("$F{}") le dicen al reporte dónde colocará los valores obtenidos a través del
datasource. Por ejemplo, nuestro objeto "Partcipante" tiene un atributo llamado "username".
Usando una expresión de campo indicamos en cuál parte o sección del reporte debe aparecer el
valor de ese atributo usando "$F{username}". Esto quedará más claro un poco más adelante.

Los parámetros ("$P{}") son valores que usualmente se pasan al reporte directamente desde el
programa que crea el JasperPrint del reporte (en nuestra aplicación Java). Aunque también
existen algunos parámetros internos que podemos leer pero no modificar. Para hacer uso de estos
parámetros simplemente indicamos el nombre del parámetro en el lugar que queremos colocarlo.
Pueden encontrar los nombres y significados de los parámetros internos en la documentación de
JasperReports.

Las variables ("$V{}") son objetos usados para almacenar valores como los resultados de
cálculos. Al igual que con los parámetros, JasperReports tiene algunas variables internas que
podemos leer. Pueden encontrar los nombres y significados de las variables la documentación de
JasperReports.

Cada uno de estos elementos tiene un nombre, un tipo (que debe corresponder con un tipo de
objeto Java como String o Integer), y una descripción opcional. Además deben ser
registrados para poder ser usados en tiempo de diseño y que puedan ser entendidos al momento
de compilar el reporte, y por lo tanto para que nuestro reporte funcione correctamente en tiempo de
ejecución. Esto lo veremos un poco más adelante.

Regresemos a donde nos quedamos. Queremos agregar un texto estático a nuestro reporte a
modo de título. Para esto debemos agregar un elemento llamado "Static Text". Los elementos
que podemos agregar a nuestros reportes están en una ventana llamada "Palette", que se
encuentra en la parte derecha de iReport, bajo la categoría "Report Elements". Si no pueden
ver la ventana "Palette" presionen las teclas "Ctrl + Shift + 8":

De esta ventana arrastramos el elemento "Static Text" a la banda "Title". "Title" es una
banda que solo aparece en la parte superior de la primer página. Por lo que nos sirve para colocar
el título del reporte y/o el nombre y logo de nuestra empresa.
Una vez que hayamos colocado el texto estático en la banda correspondiente y mientras aún esté
seleccionado, modificamos sus propiedades usando la ventana de propiedades del elemento y la
barra de formato de texto. También podemos abrir otra ventana que nos ayude a alinear y controlar
el alto y el ancho de los elementos yendo al menú "Window -> Formatting Tools".

Ahora agregamos los encabezados de las columnas en las que se mostrarán los datos que
pasaremos al reporte. Agregamos estos nombres en la banda "Column Header", la cual se
repetirá en cada página antes de mostrar los datos de las columnas.

Agregaremos las columnas "Nombre", "Usuario", "Contraseña", y "Comentarios". Por lo que


nuevamente arrastramos un elemento "Static Text" para cada una de las columnas. También
podemos ajustar el alto de esta banda para que se ajuste al de nuestro texto, ya sea moviéndola
directamente en el diseñador, o desde la ventana de propiedades:

Nuestro reporte ya casi está terminado, ahora solo nos queda agregar los campos en los que se
mostrarán los datos que pasaremos al reporte en un momento. Para que estos campos puedan ser
reemplazados por el valor real es necesario que usemos las expresiones (texto dinámico) de las
que hablé anteriormente. Para esto definiremos un "field" para cada uno de los campos que
queramos mostrar (en este caso serán los mismos campos para los que definimos las cabeceras
de las columnas).

Los fields deben definirse antes de poder ser usados. Esta definición incluye el nombre del
field y su tipo. Los fields (así como el resto de las expresiones) se definen en la ventana
"Report Inspector" a la izquierda del diseñador del reporte. Ahí existe un nodo llamado
"Fields" que es donde se encuentran los fields que hemos definido y que por lo tanto podemos
usar ^-^.
Hacemos clic derecho en el nodo "Fields" de la ventana "Report Inspector". Con esto se
abre un menú contextual. Seleccionamos la opción "Add Field" (la única habilitada).

Con esto se agregará un field llamado "field1" que por default es de tipo "java.lang.String".
Cambiamos el nombre de este campo por "nombre" usando la ventana de propiedades. Esto es
importante porque donde pongamos este campo será en donde se muestre el valor del campo
nombre de nuestros objetos Participantes.

Hacemos lo mismo para el resto de los campos ("username", "password", "comentarios",


"id"). Hay que tener cuidado cuando agreguemos el field "id". Si recuerdan, en la definición de la
clase "Participante" la propiedad "id" está definida como "int". Sin embargo, a
JasperReports solo podemos pasarle objetos para ser usados como valores, por lo que será
necesario cambiar el tipo de la clase ("Field Class en la ventana de propiedades) a
"java.lang.Integer" (aunque en realidad no mostraremos el "id" en este ejemplo).
Ahora debemos indicar en qué parte de nuestro reporte queremos que se muestren los valores
correspondientes a los atributos de los objetos "Participante" que le pasemos. Para eso
simplemente arrastramos los fields correspondientes al lugar en el que queremos que se
muestren (arrastramos el field "nombre" a donde queremos que se muestre el atributo "nombre",
el campo "username" en donde queremos que se muestre el atributo "username", etc.) desde el
"Report Inspector". Al arrastrar los fields, iReport agregará automáticamente un encabezado
para este field, solo borren el encabezado agregado =).

Estos fields los colocaremos en la banda "Detail 1" la cual se repite cada vez que recibe un
nuevo objeto y coloca sus valores en la misma fila (quedará más claro cuando ejecutemos el
ejemplo). Al final, el reporte debe quedar de la siguiente forma:

Por el momento esto es todo lo que necesitamos hacer en iReport para mostrar este reporte
básico. Hacemos clic en el botón "Compile Report" para compilar el reporte y generar su archivo
".jasper" respectivo.

Podemos ver una vista previa del reporte haciendo clic en la pestaña "Preview". Asegúrense de
seleccionar el "Empty datasource" antes de ver el preview, de lo contrario les aparecerá un
error indicado que el documento no tiene páginas. Al final deben ver algo como esto:
Los "nulls" aparecen porque no se recuperó ningún valor que coincidiera con el nombre de ese
field usando nuestro datasource (que en este caso está vacío, lo cual solucionaremos a
continuación).

Regresamos al NetBeans y ahora crearemos una clase que implemente la interface


"JRDataSource" de la que hablé antes. Esta clase será la que usaremos como datasource para
nuestro reporte, y la que regresará los valores correspondientes a cada uno de los fields que
creamos antes.

Creamos una nueva clase llamada "ParticipantesDatasource" y hacemos que esta nueva
clase implemente la interface "JRDataSource". Podemos hacer que NetBeans implemente de
forma automática los métodos de esta interface (proporcionando una implementación vacía)
presionando las teclas "Alt + Insert" y seleccionando la opción "Implement Method" en el
menú contextual que se abre.

Con esto se abrirá una ventana llamada "Generate Implement Methods" en la cual
seleccionamos la interface "JRDataSource" para que se seleccionen de forma automática todos
sus métodos y hacemos clic en el botón "Generate".
Con esto tendremos los dos métodos implementados y en cuyos cuerpos solo habrá:

throw new UnsupportedOperationException("Not supported yet.");

Ahora agregaremos a nuestra clase un atributo de tipo "java.util.List" llamado


"listaParticipantes" que mantendrá justamente eso: la lista de los participantes de los cuales
mostraremos los datos en el reporte. Inicializamos esta lista a un objeto de tipo
"java.util.ArrayList", de esta forma:

private List<Participante> listaParticipantes = new

ArrayList<Participante>();

También agregamos un contador llamado "indiceParticipanteActual" de tipo "int", que


usaremos enseguida, y lo inicializamos a "-1"; un poco más adelante explicaré por qué este valor:

private int indiceParticipanteActual = -1;

Hasta ahora nuestra clase debe verse así:

public class ParticipantesDatasource implements JRDataSource

{
private List<Participante> listaParticipantes = new
ArrayList<Participante>();
private int indiceParticipanteActual = -1;

public Object getFieldValue(JRField jrf) throws JRException


{
throw new UnsupportedOperationException("Not supported yet.");
}

public boolean next() throws JRException


{
throw new UnsupportedOperationException("Not supported yet.");

Ahora implementaremos el método getFieldValue. Este método recibe un argumento de tipo


JRField. Este parámetro nos indicará por cuál de los "fields" nos está preguntando el reporte.

En la implementación de este método regresaremos los valores correspondientes a cada uno de


los atributos de nuestros objetos "Participante" conforme se vayan pidiendo. Por lo que el
método queda así:

public Object getFieldValue(JRField jrField) throws JRException

{
Object valor = null;

if("nombre".equals(jrField.getName()))
{
valor =
listaParticipantes.get(indiceParticipanteActual).getNombre();

}
else if("username".equals(jrField.getName()))
{
valor =
listaParticipantes.get(indiceParticipanteActual).getUsername();
}
else if("password".equals(jrField.getName()))
{
valor =
listaParticipantes.get(indiceParticipanteActual).getPassword();
}
else if("comentarios".equals(jrField.getName()))
{
valor =
listaParticipantes.get(indiceParticipanteActual).getComentarios();
}

return valor;
}

Donde básicamente ocurre lo que dije anteriormente: cada vez que el reporte pregunta por el valor
de un atributo del objeto "Participante" actual (al que hace referencia el contador
"indiceParticipanteActual") se regresa el valor correspondiente. Esta petición se hace en
base al nombre del field que creamos desde iReport.

Ahora tal vez se estén preguntando ¿en qué momento se incrementa el contador?, o ¿cómo sabe
JasperReport cuántos participantes existen? Pues bien, ambas cosas ocurren gracias a la
implementación del método "next()".

public boolean next() throws JRException

return ++indiceParticipanteActual < listaParticipantes.size();

JasperReport pregunta a este método para saber si existe otro "Participante" en la lista.
Este método es el primero que se llama al generar el reporte. Por lo que el contador debe
comenzar en "-1", así cuando este método se llama la primera vez el contador queda en "0", y
cuando se invoca al método "getFieldValue" se regresa el objeto Participante del índice
adecuado.

Esto es todo lo que necesitamos para que nuestro datasource funcione para generar reportes.
Agregaré un método de utilidad a esta clase, llamado "addParticipante", que me permita
agregar un nuevo participante a la lista (aunque si lo prefieren pueden agregar el setter de
"listaParticipantes"):

public void addParticipante(Participante participante)

{
this.listaParticipantes.add(participante);
}

La clase "ParticipantesDatasource" queda de esta forma (omitiendo los imports):

public class ParticipantesDatasource implements JRDataSource

{
private List<Participante> listaParticipantes = new
ArrayList<Participante>();
private int indiceParticipanteActual = -1;

public Object getFieldValue(JRField jrf) throws JRException


{
Object valor = null;

if ("nombre".equals(jrf.getName()))

{
valor =
listaParticipantes.get(indiceParticipanteActual).getNombre();
}
else if ("username".equals(jrf.getName()))
{
valor =
listaParticipantes.get(indiceParticipanteActual).getUsername();
}
else if ("password".equals(jrf.getName()))
{
valor =
listaParticipantes.get(indiceParticipanteActual).getPassword();
}
else if ("comentarios".equals(jrf.getName()))
{
valor =
listaParticipantes.get(indiceParticipanteActual).getComentarios();

return valor;
}

public boolean next() throws JRException


{

return ++indiceParticipanteActual < listaParticipantes.size();


}

public void addParticipante(Participante participante)


{
this.listaParticipantes.add(participante);
}
}

Para finalizar agregaremos en nuestra clase "Main" un ciclo dentro del cual crearemos 10 objetos
"Participante", los cuales iremos agregando uno a uno a un objeto de tipo
"ParticipantesDatasource":

ParticipantesDatasource datasource = new ParticipantesDatasource();

for (int i = 1; i <= 10; i++)

Participante p = new Participante(i, "Particpante " + i, "Usuario "

+ i, "Pass " + i, "Comentarios para " + i);


datasource.addParticipante(p);
}

El resto del código para generar el reporte es similar al del primer tutorial de JasperReports, solo
que en esta ocasión en lugar de pasar un objeto de tipo "Connection" al método "fillReport"
del "JasperFillManager" pasamos nuestro objeto "ParticipantesDatasource" de esta
forma:

JasperPrint jasperPrint = JasperFillManager.fillReport(reporte, null,

datasource);

Al final el código de nuestra clase "Main" queda así:

public class Main

{
public static void main(String[] args) throws Exception
{
ParticipantesDatasource datasource = new
ParticipantesDatasource();

for (int i = 1; i <= 10; i++)


{
Participante p = new Participante(i, "Particpante " + i,

"Usuario " + i, "Pass " + i, "Comentarios para " + i);


datasource.addParticipante(p);
}

JasperReport reporte = (JasperReport)


JRLoader.loadObject("reporte2.jasper");
JasperPrint jasperPrint = JasperFillManager.fillReport(reporte,

null, datasource);

JRExporter exporter = new JRPdfExporter();


exporter.setParameter(JRExporterParameter.JASPER_PRINT,
jasperPrint);
exporter.setParameter(JRExporterParameter.OUTPUT_FILE, new
java.io.File("reporte2PDF.pdf"));

exporter.exportReport();
}
}

Al ejecutar este código debemos terminar con un archivo llamado "reporte2PDF.pdf" en el


directorio raíz de nuestro proyecto y que tiene el siguiente contenido:

Podrá no ser el reporte más bello o más útil del mundo, pero es nuestro =D.

Podemos ver que los datos importantes (los datos de los "Participantes") aparecen en la
banda "Details 1" (donde colocamos los fields) y que esta banda se repite por cada uno de los
participantes de la lista.

Bien, con esto vemos que podemos crear nuestros propios datasources y pasar datos para generar
reportes sin la necesidad de una conexión a base de datos. Es bastante sencillo, solamente
debemos proporcionar una clase que implemente la interface "JRDataSource" y que regrese los
valores correspondientes a los fields del reporte.

Aunque esto ya es bastante fácil y útil, existe una forma aún más simple para crear un datasource,
sin la necesitad de implementar la interface "JRDataSource". Esto es gracias a un conjunto de
clases que JasperReports ya nos proporciona y realizan básicamente la misma función que la
clase "ParticipantesDatasource" que acabamos de crear. Estas clases son:

 JRBeanCollectionDataSource
 JRJpaDataSource
 JRBeanArrayDataSource

Las cuales ya implementan la interface "JRDataSource". Cada una funciona con distintos tipos de
datos, pero en que nos interesa en este momento es "JRBeanCollectionDataSource" que
puede convertir una "java.util.Collection" en un DataSource de forma automática.
Modificaremos nuestro método "main" para hacer uso de esta clase.

Ahora, en vez de llenar nuestro "ParticipantesDatasource" en el ciclo simplemente


llenaremos un "java.util.List":

List listaPariticipantes = new ArrayList();

for (int i = 1; i <= 10; i++)

{
Participante p = new Participante(i, "Particpante " + i, "Usuario "
+ i, "Pass " + i, "Comentarios para " + i);
listaPariticipantes.add(p);
}

Y en lugar de pasar un objeto de tipo "Connection" al método "fillReport" del


"JasperFillManager" pasamos un nuevo objeto "JRBeanCollectionDataSource" construido
con la lista "listaPariticipantes":

JasperPrint jasperPrint = JasperFillManager.fillReport(reporte, null,

new JRBeanCollectionDataSource(listaPariticipantes));

Al final nuestra clase "Main" queda así:

public class Main

{
public static void main(String[] args) throws Exception
{
List listaPariticipantes = new ArrayList();

for (int i = 1; i <= 10; i++)


{
Participante p = new Participante(i, "Particpante " + i,
"Usuario " + i, "Pass " + i, "Comentarios para " + i);
listaPariticipantes.add(p);
}

JasperReport reporte = (JasperReport)


JRLoader.loadObject("reporte2.jasper");

JasperPrint jasperPrint = JasperFillManager.fillReport(reporte,


null, new JRBeanCollectionDataSource(listaPariticipantes));

JRExporter exporter = new JRPdfExporter();


exporter.setParameter(JRExporterParameter.JASPER_PRINT,
jasperPrint);
exporter.setParameter(JRExporterParameter.OUTPUT_FILE, new
java.io.File("reporte2PDF_2.pdf"));

exporter.exportReport();
}
}

Al ejecutar este código se genera el archivo "reporte2PDF_2.pdf" en el directorio raíz de


nuestro proyecto, con el siguiente contenido:

El cual es idéntico al reporte generado con la clase "ParticipantesDatasource".


Y con esto vemos que gracias a la clase "JRBeanCollectionDataSource" no es necesario que
proporcionemos nuestra propia clase que implemente la interface "JRDataSource", por lo que la
generación de reportes es aún más simple ^-^.
Creación de Reportes con JasperRepots y iReports -
Parte 3: Parámetros y Variables

Abrimos iReport y el reporte del tutorial anterior ("reporte2.jrxml"). En este momento nuestro
reporte debe verse como en la siguiente imagen:

En donde solo tenemos textos estáticos y "fields" para mostrar un reporte básico de los datos de
ciertos participantes. Si lo recuerdan, la salida del reporte al generarlo desde nuestra aplicación
Java, era la siguiente:

Ahora pasaremos a agregar "Parameters" a este reporte. Como dije en el tutorial anterior: los
parámetros son valores que usualmente se pasan al reporte desde el programa que crea el
"JasperPrint" del reporte (nuestra aplicación Java) haciendo uso de un "java.util.Map".
En este caso pasaremos dos parámetros: el título del reporte, y el nombre del autor del mismo.

Al igual que con los Fields, para poder hacer uso de un parámetro primero hay que declararlo en
el "Report Inspector" (situado en el panel izquierdo del iReport), por lo que nos dirigimos a
esta ventana y hacemos clic derecho sobre el nodo "Parameters". Al hacer esto se abrirá un
menú contextual. Seleccionamos la opción "Add Parameter" (la única habilitada).

Con esto se agregará un nuevo parámetro llamado "parameter1" de tipo "java.lang.String".


Cambiamos en nombre del parámetro en la ventana de propiedades a "titulo" (recuerden que
este nombre es el que deberemos usar desde nuestra aplicación Java para establecer el valor del
parámetro).

Agregamos otro parámetro llamado "autor" de la misma forma que agregamos el de "titulo".

Ahora eliminamos el elemento que teníamos como título del reporte (el que contiene el texto
estático "Reporte de Participantes") y lo reemplazamos por el parámetro "titulo"
arrastrándolo desde la ventana del "Report Inspector" a la banda "Title".
Ajustamos este elemento para que tenga el mismo formato que el título que teníamos
anteriormente.

Ahora agregamos el segundo parámetro ("autor") en la banda "Page Header", la cual se repite
en la parte superior de cada una de las páginas (en la primer página aparece después del título),
arrastrándolo a esta banda.

Si dejamos esta expresión tal y como está ("$P{autor}") solo se mostrará en nombre del autor en
la parte superior de cada una de las páginas (por ejemplo si el autor del reporte es "Juan", solo
veremos la palabra "Juan" en la parte superior de los reportes). Esto podría no ser claro para
quienes revisen este reporte, por lo que queremos indicar de forma explícita que a lo que se refiere
el valor de este parámetro es el nombre del autor. Para hacer esto nos dirigimos a la ventana de
propiedades de este parámetro (para lo cual debemos tenerlo seleccionado) y buscamos la
categoría "Text field properties". Ahi se encuentra una propiedad llamada "Text Field
Expression" cuyo valor es "$P{autor}".
Lo que haremos es editar esta expresión para anteponer la palabra "Autor: ". Para hacer esto
presionamos el botón "...", con lo que se abrirá una ventana que nos permitirá editar la
expresión. En esta ventana modificamos la expresión "$P{autor}" para que quede "Autor: "
+ $P{autor}. Con esto lo que logramos es que a la cadena estática "Autor: " se le concatene
el valor de la expresión dinámica "$P{autor}". Por lo que ahora el lo que aparecerá en la parte
superior de cada página del reporte será la cadena "Autor: Juan".

Ahora presionamos el botón "Compile Report" para que se genere el reporte compilado
"reporte2.jasper".

Veamos una vista previa del reporte, para esto hacemos clic en la pestaña "Preview". Nos pedirá
los valores de los dos parámetros. Si colocamos para el parámetro "titulo" el valor "Reporte" y
para el parámetro "autor" el valor "Alex" el preview que veremos será el siguiente:
Ahora veremos cómo pasarle estos valores desde nuestra aplicación Java, por lo que abrimos
nuestro IDE de trabajo, NetBeans.

Ahí nos dirigimos a la clase "Main" que creamos la última vez y buscamos la línea en donde
creamos nuestro objeto "JasperPrint":

JasperPrint jasperPrint = JasperFillManager.fillReport(reporte, null,

new JRBeanCollectionDataSource(listaPariticipantes));

Y antes de esta línea crearemos un objeto "java.util.Map" que contendrá nuestros parámetros.
Colocaremos el nombre de los parámetros (en este caso "autor" y "titulo") como llave y sus
respectivos valores, "Juan" para el autor y "Reporte Participantes" para el título, como
valores.

Map<String, String> parametros = new HashMap<String, String>();

parametros.put("autor", "Juan");

parametros.put("titulo", "Reporte Participantes");

Y pasamos este "Map" como el segundo parámetro del método "fillReport", al que hasta ahora
le hemos pasado "null":

JasperPrint jasperPrint = JasperFillManager.fillReport(reporte,

parametros, new JRBeanCollectionDataSource(listaPariticipantes));

El código de nuestro método "main" queda así:


public static void main(String[] args) throws Exception

{
List<Participante> listaPariticipantes = new
ArrayList<Participante>();

for (int i = 1; i <= 10; i++)


{
Participante p = new Participante(i, "Particpante " + i,
"Usuario " + i, "Pass " + i, "Comentarios para " + i);

listaPariticipantes.add(p);

JasperReport reporte = (JasperReport)


JRLoader.loadObject("reporte2.jasper");
Map<String, String> parametros = new HashMap<String, String>();
parametros.put("autor", "Juan");

parametros.put("titulo", "Reporte Participantes");

JasperPrint jasperPrint = JasperFillManager.fillReport(reporte,

parametros, new JRBeanCollectionDataSource(listaPariticipantes));


JRExporter exporter = new JRPdfExporter();
exporter.setParameter(JRExporterParameter.JASPER_PRINT,

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

exporter.exportReport();

Si ejecutamos nuestro reporte obtendremos un archivo con el siguiente contenido:


Como podemos ver los parámetros "titulo" y "autor" han sido reemplazados por los valores
"Reporte Participantes" y "Juan" respectivamente.

Gracias a los parámetros podemos pasar valores (como en este caso cadenas, pero podemos
pasar prácticamente cualquier tipo de objeto) a nuestro reporte directamente desde nuestra
aplicación Java.

Ahora veremos el último tipo de expresión que JasperReports nos proporciona, las Variables.

Como dije en el post anterior: las variables son objetos usados para almacenar valores como los
resultados de cálculos.

En este caso usaremos dos variables. La primera será una de las variables internas que ya
proporciona JasperReports: PAGE_NUMBER, que nos dice el número de la página actual. En este
caso como el reporte solo tendrá una página solo aparecerá el número 1, pero pueden extender el
ejemplo para que se generen más páginas.

La segunda variable que usaremos será una variable creada por nosotros mismos y nos mostrará
la suma de los puntos de los Participantes (en este momento los Participantes no tienen
puntos, por lo que tendremos que agregarlos).

Lo primero que haremos es modificar la clase "Participante" agregando el atributo "puntos" de


tipo "int" con sus correspondientes setters y getters:

private int puntos;


public int getPuntos()

{
return puntos;
}

public void setPuntos(int puntos)

{
this.puntos = puntos;
}

y en nuestro método "main" agregamos, en el ciclo que crea los objetos "Participante", el
siguiente código para establecer los puntos de cada uno de los Participantes:

p.setPuntos(i);

Ahora regresamos a iReport y agregamos un nuevo Field en la ventana "Report Inspector"


llamado "puntos" de tipo "java.lang.Integer". Este field será usado para mostrar los
puntos que tiene cada uno de los Participantes.

Agregamos una columna, dentro de la banda "Details 1", para mostrar este field:
Si compilamos nuestro reporte y ejecutamos nuestra aplicación Java debemos ver un reporte con
el siguiente contenido:

Ahora agregaremos la variable que realizará la suma de los puntos de todos los Participantes.
Para esto agregamos una nueva variable en el nodo "Variables" de la ventana "Report
Inspector" haciendo clic derecho sobre este nodo y seleccionando la opción "Add Variable"
del menú contextual que se abre.
Modificamos sus propiedades en la ventana "Properties" cambiando su nombre a
"sumaPuntos", su "Variable Class" a "java.lang.Integer", y "Calculation" a "Sum"
(con esto indicamos que la variable mantendrá la suma de los valores que indicaremos más
adelante, otras opciones incluyen un contador, el promedio, el valor más alto, etc.).

Ahora indicaremos la suma de cuáles valores son los que queremos que se almacene en este
variable. Para eso hacemos clic en el botón "..." de la propiedad "Variable Expression", con
lo que se abrirá una nueva ventana. Es esta nueva ventana indicaremos de dónde se tomarán los
valores para la suma. Podemos usar una expresión tan compleja como necesitemos. Como en este
caso solo queremos realizar la suma de los puntos escribimos "F{puntos}". Y presionamos el
botón "OK" para confirmar.
Al final las propiedades de nuestra variable deben quedar así:

Ahora solo arrastramos nuestra variable "sumaPuntos" desde el "Report Inspector" hasta la
banda "Summary". Esta banda se muestra cuando ya se han mostrado todos los datos de la banda
"Details 1" y se muestra justo abajo de ella.

Agregaré un texto estático y una línea en esta banda solo para que se vea un poco mejor. Nuestro
reporte hasta ahora debe verse así:
Ahora para terminar agregaremos la variable "PAGE_NUMBER" que nos dice el número de página
actual en el reporte. Arrastramos esta variable desde el "Report Inspector" hasta la banda
"Page Footer", la cual se muestra en la parte inferior de cada página.

Podría parecer un poco extraño que la banda "Summary" que se encuentra abajo de la banda
"Page Footer" en el designer vaya a aparecer antes en el reporte final, pero confíen en mi, así
será ^_^.

Agregaré también un texto estático solo para indicar que el valor que estamos mostrando
corresponde al número de página. Al final el reporte queda así:

Ahora guardamos y compilamos nuestro reporte y ejecutamos nuestra aplicación desde el


NetBeans. El reporte generado debe verse así:
Como podemos ver, la variable "sumaPuntos" contiene la suma de los puntos de todos los
participantes (55).

Nuestra clase "Participante" queda de la siguiente forma:

public class Participante

{
private int id;
private String nombre;
private String username;
private String password;
private String comentarios;
private int puntos;

public Participante()
{
}

public Participante(int id, String nombre, String username, String


password, String comentarios)
{
this.id = id;
this.nombre = nombre;
this.username = username;
this.password = password;
this.comentarios = comentarios;
}
public String getComentarios()
{
return comentarios;
}

public void setComentarios(String comentarios)


{
this.comentarios = comentarios;
}

public int getId()


{
return id;
}

public void setId(int id)


{
this.id = id;
}

public String getNombre()


{
return nombre;
}

public void setNombre(String nombre)


{
this.nombre = nombre;
}

public String getPassword()


{
return password;
}

public void setPassword(String password)


{
this.password = password;
}

public String getUsername()


{
return username;
}

public void setUsername(String username)


{
this.username = username;
}

public int getPuntos()


{
return puntos;
}
public void setPuntos(int puntos)
{
this.puntos = puntos;
}
}

y nuestra clase "Main" de la siguiente forma (omitiendo los imports):

public class Main

{
public static void main(String[] args) throws Exception
{
List<Participante> listaPariticipantes = new
ArrayList<Participante>();
for (int i = 1; i <= 10; i++)
{
Participante p = new Participante(i, "Particpante " + i,
"Usuario " + i, "Pass " + i, "Comentarios para " + i);
p.setPuntos(i);

listaPariticipantes.add(p);
}

JasperReport reporte = (JasperReport)


JRLoader.loadObject("reporte2.jasper");
Map<String, String> parametros = new HashMap<String, String>();
parametros.put("autor", "Juan");

parametros.put("titulo", "Reporte Participantes");

JasperPrint jasperPrint = JasperFillManager.fillReport(reporte,

parametros, new JRBeanCollectionDataSource(listaPariticipantes));

JRExporter exporter = new JRPdfExporter();

exporter.setParameter(JRExporterParameter.JASPER_PRINT,

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

exporter.exportReport();
}
}
Para terminar solo recuerden: los parámetros son expresiones que nos permiten pasar valores,
desde nuestra aplicación Java, a los reportes generador por JasperReports. Y las variables
almacenan valores que son el resultado de cálculos de distinta naturaleza sobre los valores que
recibimos en nuestro reporte.
Algunas veces es más fácil entender la información cuando se nos presenta en una imagen. En el
caso de los datos, cuando estamos haciendo comparaciones, lo más fácil es visualizarlos en una
gráfica de barras o en una gráfica de pie o pastel. En este tutorial mostraré cómo podemos colocar
gráficas en nuestros reportes para hacer comparaciones de un conjunto de datos.

Para este ejemplo los datos que graficaremos son las ventas de consolas de última generación
(Wii, XBox360, y PS3). Tomaremos estos datos de VG Chartz que, aunque no son cifras oficiales,
mantiene sus datos actualizados. En el momento de escribir este tutorial las ventas van:

 Wii: 48.79% para nosotros será 49%


 XBox 360: 29.63% para nosotros será 30%
 PS3: 21.57% para nosotros será 21%

Nota: Recientemente han aparecido las versiones 3.5 de JasperReports y iReports, por lo que comenzaré a
usarlos a partir de este tutorial. La configuración de la biblioteca JasperReports que creamos en este
tutorial y el uso de iReport para lo que hemos hecho hasta ahora es igual, por lo que todo lo que hemos
hecho servirá.

Bien, para comenzar crearemos un nuevo proyecto Java standalone en NetBeans (File -> New
Project... -> Java -> Java Application), le asignamos un nombre (que en mi caso
será ReporteGrafica) y presionamos el botón "Finish" para que el nuevo proyecto se genere y
veamos en el editor nuestra clase Main.

Agregamos al nodo "Libraries" de nuestro proyecto la biblioteca "JasperReports" que


creamos en la primer parte del tutorial y el jar "commons-logging-1.1.1.jar",como lo
hemos venido haciendo hasta ahora.

Adicionalmente debemos agregar dos jars más que nos permitirán generar las gráficas. Puesto que
JasperReports hace uso de JFreeChart para generar las gráficas debemos agregar dos de sus jars:
jfreechart.jar y jcommon.jar. Si bajaron JasperReports en el archivo .zip que contiene las
bibliotecas de soporte entonces ya tienen estos jars (que se encuentran en el directorio lib del .zip
anterior), solo deben agregarlos al nodo "Libraries" del proyecto.

Ahora necesitamos, como en los casos anteriores, una clase cuyas instancias mantendrán los
datos que mostraremos en el reporte. En este caso, como estamos hablando de consolas, creo
que lo más adecuado es que esta sea una clase "Jugador". Así que agreguemos esta clase a
nuestro proyecto.

Esta clase tendrá tan solo tres atributos: un id (que en este caso podría no ser necesario, pero es
para no perder la costumbre, cuando veamos algo de Hibernate veremos que es mejor
acostumbrarnos desde el prinicpio a poner este id), un nombre para distinguir al usuario, y el
nombre de la consola que tiene (que es el dato que nos interesa para crear la gráfica).

El código de la clase Jugador queda de la siguiente forma:


public class Jugador
{
private int id;
private String nombre;
private String consola;

public Jugador(int id, String nombre, String consola)


{
this.id = id;
this.nombre = nombre;
this.consola = consola;
}

public String getConsola()


{
return consola;
}

public void setConsola(String consola)


{
this.consola = consola;
}

public int getId()


{
return id;
}

public void setId(int id)


{
this.id = id;
}

public String getNombre()


{
return nombre;
}

public void setNombre(String nombre)


{
this.nombre = nombre;
}
}
El código de la clase Main es el código estandar que hemos estado usando en esta serie de
tutoriales de JasperReports, con excepción de la parte en la que se crean los Jugadores. En este
caso usaremos tres ciclos, uno para cada consola. Por lo que esta parte del código queda más o
menos así (listaJugadores es una lista de objetos Jugador):

for (int i = 1; i <= 49; i++)


{
listaJugadores.add(new Jugador(i, "Jugador " + i , "Wii"));
}

for(int i = 50; i <= 79; i++)


{
listaJugadores.add(new Jugador(i, "Jugador " + i , "XBox"));
}

for(int i = 80; i <= 100; i++)


{
listaJugadores.add(new Jugador(i, "Jugador " + i , "PS3"));
}
Ahora abriremos el iReport y comenzaremos con el diseño de nuestro reporte. El nuevo iReport
(3.5.0) muestra los menús en el mismo idioma que nuestro sistema operativo, que en mi caso es
español, por lo que apartir de ahora colocaré los nombres de las opciones y los menús en español
(en el caso en el que los muestre así, si alguno se muestra en inglés colocaré el nombre en inglés).

Creamos un nuevo reporte vacio llendo al menú Archivo -> New... -> Empty Report. En
la ventana que se abre colocamos el nombre de nuestro reporte (reporteGrafica.jrxml) y lo
guardamos en el directorio raíz de nuestro proyecto de NetBeans:

Comencemos colocando un título y los encabezados de nuestras columnas de datos usando textos
estáticos, así como los fields para los datos que obtendremos de cada uno de los objetos
Jugador (id, nombre, y consola) de la misma forma que lo hicimos en este tutorial (no olviden
guardar de forma constante sus avances para no perder su trabajo):

Ahora vienen los pasos interesantes. Primero debemos crear un grupo. Un grupo nos permite tratar
de forma especial un conjunto de datos que se encuentran asociados (es como un group by en
SQL). Además, al crear un grupo se genera también una variable que mantiene el conteo de los
elementos de cada grupo (como si hicieramos un count sobre los elementos de los grupos en
SQL).

En este caso el grupo que nos interesa es el de las consolas.

Si estuvieramos usando consultas SQL obtener estos datos sería sencillo. Es más, si hubieramos
creado nuestro reporte usando el "Report Wizard" podríamos haber creado el grupo que nos
interesa desde ahi. Pero como estamos usando un DataSource propio, tenemos que agregar el
grupo a mano. Afortunadamente es muy sencillo agregar grupos desde iReport. Lo único que
debemos hacer es click derecho sobre el nodo "report name" (la raíz de los elementos del
proyecto) en el panel "Report Inspector". Con esto se abrirá un menú contextual. De este
seleccionamos el elemento "Add Report Group":
Al hacer esto se abrirá la ventana del "Group Wizard". En esta colocamos el nombre del grupo,
en este caso será CONSOLAS, y en el campo "Group by the following report object:"
seleccionamos el field "consola" que creamos anteriormente. Con esto conseguiremos que el
nuevo grupo que se creará se haga con respecto al valor del atributo "cosola" de nuestros objeto
"Jugador".

Presionamos el botón "Siguiente >" y se nos mostrarán dos radio buttons preguntando si
quieremos agregar la cabecera (header) y el pie de pagina (footer) del grupo. Nosotros
deseleccionamos estas opciones (se encuentran seleccionadas por default) ya que no nos interesa
agregar ninguno de estos elementos. Para terminar presionamos el botón "Finalizar" y ya
tendremos agregado nuestro grupo ^-^.

No es muy obvio el que este grupo existe, de hecho los unicos indicadores que tenemos son que
se han agregado en la zona de las bandas del "Report Inspector" dos nuevas bandas:
"CONSOLAS Group Header" y "CONSOLAS Group Footer", además se ha agregado una
variable llamada "CONSOLAS_COUNT", que es la variable que nos interesa y por la que hemos
creado el grupo, que mantendrá el número de jugadores que tienen cada una de las consolas:
Ahora agregaremos nuestra gráfica. Para eso arrastraremos desde la Paleta de elementos del
reporte un "Chart" y lo colocamos en la banda "Summary" (ajusten el tamaño de la banda para
que la gráfica se vea bien).

Al arrastrar la gráfica se abrirá una nueva ventana preguntándonos qué tipo de gráfico queremos
mostrar. En este caso seleccionaremos el gráfico de pie o de pastel (la primer o segunda opción):
Presionamos el botón "OK" y la gráfica se agregará a nuestro reporte, ajustenla para que abarque
toda el área de la banda.

Lo último que haremos es configurar la gráfica para que obtenga los datos de los campos y
variables que nos interesa mostrar. Para esto, hacemos click derecho sobre la gráfica, con lo que
se abrirá un menú contextual. En este menú seleccionamos la opción "Chart Data".
Con lo que se abrirá una nueva ventana, y en esta ventana seleccionamos la pestaña "Details".
En esta pestaña configuraremos tres valores:

 Key expression
 Value expression
 Label expression

Nota: Dependiendo del tipo de gráfica que estemos haciendo puede que debamos agregar más valores, pero
para los gráficos de pie solo son necesarios estos.

La "Key expression" dice cuál será la base que se usará para cada uno de las piezas de la
gráfica. En nuestro caso queremos que cada trozo muestre las consolas. Por lo que colocamos
como valor $F{consola}.

La "Value expression" dice cuál será el tamaño de cada una de las piezas de la gráfica.
Nosotros queremos que cada pieza sea equivalente al número de consolas que se han comprado.
Por lo que colocamos como valor $V{CONSOLAS_COUNT}.

Label expression es la etiqueta que se mostrará para cada valor. Nosotros queremos mostrar
el nombre de la consola junto con el número de unidades que se han vendido de cada una. Por lo
que colocamos como valor $F{consola} + " - " + $V{CONSOLAS_COUNT}. Lo cual colocará
como valor el nombre de la consola, concatenándole el signo " - " y concatenándole el número de
consolas vendidas (el número de jugadores que han comprado cada una de las consolas).

Esta ventana queda de la siguiente forma:


Presionamos el botón "Close" y hemos terminado con nuestro reporte. Cambiamos a la vista
"Preview" para compilar el reporte. No se nos mostrará nada del reporte final. De hecho los
regresará a la vista del "Designer" y mostrará una excepción en la ventana de salida indicando
algo así: "Key is null in pie dataset". Esto es normal ya que la gráfica no puede
generarse ya que no existen datos. Lo importante es que se haya generado el archivo
"reporteGrafica.jasper".

Ahora ejecutamos nuestra aplicación, con lo que debe generarse nuestro reporte en PDF y
debemos ver, al final del reporte, la siguiente gráfica:

Con lo que comprobamos la gráfica se ha


creado correctamente ^-^.

Finalmente este es el codigo de la clase Main (omitiendo los imports):


public class Main
{
public static void main(String[] args) throws Exception
{
List listaJugadores = new ArrayList();

for (int i = 1; i <= 49; i++)


{
listaJugadores.add(new Jugador(i, "Jugador " + i , "Wii"));
}

for(int i = 50; i <= 79; i++)


{
listaJugadores.add(new Jugador(i, "Jugador " + i , "XBox"));
}

for(int i = 80; i <= 100; i++)


{
listaJugadores.add(new Jugador(i, "Jugador " + i , "PS3"));
}

JasperReport reporte =
(JasperReport)JRLoader.loadObject("reporteGrafica.jasper");
JasperPrint jasperPrint = JasperFillManager.fillReport(reporte,
null, new JRBeanCollectionDataSource(listaJugadores));

JRExporter exporter = new JRPdfExporter();


exporter.setParameter(JRExporterParameter.JASPER_PRINT,
jasperPrint);
exporter.setParameter(JRExporterParameter.OUTPUT_FILE, new
File("reporte grafica.pdf"));

exporter.exportReport();
}
}
Creación de Reportes con JasperRepots y iReports -
Parte 7: Subreportes
Los subreportes son una característica importante de una herramienta generadora de reportes.
Permiten crear reportes más complejos y simplificar el trabajo de diseño.

Los subreportes son muy útiles cuando se crea un reporte maestro de detalles o cuando la
estructura de un solo reporte no es suficiente para describir la complejidad del documento de salida
deseado.

Un subreporte es solamente un reporte que ha sido incorporado a otro reporte. De hecho podemos
tener subreportes dentro de otros subreportes.

En este último tutorial de la serie de JasperReports y iReports veremos cómo crear subreportes
haciendo uso de estas dos herramientas. Veremos dos ejemplos, el primero mostrará cómo hacer
los subreportes mediante una conexión JDBC a la base de datos. El segundo mostrará como
hacerlo con un DataSource propio.

En ambos casos crearemos un reporte de alumnos de una escuela y subreportes de cada uno de
los alumnos con la lista de materias que tiene cada uno (aunque por facilidad todos tendrán las
mismas materias cuando hagamos el ejemplo con el DataSource propio).

1 - Subreportes con conexión a base de datos

Lo primero que haremos es generar una base de datos de prueba. Yo hare uso de MySql 5.1, pero
pueden usar el manejador que más les guste. Creamos una base de datos llamada
"pruebaReportes" y usamos el siguiente script para crear la tabla "alumnos":
CREATE TABLE `alumnos` (
`ID` bigint(21) NOT NULL,
`NOMBRE` varchar(100) NOT NULL,
`CLAVE` varchar(100) NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
después este para las materias:

CREATE TABLE `materias` (


`ID` BIGINT(21) NOT NULL,
`NOMBRE` VARCHAR(100) NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=INNODB DEFAULT CHARSET=latin1

y finalmente esta será la tabla intermedia, o tabla de unión de las dos anteriores (ya que se
generará una relación N:M entra ambas):

CREATE TABLE `alumnos_materias` (


`ALUMNO_ID` BIGINT(21) NOT NULL,
`MATERIA_ID` BIGINT(21) NOT NULL,
PRIMARY KEY (`ALUMNO_ID`, `MATERIA_ID`),
FOREIGN KEY (`ALUMNO_ID`) REFERENCES `alumnos` (`ID`),
FOREIGN KEY (`MATERIA_ID`) REFERENCES `materias` (`ID`) )
ENGINE=INNODB DEFAULT CHARSET=latin1

Ahora que tenemos las tablas usaremos el siguiente script para llenarlas:

INSERT INTO alumnos VALUES (1, 'Alumno 1', '00001');


INSERT INTO alumnos VALUES (2, 'Alumno 2', '00002');
INSERT INTO alumnos VALUES (3, 'Alumno 3', '00003');
INSERT INTO alumnos VALUES (4, 'Alumno 4', '00004');
INSERT INTO alumnos VALUES (5, 'Alumno 5', '00005');
INSERT INTO alumnos VALUES (6, 'Alumno 6', '00006');
INSERT INTO alumnos VALUES (7, 'Alumno 7', '00007');
INSERT INTO alumnos VALUES (8, 'Alumno 8', '00008');
INSERT INTO alumnos VALUES (9, 'Alumno 9', '00009');
INSERT INTO alumnos VALUES (10, 'Alumno 10', '000010');

INSERT INTO materias VALUES (1, 'Matematicas');


INSERT INTO materias VALUES (2, 'Fisica');
INSERT INTO materias VALUES (3, 'Quimica');
INSERT INTO materias VALUES (4, 'Biologia');
INSERT INTO materias VALUES (5, 'Historia');
INSERT INTO materias VALUES (6, 'Geografia');

INSERT INTO alumnos_materias VALUES (1, 1);


INSERT INTO alumnos_materias VALUES (1, 3);
INSERT INTO alumnos_materias VALUES (1, 5);

INSERT INTO alumnos_materias VALUES (2, 1);


INSERT INTO alumnos_materias VALUES (2, 2);
INSERT INTO alumnos_materias VALUES (2, 3);

INSERT INTO alumnos_materias VALUES (3, 2);


INSERT INTO alumnos_materias VALUES (3, 4);
INSERT INTO alumnos_materias VALUES (3, 6);

INSERT INTO alumnos_materias VALUES (4, 4);


INSERT INTO alumnos_materias VALUES (4, 5);
INSERT INTO alumnos_materias VALUES (4, 6);

INSERT INTO alumnos_materias VALUES (5, 1);


INSERT INTO alumnos_materias VALUES (5, 4);
INSERT INTO alumnos_materias VALUES (5, 5);

INSERT INTO alumnos_materias VALUES (6, 2);


INSERT INTO alumnos_materias VALUES (6, 5);
INSERT INTO alumnos_materias VALUES (6, 6);

INSERT INTO alumnos_materias VALUES (7, 1);


INSERT INTO alumnos_materias VALUES (7, 3);
INSERT INTO alumnos_materias VALUES (7, 5);

INSERT INTO alumnos_materias VALUES (8, 1);


INSERT INTO alumnos_materias VALUES (8, 2);
INSERT INTO alumnos_materias VALUES (8, 3);

INSERT INTO alumnos_materias VALUES (9, 2);


INSERT INTO alumnos_materias VALUES (9, 4);
INSERT INTO alumnos_materias VALUES (9, 6);

INSERT INTO alumnos_materias VALUES (10, 4);


INSERT INTO alumnos_materias VALUES (10, 5);
INSERT INTO alumnos_materias VALUES (10, 6);

Ya con los datos listos procedemos a crear el proyecto en NetBeans ("File -> New
Project... -> Java -> Java Application"). Con lo que se creará una clase Main que
aparecerá en nuestro editor.

Por el momento dejaremos así el proyecto de NetBeans y procederemos a crear la plantilla de


nuestro reporte desde iReport.

Como en esta ocasión tenemos una base de datos, usaremos el "Report Wizard", por lo que
vamos al menú "Archivo -> New.. -> Report Wizard". Con esto se abrirá el wizard de 7
pasos que expliqué en el primer tutorial.

El paso 2 (en el que empieza el wizard) nos pide dar un nombre al archivo del reporte y una
ubicación. Denle el nombre que gusten (en mi caso "reporteMaestro.jrxml") y guardenlo en la
carpeta raíz del proyecto de NetBeans que acabamos de crear.

Presionamos el botón "Siguiente >" para ir la paso 3. Aquí debenos seleccionar el Data Source
que se usará para generar el reporte. Si ya tienen creado el datasource para la base de datos
"pruebaReportes" pueden seleccionarla aqui. Sino no se preocupen, este es el momento para
crearlo.

Para crear el datasource que usaremos hacelos click en el botón "New":

Esto abrirá una ventana en la que tendremos que seleccionar el tipo de Datasource que queremos
usar. En nuestro caso será un "Database JDBC connection" (la primer opción).
Presionamos el botón "Next >". En la siguiente pantalla debemos darle un nombre y algunos
parámetros al datasource, como la dirección del servidor y el nombre de la base de datos.

Para probar que la conexión puede establecerse, hagan click en el botón "Test" y, si todo estpa
bien, debe aparecer un mensaje como el siguiente:
Si obtuvieron el mensaje anterior hagan click en "Aceptar" y posteriormente en el botón "Save"
para guardar el datasource.

Veremos que en la ventana del paso 3 del "Report Wizard" ahora tenemos un textarea que nos
indica que debemos introducir un query. Pueden usar el query designer si gustan (haciendo click
en el botón "Design Query") para crear la query que usaremos para obtener todos los datos de la
tabla "alumnos" (solo de esa tabla). Al final la query debe ser más o menos así:

SELECT
alumnos.`ID` AS alumnos_ID,
alumnos.`NOMBRE` AS alumnos_NOMBRE,
alumnos.`CLAVE` AS alumnos_CLAVE
FROM
`alumnos` alumnos

Hacemos click en el botón "Siguiente >" para ir al paso 4. En este paso tendremos que
seleccionar los campos, de los que acabamos de seleccionar, que queremos mostrar en el reporte.
En este caso solo queremos mostrar el nombre y la clave del alumno (el id lo usaremos como un
elemento auxiliar para obtener los datos del subreporte, por lo que es necesario que también lo
releccionemos). Por lo que seleccionamos todos los campos:
Presionamos el botón "Siguiente >". En el paso 5 podemos seleccionar un campo sobre el que
queramos crear un grupo. Nosotros no queremos crear ninguno, por lo que dejamos todo como
está y presionamos el botón "Siguiente >" para ir al paso 6 en el que seleccionaremos el layout
del reporte. La opción por defecto ("Columnar Layout") esta bien, por lo que la dejamos y
hacemos click en "Siguiente >" para ir al paso final en el que nos felicitarán por haber creado
exitosamente nuestro reporte ^-^!.

Ahora podemos hacer click en el botón "Finalizar" para ver aparecer la plantilla de nuestro
reporte, en la pestaña "Designer", el cual debe verse de la siguiente forma:

Modificaremos los textos estáticos para que concuerden un poco más con el tipo de reporte que
queremos lograr. También eliminaremos las etiqueta y el texto que muestran el valor de id ya que,
como dijimos hace un momento, no nos interesa mostrarlo:
Si generamos la vista previa del reporte veremos lo siguiente:

No es el mejor reporte pero es un principio ^-^. Ahora procederemos a agregar el subreporte. Este
subreporte mostrará las materias a las que esta inscrito cada uno de los alumnos.

Para esto arrastramos el elemento "Subreport" desde los "Report Elements" y lo colocamos
en la banda details, justo debajo de los campos de texto:

Al hacer esto se abrirá la ventana del "Subreport Wizard" que es la que nos guiará en el
proceso de la creación del subreporte:

El primer paso consiste en indicar si nuestro subreporte será un reporte nuevo, uno existente, o si
solo queremos crear el elemento subrepote. Nosotros crearemos un nuevo reporte (que es el que
mostrará las materias a las que está inscrito cada alumno), así que dejamos seleccionada la
primera opción ("Create a new report") y hacemos click en el botón "Siguiente >".

En el paso 2 se nos preguntara qué datasource usaremos para este reporte. Nosotros usaremos el
datasource creado hace unos momentos (que en mi caso se llamaba "Prueba Reportes").
Seleccionamos este en el menú desplegable, con los que nos aparecerá un textarea para que
coloquemos una query. Pueden usar el query designer si gustan para obtener una query que
seleccione todos los campos de las tablas "alumnos_materias" y "materias" y haga un join
entre estas (que obtenga las materias que tiene cada alumno). La query final queda de la siguiente
forma:

SELECT
alumnos_materias.`ALUMNO_ID` AS alumnos_materias_ALUMNO_ID,
alumnos_materias.`MATERIA_ID` AS alumnos_materias_MATERIA_ID,
materias.`ID` AS materias_ID,
materias.`NOMBRE` AS materias_NOMBRE
FROM
`materias` materias INNER JOIN `alumnos_materias` alumnos_materias ON
materias.`ID` = alumnos_materias.`MATERIA_ID`

Presionamos el botón "Siguiente >" para ir al paso 3, en el que se nos preguntará qué campos de
los regresados por la consulta queremos mostrar en el reporte (o en este caso en el subreporte). A
nosotros solo nos interesa mostrar los campos que tienen que ver con la materia, por lo que solo
seleccionamos los campos "materias_NOMBRE" y "materias_ID":

Presionamos en botón "Siguiente >" para ir al paso 4. En este paso podemos elegir si
queremos crear un grupo, como nosotros no queremos crear ninguno, simplemente dejamos todo
como está y volvemos a presionar el botón "Siguiente >".

En el paso 5 podemos elegir el layout del reporte. Puden seleccionar el que quieran. En mi caso
dejaré la opción por default ("Columnar Layout") y presionamos el botón "Siguiente >".

En el paso 6 podemos darle un nombe y una ubicación al subreporte. Yo le llamaré


"subreporteMaterias.jrxml" y lo guardaré en el mismo directorio que el
"reporteMaestro.jrxml" (en la carpeta raíz del proyecto de NetBeans). También podemos
ejegir si queremos guardar la ruta del subreporte (para que el reporte maestro sepa donde
buscarlo) como un parámetro llamado $P{SUBREPORT_DIR}, o como una ruta absoluta estática.
Lo mejor es elegir está ultima ya que modificaremos la ruta para que busque el subreporte en en el
mismo directorio que el reporte maestro. Así si los movemos de un directorio a otro, solo
tendremos que preocuparnos de llevarnos los dos juntos.

Presionamos una vez más el botón "Siguiente >" para ir al ultimo paso.

En el paso final (el paso 7) debemos seleccionar cómo le pasaremos el datasource al subreporte
desde el reporte maestro. Tenemos 5 opciones:

 Usar la misma conexión que el reporte maestro


 Usar otra conexión
 Usar una expresión de un JRDataSource
 Usar un datasource vacio
 No usar conexión o datasource alguno

Nosotros seleccionamos la primera opción ya que queremos que el subreporte use la misma
conexión que el reporte maestro:
presionamos el botón "Finalizar" para mostrar el subreporte:

Modificamos un poco el diseño del reporte para que se vea bien al mostrarlo dentro del reporte
maestro (cambiamos unos textos, eliminamos otros, y eliminamos la banda "Page Footer",
también agregamos una línea en la banda "Summary" para identificar en el reporte final cuando
termine la lista de materias):

Ahora agregamos un nuevo parámetro al subreporte (click derecho en el nodo "Parameters" del
panel "Report Inspector" y seleccionamos "Añadir Parameter") llamado alumnos_ID de
tipo java.lang.Long.

Lo siguiente que haremos es el primero de los dos trucos para generar subreportes en base a
una conexión con base de datos: hacemos click sobre la ventana del designer, pero fuera del
reporte para que en el panel de propiedades aparezcan las propiedades del "subreporteMaterias".
Una vez en este panel buscamos la propiedad "Query Text" de la sección "More...":

Hacemos click en el botón "..." para que se abra una ventana que contiene el texto de la consulta
que creamos al crear el subreporte. Agregamos el final de la consulta lo siguiente:

AND alumnos_materias.`ALUMNO_ID`= $P{alumnos_ID}

Con esto lograremos que el subreporte se genere solo con las materias que correspondan al
alumno con el id que le indiquemos (lo cual haremos en un momento y que de hecho es el
segundo secreto).

Presionamos el botón "OK" para guardar la consulta.

Para terminar guardamos el subreporte y cambiamos a la vista "Preview" para compilar el reporte
y generar el archivo "subreporteMaterias.jasper". El preview debe verse más o menos así:
Ahora podemos regresar al reporteMaestro, el cual debe verse así (después de ajustar el tamaño
y la posición del componente subreporte):

Seleccionamos el elemento subreporte y en el panel de propiedades buscamos el elemento


"Subreport Expression" de la sección "Subreport Properties". Eliminamos la ruta
absoluta y dejamos solo el nombre del reporte ("subreporteMaterias.jasper"):

Ahora viene el segundo de los secretos para le generación de los subreportes usando conexión a
base de datos. Seleccionamos el componente del subreporte y buscamos en panel de propiedades
y buscamos la propiedad "Parameters" de la sección "Subreport Properties":
Hacemos click en el botón "..." con lo que se abrirá una ventana que nos permite agregar
parámetros que serán pasados del reporte maestro al subreporte.

Si recuerdan nosotros indicamos en el subreporte que queremos que muesre las materias en las
que está inscrito un alumno con un particular. Pues bien es aquí en donde pasamos ese dato, el id
del alumno del que se están mostrando los datos. Este parametro nos permitirá pasarle el valor al
parámetro "alumnos_ID" que agregamos en el subreporte.

Presionamos el botón "Add" y agregamos como nombre del parámetro "alumnos_ID" y como
valor "$F{alumnos_ID}":

Presionamos "OK" en ambas ventanas y listo, ya tenemos nuestro reporte maestro con subreportes
^-^.

Ahora guardamos el reporte y cambiamos a la vista de "Preview". Ahora debemos ver algo como
lo siguiente:
Con esto terminamos la parte que corresponde a iReport y podemos regresar al NetBeans.

Si lo recuerdan dejamos la clase Main vacia, ahora procederemos a llenarla con el código para
generar el reporte.

Recuerden que lo primero que debemos hacer es agregar al nodo "Libraries" del panel
"Projects" la biblioteca "JasperReports" que creamos en el primer tutorial de la serie, el jar
"commons-logging-1.1.1.jar", y el jar "mysql-connector-java-5.1.7-bin.jar" que es
el driver de la base de datos.

Una vez que tenemos esto, escribimos el siguiente códifo en el método main de la clase Main:
Class.forName("com.mysql.jdbc.Driver");
Connection conexion =
DriverManager.getConnection("jdbc:mysql://localhost:3306/pruebareportes",
"user", "pass");

JasperReport reporte = (JasperReport)


JRLoader.loadObject("reporteMaestro.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();

La explicación de este código está en el primer tutorial de esta serie.

Al ejecutarlo se creará el archivo "reportePDF.pdf" en el directorio raíz del proyecto. Si abrimos


el archivo veremos más o menos lo siguiente:
Con lo que comprobamos que el reporte, junto con su subreporte, se ha generado correctamente ^-
^. Ahora veremos cómo hacer esto mismo usando un DataSource propio.

2 - Subreportes con datasources propios

Para hacer un subreporte con un datasource propio también es necesario conocer un par de
secretos, los cuales revelaré un unos momentos.

Lo primero que haremos es crear un nuevo proyecto en NetBeans ("File -> New Project...
->Java -> Java Application"). Con lo que se creará una clase Main que aparecerá en
nuestro editor.

Recuerden que también debemos agregar al nodo "Libraries" del panel "Projects" la
biblioteca "JasperReports" que creamos en el primer tutorial de la serie y el jar "commons-
logging-1.1.1.jar"

Crearemos las clases que mantendrán los datos que mostraremos en el reporte ("Alumno" y
"Materia"). La clase "Alumno" tendrá solo los atributos "id", "clave" y "nombre" (con sus
correspondientes setters y getters):

public class Alumno


{
private int id;
private String clave;
private String nombre;

public Alumno()
{
}

public Alumno(int id, String clave, String nombre)


{
this.id = id;
this.clave = clave;
this.nombre = nombre;
}

public String getClave()


{
return clave;
}

public void setClave(String clave)


{
this.clave = clave;
}

public int getId()


{
return id;
}

public void setId(int id)


{
this.id = id;
}

public String getNombre()


{
return nombre;
}

public void setNombre(String nombre)


{
this.nombre = nombre;
}
}

La clase "Materia" tendrá los atributos "id" y "nombre":

public class Materia


{
private int id;
private String nombre;

public Materia()
{
}

public Materia(int id, String nombre)


{
this.id = id;
this.nombre = nombre;
}

public int getId()


{
return id;
}
public void setId(int id)
{
this.id = id;
}

public String getNombre()


{
return nombre;
}

public void setNombre(String nombre)


{
this.nombre = nombre;
}
}

Aún falta agregar algunas cosas a la clase "Alumno", pero dejaremos este proyecto a un lado por
el momento mientras creamos la plantilla de nuestro reporte desde iReport.

Abrimos el iReport y creamos un nuevo reporte vacio (menú Archivo -> New... -> Empty
report). Asignamos al reporte un nombre (que en mi caso será "reporteMaestroDS.jrxml") y
lo guardamos en la raíz del proyecto de NetBeans. Hacemos click en el botón "Finalizar" con lo
que veremos aparecer la plantilla vacia dentro de la vista "Designer".

Agregamos un par de fields (clave y nombre), y unos textos estáticos para que este reporte
maestro sea similar al anterior (eliminé algunas bandas para que el reporte se vea más claro):

Agregamos un field adicional llamado "materiasDS" de tipo


"net.sf.jasperreports.engine.JRDataSource". Como este tipo no aparece en el combo
para selección de tipo del field debemos escribirlo en la ventana que se abre al presionar el
botón "..." junto a este combo box:
Este field será el que dirá a JasperReports que debe llamar al getter correspondiente de la clase
Alumno que crearemos más adelante para preguntar a cuáles materias está inscrito (quedará claro
cuando escribamos el código Java).

Ahora agregamos arrastramos el elemento "Subreport" de los "Report Elements" a la banda


"Details":

Al hacer esto se abrirá la ventana "Subreport wizard". Como ahora no usaremos una conexión
no necesitamos un query, entonces no todos los pasos aplican.

En el primer paso seleccionamos si queremos crear un nuevo reporte que servirá de subreporte,
usar un reporte existente, o solo crear un elemento subreporte. Seleccionamos la primera opcion
("Create a new report") y presionamos el botón "Siguiente >".

En el paso 2 debemos seleccionar un datasource. Nosotros seleccionaremos el "Empty


datasource". Presionamos el botón "Siguiente >" para ir al paso 3, en el que debemos
seleccionar los fields que queremos agregar al subreporte. Como nosotros no estamos usando una
conexión, no tenemos fields para seleccionar, así que simplemente presionamos el botón
"Siguiente >".

En el paso 4 podemos escoger crear un grupo, aqui pasa lo mismo que en el paso 3 así que
seguimos adelante.

En el paso 5 seleccionamos un layout para el subreporte. Pueden seleccionar el que quieran, yo


usaré el "Columnar Layout". Presionamos el botón "Siguiente >".

Vamos al paso 6. Aquí le damos una ubicación y un nombre al proyecto. Le daré de nombre
"subreporteMateriasDS.jrxml". Lo guardamos en el mismo directorio que el
"reporteMaestroDS.jrxml". Además indicamos que queremos que la ruta del subreporte se
almacene en una referencia estática absoluta ("Use a static absolute path reference"):
Pulsamos el botón "Siguiente >" para ir al último paso.

En el paso 7 debemos indicar cómo queremos pasar los datos del reporte maestro al subreporte.
En este caso queremos usar una "JRDatasource expression" (la tercer opción),
seleccionamos esta opción y agregamos la expresión creada anteriormente ("$F{materiasDS}"),
que será la que nos permita conectar el reporte con el subreporte:

Presionamos el botón "Finalizar" con lo que aprecerá el subreporte en la vista de diseño:

Agregamos dos fields: uno para el identificador de la materia (de tipo java.lang.Integer), y
uno para el nombre de la materia (de tipo java.lang.String):
Ahora arreglamos un poco el diseño del subreporte para que se vea mejor: eliminamos la página
"Page Footer", agregamos los fields que acabamos de crear a la banda "Detail", y arreglamos
un poco el título. También agregamos una línea en la banda "Summary" para saber cuando termina
el subreporte:

Guardamos el reporte y cambiamos a la vista preview para compilar el subreporte. En la vista de


preview deberian ver algo asi (recuerden seleccionar que quieren usar el "Empty datasource"):

Ahora regresemos al reporteMaestro, el cual debe verse así (después de ajustar el tamaño y la
posición del componente subreporte):
Seleccionamos el elemento subreporte y en el panel de propiedades buscamos el elemento
"Subreport Expression" de la sección "Subreport Properties". Eliminamos la ruta
absoluta y dejamos solo el nombre del reporte ("subreporteMateriasDS.jasper"):

Esto es todo lo que se necestita hacer para generar el reporte, así que cambiaremos a la vista
"Preview" para compilar el reporte. Deben ver algo asi:

Ahora regresamos al proyecto de NetBeans.

Hace unos momentos creamos dos clases: "Alumno" y "Materia" y dijimos que aún les faltaba
algo: falta crear la relación entre un objeto alumno y las materias que tiene. Para esto agregaremos
un atributo de tipo java.util.List a la clase "Alumno" que mantendrá la lista de materias a las
que está inscrito el alumno (con sus correspondientes getters y setters). Además agregaremos un
método auxiliar que nos permitirá agregar las materias de una forma más simple:

private List materias = new ArrayList();


public List getMaterias()
{
return materias;
}

public void setMaterias(List materias)


{
this.materias = materias;
}

public void addMateria(Materia materia)


{
this.materias.add(materia);
}

Ahora viene el segundo secreto para crear subreportes con datasource propios: si lo recuerdan,
en el reporteMaestro agregamos un parémetro llamado "materiasDS" de tipo
"net.sf.jasperreports.engine.JRDataSource". Es por medio de este parámetro que el
reporte maestro pregunta a cada uno de los alumnos con cuáles materias está relacionado (a
cuáles está inscrito) para poder generar el subreporte.

Es el alumno el encargado de regresar esta información a JasperReports por medio de un getter,


que debe estár formado siguiente el patrón de getters como si tuviera un atributo llamado
"materiasDS" de tipo "net.sf.jasperreports.engine.JRDataSource". Por lo que el
método será de la siguiente forma:

public JRDataSource getMateriasDS() {


{
return new JRBeanCollectionDataSource(materias);
}
El código completo de la clase "Alumno" queda de la siguiente forma:

import java.util.ArrayList;
import java.util.List;
import net.sf.jasperreports.engine.JRDataSource;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;

/**
* @author Alex
*/

public class Alumno


{
private int id;
private String clave;
private String nombre;
private List materias = new ArrayList();

public Alumno()
{
}

public Alumno(int id, String clave, String nombre)


{
this.id = id;
this.clave = clave;
this.nombre = nombre;
}

public String getClave()


{
return clave;
}

public void setClave(String clave)


{
this.clave = clave;
}

public int getId()


{
return id;
}

public void setId(int id)


{
this.id = id;
}

public String getNombre()


{
return nombre;
}

public void setNombre(String nombre)


{
this.nombre = nombre;
}

public List getMaterias()


{
return materias;
}

public void setMaterias(List materias)


{
this.materias = materias;
}

public void addMateria(Materia materia)


{
this.materias.add(materia);
}

public JRDataSource getMateriasDS()


{
return new JRBeanCollectionDataSource(materias);
}
}

Este es todo el cambio que necesita la clase "Alumno" para que nuestros subreportes se generen
exitosamente.

Ahora regresaremos a la clase "Main". Aqui agregaremos 2 ciclos for, uno que creará las
instancias de "Alumno" y las agregará a la lista que posteriormente pararemos como DataSource y
JasperReports, y un ciclo interno que creará instancias de "Materia" y las relacionará con los
alumnos (todos los alumnos tendrán las mismas tres materias en este caso). Los cliclos quedán así
(listaAlumnos es un objeto List que mantendrá los objetos Alumno):

for (int i = 1; i <= 5; i++)


{
Alumno alumno = new Alumno(i, "0000" + i, "Alumno " + i);
listaAlumnos.add(alumno);

for (int j = 1; j <= 3; j++)


{
alumno.addMateria(new Materia(j, "Materia " + j));
}
}

El resto de la clase Main es el que hemos estado viendo a lo largo de la serie de tutoriales y que
está explicado detalladamente en el segundo tutorial. El código completo de Main es el siguiente
(omitiendo los imports):

public class Main


{
public static void main(String[] args) throws Exception
{
List listaAlumnos = new ArrayList();

for (int i = 1; i <= 5; i++)


{
Alumno alumno = new Alumno(i, "0000" + i, "Alumno " + i);
listaAlumnos.add(alumno);

for (int j = 1; j <= 3; j++)


{
alumno.addMateria(new Materia(j, "Materia " + j));
}
}

JasperReport reporte = (JasperReport)


JRLoader.loadObject("reporteMaestroDS.jasper");
JasperPrint jasperPrint = JasperFillManager.fillReport(reporte,
null, new JRBeanCollectionDataSource(listaAlumnos));

JRExporter exporter = new JRPdfExporter();


exporter.setParameter(JRExporterParameter.JASPER_PRINT,
jasperPrint);
exporter.setParameter(JRExporterParameter.OUTPUT_FILE, new
File("reporteMaestroDS.pdf"));
exporter.exportReport();
}
}
Esto generará un archivo llamado "reporteMaestroDS.pdf" en el directrio raíz del proyecto de
NetBeans. El archivo tendrá el siguiente contenido:

Con lo que comprobamos que el reporte maestro junto con sus subreportes se ha creado
correctamente ^-^.

Bien, esta es el último tutorial de la serie de JasperReports. Tal vez haga algunos otros post
referentes a JasperReports, pero serán aparte de la serie. Espero que todo les sea de utilidad.