En este tutorial voy a explicar como generar un reporte en PDF obteniendo la información de una base de datos, si eres realmente nuevo manejando Jasper Reports, te sugiero darle una leída a la introducción y al paso de parámetros.
El reporte que se generará en este tutorial contendrá un listado de facultades que pertenecen a una determinada universidad, esta información sacada de una base de datos.
La base de datos a utilizar es MySQL 5.0.45, así que es necesario agregar al classpath de tu proyecto el MySQL Conector, junto con todas las librerías necesarias (mencionadas en la introducción).
Una vez hecho esto, ha comenzar a codificar el JRXML, primero hay que crear el documento y pasarle dos parámetros, el primero es el id de la universidad que queremos generar el reporte, y el segundo parámetro es la url donde esta la imagen del logotipo de la universidad, hasta ahora tenemos.
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE jasperReport PUBLIC "//JasperReports//DTD Report Design//EN" "http://jasperreports.sourceforge.net/dtds/jasperreport.dtd">
<jasperReport
name="plantilla"
pageWidth="595"
pageHeight="842"
leftMargin="20"
rightMargin="20"
topMargin="20"
bottomMargin="20">
<parameter name="P_ID_UNIVERSIDAD" class="java.lang.String"/>
<parameter name="LOGO_URL" class="java.lang.String"/>
</jasperReport>
La estructura de la base de datos es muy simple, consta de dos tablas, una se llama Universidades y la otra se llama Facultades, la tabla Universidades solo tiene tres campos, el id, el nombre de la universidad y el domicilio, la tabla facultades contiene cinco campos, el id, facultad, director, total de alumnos y una relación a la tabla universidades, a continuación muestro el SQL de la base de datos.
--
-- Base de datos: `test`
--
-- --------------------------------------------------------
--
-- Estructura de tabla para la tabla `facultades`
--
CREATE TABLE `facultades` (
`id_facultad` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`id_universidad` int(10) UNSIGNED NOT NULL,
`facultad` varchar(200) NOT NULL,
`director` varchar(200) NOT NULL,
`alumnos` int(11) NOT NULL,
PRIMARY KEY (`id_facultad`),
KEY `id_universidad` (`id_universidad`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=10 ;
--
-- Volcar la base de datos para la tabla `facultades`
--
INSERT INTO `facultades` VALUES (1, 1, 'Facultad de Ingeniería y Tecnología', 'Pedro Mejia', 251);
INSERT INTO `facultades` VALUES (2, 1, 'Facultad de Artes y Comunicación', 'Imelda Torrez', 193);
INSERT INTO `facultades` VALUES (3, 1, 'Facultad de Ciencias de la Salud', 'Oscar Ochoa', 428);
INSERT INTO `facultades` VALUES (4, 1, 'Facultad de Educación', 'Lorena Mena', 173);
INSERT INTO `facultades` VALUES (5, 1, 'Facultad de Ciencias Sociales', 'Alfonso Reyes', 95);
INSERT INTO `facultades` VALUES (6, 1, 'Facultad de Teología', 'Emanuel Perez', 162);
INSERT INTO `facultades` VALUES (7, 2, 'Facultad de Comunicacion', 'Hector Solano', 320);
INSERT INTO `facultades` VALUES (8, 2, 'Facultad de Diseño', 'Sergio Monrroy', 245);
INSERT INTO `facultades` VALUES (9, 2, 'Facultad de Salud', 'Juana Salazar', 562);
-- --------------------------------------------------------
--
-- Estructura de tabla para la tabla `universidades`
--
CREATE TABLE `universidades` (
`id_universidad` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`nombre` varchar(200) NOT NULL,
`domicilio` varchar(250) NOT NULL,
PRIMARY KEY (`id_universidad`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ;
--
-- Volcar la base de datos para la tabla `universidades`
--
INSERT INTO `universidades` VALUES (1, 'Universidad de Montemorelos', 'Montemorelos NL MX');
INSERT INTO `universidades` VALUES (2, 'Tecnológico de Monterrey', 'Monterrey NL MX');
INSERT INTO `universidades` VALUES (3, 'Universidad del Valle de Mexico', 'Mexico DF MX');
INSERT INTO `universidades` VALUES (4, 'Universidad Regiomontana', 'Monterrey NL MX');
--
-- Filtros para las tablas descargadas (dump)
--
--
-- Filtros para la tabla `facultades`
--
ALTER TABLE `facultades`
ADD CONSTRAINT `facultades_ibfk_1` FOREIGN KEY (`id_universidad`) REFERENCES `universidades` (`id_universidad`) ON DELETE CASCADE ON UPDATE CASCADE;
El siguiente paso es hacer el Query con el que se llenará la información, en este caso será el siguiente.
SELECT U.nombre AS universidad, U.domicilio, CURDATE( ) AS fecha, F.facultad, F.director, F.alumnos
FROM facultades F, universidades U
WHERE U.id_universidad = F.id_universidad
AND U.id_universidad =1
He sacado la fecha del sistema para mostrar como dar formato a una fecha en JasperReport. Ahora hay que introducir el Query al reporte y pasarle el parámetro necesario para que podamos sacar dinámicamente, desde Java, la universidad que queramos.
<queryString><![CDATA[
SELECT U.nombre AS universidad, U.domicilio, CURDATE() AS fecha, F.facultad, F.director, F.alumnos
FROM facultades F, universidades U
WHERE U.id_universidad = F.id_universidad
AND U.id_universidad = $P{P_ID_UNIVERSIDAD}]]>
</queryString>
<field name="universidad" class="java.lang.String"/>
<field name="domicilio" class="java.lang.String"/>
<field name="fecha" class="java.util.Date"/>
<field name="facultad" class="java.lang.String"/>
<field name="director" class="java.lang.String"/>
<field name="alumnos" class="java.lang.Integer"/>
La etiqueta es la que almacena el Query que se ejecutará cuando el reporte sea mandado a llenar desde Java. Algo importante a mencionar es que se han creado varias field (campos), uno para cada campo regresado por el Query, el name de cada campo debe coincidir con los capos o alias devueltos por el Query, de esta manera se puede accesar a la información y colocarla en el reporte.
Como he mencionado en la introducción hay varias secciones en un reporte, y una de ellas es el background, hasta ahora no he mencionado nada sobre esta sección, pero como su nombre lo indica, esta sección es el fondo del documento, aquí se puede poner la plantilla de la empresa, o cualquier cosa, en este caso se pondrá una imagen que es el logotipo de la universidad, todo esto resumido en código queda de la siguiente manera.
<background>
<band height="41">
<image>
<reportElement
x="500"
y="0"
width="33"
height="38"/>
<imageExpression class="java.lang.String"><![CDATA[$P{LOGO_URL}]]></imageExpression>
</image>
</band>
</background>
Para poner una imagen se utiliza la etiqueta <image> y la url se le pasa mediante el parámetro $P{LOGO_URL}.
La siguiente sección es el titulo del documento, aquí se pondra con letras grandes el nombre de la universidad, el domicilio y la fecha en que se ha generado el reporte, además de una línea divisoria, esto se hace de la siguiente manera.
<title>
<band height="70">
<textField>
<reportElement
x="0"
y="20"
width="530"
height="30"/>
<textElement>
<font pdfFontName="Helvetica-Bold" size="20" isBold="true"/>
</textElement>
<textFieldExpression class="java.lang.String"><![CDATA[$F{universidad}]]></textFieldExpression>
</textField>
<line direction="TopDown">
<reportElement
x="0"
y="49"
width="530"
height="0"
key="line"/>
<graphicElement stretchType="NoStretch"/>
</line>
<textField>
<reportElement
x="0"
y="50"
width="250"
height="20"
key="textField"/>
<textElement>
<font pdfFontName="Helvetica-Bold" size="10"/>
</textElement>
<textFieldExpression class="java.lang.String"><![CDATA[$F{domicilio}]]></textFieldExpression>
</textField>
<textField pattern="EEEEE dd MMMMM yyyy">
<reportElement
x="260"
y="50"
width="270"
height="20"
key="textField"/>
<textElement textAlignment="Right">
<font pdfFontName="Helvetica-Bold" size="10"/>
</textElement>
<textFieldExpression class="java.util.Date"><![CDATA[$F{fecha}]]></textFieldExpression>
</textField>
</band>
</title>
No me voy a detener a explicar la parte de la interface pues esto lo he explicado en el paso de parámetros a un reporte, lo que si hay que tomar en cuenta es que a diferencia del tutorial anterior, ahora, en lugar de imprimir parámetros se esta imprimiendo lo que proviene de la base de datos, mediante $F{universidad}, mediante el operador $F{} se accesa a los campos declarados en el Query, únicamente se escribe dentro de las llaves el nombre del campo a acceder.
Otra diferencia a notar es que al textfield de la fecha se le agrego una propiedad pattern=”EEEEE dd MMMMM yyyy”, este patrón se puede cambiar al gusto, es posible poner algo como “dd/MM/yyyy” para desplegar la fecha en formato “21/10/2008″.
Ahora la última parte interesante de este tutorial es la sección “detail”. Es aquí donde se desplegará la información del reporte, esta queda de la siguiente manera.
<detail>
<band height="15">
<textField>
<reportElement x="0" y="0" width="200" height="13"/>
<textFieldExpression class="java.lang.String">
<![CDATA[$F{facultad}]]>
</textFieldExpression>
</textField>
<textField>
<reportElement x="205" y="0" width="200" height="13"/>
<textFieldExpression class="java.lang.String">
<![CDATA[$F{director}]]>
</textFieldExpression>
</textField>
<textField>
<reportElement x="410" y="0" width="20" height="13"/>
<textFieldExpression class="java.lang.Integer">
<![CDATA[$F{alumnos}]]>
</textFieldExpression>
</textField>
</band>
</detail>
Como se puede ver, solo se han declarado tres textfields, y se ha impreso en ellas lo que proviene de la base de datos, esta sección es diferente a todas las demás, pues esta sección itera el resultset (en este caso) o bien un listado de beans enviado desde Java.
Ya esta listo el reporte, que al final queda de la siguiente manera.
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE jasperReport PUBLIC "//JasperReports//DTD Report Design//EN"
"http://jasperreports.sourceforge.net/dtds/jasperreport.dtd">
<!--======================================================================================== -->
<!--===================================== Por Crysfel Villa==================================== -->
<!--======================================================================================== -->
<jasperReport
name="plantilla"
pageWidth="595"
pageHeight="842"
leftMargin="20"
rightMargin="20"
topMargin="20"
bottomMargin="20">
<parameter name="P_ID_UNIVERSIDAD" class="java.lang.String"/>
<parameter name="LOGO_URL" class="java.lang.String"/>
<queryString><![CDATA[
SELECT U.nombre AS universidad, U.domicilio, CURDATE() AS fecha, F.facultad, F.director, F.alumnos
FROM facultades F, universidades U
WHERE U.id_universidad = F.id_universidad
AND U.id_universidad = $P{P_ID_UNIVERSIDAD}]]>
</queryString>
<field name="universidad" class="java.lang.String"/>
<field name="domicilio" class="java.lang.String"/>
<field name="fecha" class="java.util.Date"/>
<field name="facultad" class="java.lang.String"/>
<field name="director" class="java.lang.String"/>
<field name="alumnos" class="java.lang.Integer"/>
<background>
<band height="41">
<image>
<reportElement
x="500"
y="0"
width="33"
height="38"/>
<imageExpression class="java.lang.String"><![CDATA[$P{LOGO_URL}]]></imageExpression>
</image>
</band>
</background>
<title>
<band height="70">
<textField>
<reportElement
x="0"
y="20"
width="530"
height="30"/>
<textElement>
<font pdfFontName="Helvetica-Bold" size="20" isBold="true"/>
</textElement>
<textFieldExpression class="java.lang.String"><![CDATA[$F{universidad}]]></textFieldExpression>
</textField>
<line direction="TopDown">
<reportElement
x="0"
y="49"
width="530"
height="0"
key="line"/>
<graphicElement stretchType="NoStretch"/>
</line>
<textField>
<reportElement
x="0"
y="50"
width="250"
height="20"
key="textField"/>
<textElement>
<font pdfFontName="Helvetica-Bold" size="10"/>
</textElement>
<textFieldExpression class="java.lang.String"><![CDATA[$F{domicilio}]]></textFieldExpression>
</textField>
<textField pattern="EEEEE dd MMMMM yyyy">
<reportElement
x="260"
y="50"
width="270"
height="20"
key="textField"/>
<textElement textAlignment="Right">
<font pdfFontName="Helvetica-Bold" size="10"/>
</textElement>
<textFieldExpression class="java.util.Date"><![CDATA[$F{fecha}]]></textFieldExpression>
</textField>
</band>
</title>
<detail>
<band height="15">
<textField>
<reportElement x="0" y="0" width="200" height="13"/>
<textFieldExpression class="java.lang.String">
<![CDATA[$F{facultad}]]>
</textFieldExpression>
</textField>
<textField>
<reportElement x="205" y="0" width="200" height="13"/>
<textFieldExpression class="java.lang.String">
<![CDATA[$F{director}]]>
</textFieldExpression>
</textField>
<textField>
<reportElement x="410" y="0" width="20" height="13"/>
<textFieldExpression class="java.lang.Integer">
<![CDATA[$F{alumnos}]]>
</textFieldExpression>
</textField>
</band>
</detail>
</jasperReport>
Lo siguiente es compilar el jrxml y generar el pdf mediante java, esto es muy sencillo y se logra con muy pocas lineas de código.
package pruebas;
/**
* Generar un reporte con Jasper Report
* Por Crysfel Villa Roman
* 14/01/2008
*
* */
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.HashMap;
import java.util.Map;
import net.sf.jasperreports.engine.JREmptyDataSource;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
public class JasperReport2{
public static void main(String[] args){
String reportName = "plantilla";
JasperReport jasperReport;
JasperPrint jasperPrint;
Map pars = new HashMap();
pars.put("LOGO_URL", "logo.jpg");
pars.put("P_ID_UNIVERSIDAD", "1");
try{
//1-Se hace la conexion a la Base de Datos
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection ("jdbc:mysql://localhost:3306/test?user=root&password=la_password_del_servidor");
//2-Compilamos el archivo XML y lo cargamos en memoria
jasperReport = JasperCompileManager.compileReport(
reportName+".jrxml");
//3-Llenamos el reporte con la información (de la DB) y parámetros necesarios para la consulta
jasperPrint = JasperFillManager.fillReport(
jasperReport, pars, conn);
//4-Exportamos el reporte a pdf y lo guardamos en disco
JasperExportManager.exportReportToPdfFile(
jasperPrint, reportName+".pdf");
//5-Cerrar la conexion
conn.close();
System.out.println("Done!");
}catch (Exception e){
System.out.println(e);
e.printStackTrace();
}
}
}
Primero es necesario conectarse a la base de datos, puede ser cualquier base de datos, pero en este ejemplo es MySQL.
El segundo paso es compilar el reporte.
El tercer paso es llenar el reporte con la información de la base de datos y pasarle los parámetros necesarios.
El cuarto paso es exportarlo al formato deseado.
Por ultimo se cierra la conexión a la base de datos.
A diferencia de los tutoriales anteriores en este voy a poner el proyecto configurado con las librerías y códigos necesarios, para que lo instales en el eclipse y lo puedas ejecutar, esto por que en los tutoriales pasados algunas personas no pudieron completar el tutorial, el proyecto lo puedes descargar desde aqui.
Saludos.