I. Introduction

Parfois on a besoin d'illustrer nos rapports à l'aide de graphes. Cet article vous expliquera pas à pas comment générer un rapport contenant des graphes de différents formats via l'API JasperReports et JFreeChart.

II. Création du fichier JRXML

2.1. Présentation

Dans cet article je ne vais pas m'attarder sur les premières étapes pour la création d'un état jasper, vous pouvez toujours vous référez à cet article expliquant les différentes étapes pour créer et éditer un état jasper à partir d'une application web de type JSF.

Wikipédia définit JFreeChart comme étant une API Java permettant de créer des graphiques et des diagrammes de très bonne qualité. Cette API est open source et sous licence LGPL. En revanche, la documentation est payante.

L'API JFreeChart propose de nombreux types d'affichages de graphiques :

  • Camemberts
  • Courbes
  • Histogrammes
  • ...

2.2. Téléchargement des librairies nécessaires

Ici le site officiel officiel de l'API JFreeChart. Les différentes librairies de l'API JFreeChart peuvent être téléchargées à partir de sourceforge.

2.3. Création de l'état sous iReport

La base de données utilisée dans cet article est de type ACCESS. Nous allons donc créer une base de données de type sur ACCESS en lui donnant pour nom TestJasperJFreeChart. Cette base de données contient une seule table Personne dont la définition des champs se présente comme suit :

Image non disponible

Une fois cette table créée, nous devons l'alimenter par quelques enregistrements.

Sous iReport nous allons configurer la source de données pointant sur la base précédemment créée comme expliqué dans cet article.

Maintenant, nous allons créer un simple état à partir de la table Personne en listant tous ses enregistrements, en suivant toujours l'article précédemment mentionné.

Une fois notre état créé, nous y modifions la taille de la bande sommaire afin d'y mettre l'image qui contiendra le futur graphe. Pour ce faire, cliquez droit sur n'importe quelle bande (Header, footer, summary...) et choisissez Propriétés de bande.

Image non disponible

Modifiez la taille de la bande sommaire, en y mettant 150 par exemple dans le champ Hauteur de bande comme le montre l'image suivante :

Image non disponible

La partie sommaire, vide pour le moment, est bien visible sur notre rapport. Nous y plaçons un objet de type Image en sélectionnant l'objet Image en haut comme suit :

Image non disponible

En plaçant cet objet sur le rapport, ce dernier ressemblera à ceci :

Image non disponible

Créez un paramètre PersonneChart qui sera alimenté par la Classe Java et qui servira comme source de données pour le graphe sur l'état. Ce paramètre aura pour type java.awt.Image.

Double cliquer sur le graphe sous iReport, sélectionner l'onglet Image et mettre dans la propriété Expression de l'image l'expression $P{PersonneChart} comme suit :

Image non disponible

Notre rapport est à présent prêt pour exécution. Nous pouvons le tester à partir de iReport, mais le graphe ne sera pas visible vu qu'on n'a pas encore alimenté le paramètre PersonneChart.

III. Exécution de l'état à partir d'une application Java

Pour tester notre état, nous allons créer une simple application Java qui y fera appel.

3.1. Configuration de l'environnement de travail

Nous allons créer une application Java testJasperJFreeChart. Créez un dossier lib pour y mettre les différentes librairies y compris celles qu'on a téléchargées précédemment et mettez les dans le CLASSPATH de l'application.

Image non disponible

3.2. Création de la Classe appelant l'état

3.2.1. Exemple de graphe en Camembert

Créer une Classe MyTestCamembert et y insérer le code suivant :

 
Sélectionnez
package jaub;

import java.io.File;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.view.JasperViewer;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.data.general.DefaultPieDataset;

public class MyTestCamembert {

	public MyTestCamembert() {
	}

	public static void main(String[] args) {
		try {

			Map parameters = new HashMap();
			// on met dans le paramétre PersonneChart créé au niveau de iReport
			// le résultat du chart créé avec les mêmes données issues
			// de la table Personne

			parameters.put("PersonneChart", createPersonneChartImage());

			File file = new File("C:\\JASPER");
			JasperPrint jasperPrint = JasperFillManager.fillReport(
					new FileInputStream(new File(file, "personne.jasper")),
					parameters, getConnection());
			getConnection().close();
			
			// on exporte l'état dans un fichier pdf
			JasperExportManager.exportReportToPdfFile(jasperPrint,
					"C:\\PersonnesCamembert.pdf");

			// Affichage du rapport dans l'objet JasperViewer
			JasperViewer.viewReport(jasperPrint);
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	private static java.awt.Image createPersonneChartImage() throws SQLException {

		// la variable infosPersonnes Contient les noms
		// des personnes (le champ Nom) comme clés
		// et le nombre d'absence comme valeurs

		java.util.Hashtable infosPersonnes = new Hashtable();
	

		/**
		 * Alimentation de la variable infosPersonnes
		 */

		// On récupére l'objet Connection
		
		PreparedStatement recherchePersonne = getConnection()
				.prepareStatement("SELECT * FROM personne");
		
		ResultSet resultats = null;
		resultats = recherchePersonne.executeQuery();
		
		boolean encore = resultats.next();
		while (encore) {
			infosPersonnes.put(resultats.getString(1), Double.parseDouble(resultats.getString(2)));
			encore = resultats.next();
		}
		resultats.close();
		

		// create a dataset...

		DefaultPieDataset data = new DefaultPieDataset();
		// fill dataset with infosPersonnes datas
		for (java.util.Enumeration e = infosPersonnes.keys(); e
				.hasMoreElements();) {
			String employeeName = (String) e.nextElement();
			data.setValue(employeeName, (Double) infosPersonnes
					.get(employeeName));
		}

		// create a chart with the dataset
		JFreeChart chart = ChartFactory.createPieChart("Personnes Chart", data,
				true, true, true);
		// create and return the image

		return chart.createBufferedImage(500, 220);

	}

	// Retourne un objet de type Connection
	// à partir d'un ODBC pointant vers 
	//la base de données ACCESS TestJasperJFreeChart
	private static Connection getConnection() {
		Connection conn = null;

		try {
			Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
		} catch (ClassNotFoundException e) {

		}
		// connection a la base de données

		try {
			String DBurl = "jdbc:odbc:TestJasperJFreeChart";
			conn = DriverManager.getConnection(DBurl);
		} catch (SQLException e) {
		}

		return conn;
	}
}

A l'exécution de cette Classe, l'état est exporté sous format pdf sur C:\PersonnesCamembert.pdf et l'objet JasperViewer affiche l'ensemble des enregistrements de la table Personne ainsi qu'un graphe dans le sommaire comme suit :

Image non disponible

3.2.2. Exemple de graphe en Histogramme en 3D

Créer une deuxième Classe MyTestHistogramme et y insérer le code suivant :

 
Sélectionnez
package jaub;

import java.io.File;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.view.JasperViewer;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.data.general.DefaultPieDataset;

public class MyTestHistogramme {

	public MyTestHistogramme() {
	}

	public static void main(String[] args) {
		try {

			Map parameters = new HashMap();
			// on met dans le paramétre PersonneChart créé au niveau de iReport
			// le résultat du chart créé avec les mêmes données issues
			// de la table Personne

			parameters.put("PersonneChart", createPersonneChartImage());

			File file = new File("C:\\JASPER");
			JasperPrint jasperPrint = JasperFillManager.fillReport(
					new FileInputStream(new File(file, "personne.jasper")),
					parameters, getConnection());
			getConnection().close();
			JasperExportManager.exportReportToPdfFile(jasperPrint,
					"C:\\PersonnesHistogramme.pdf");

			// Affichage du rapport dans l'objet JasperViewer
			JasperViewer.viewReport(jasperPrint);
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	private static java.awt.Image createPersonneChartImage()
			throws SQLException {

		// la variable infosPersonnes Contient les noms
		// des personnes (le champ Nom) comme clés
		// et le nombre d'absence comme valeurs

		java.util.Hashtable infosPersonnes = new Hashtable();

		/**
		 * Alimentation de la variable infosPersonnes
		 */

		PreparedStatement recherchePersonne = getConnection().prepareStatement(
				"SELECT * FROM personne");

		ResultSet resultats = null;
		resultats = recherchePersonne.executeQuery();

		boolean encore = resultats.next();
		while (encore) {
			// System.out.print(resultats.getString(1) + " " +
			// resultats.getString(2));
			System.out.println();
			infosPersonnes.put(resultats.getString(1), Double
					.parseDouble(resultats.getString(2)));
			encore = resultats.next();
		}
		resultats.close();

		// create a dataset
		DefaultCategoryDataset defaultCategoryDataset = new DefaultCategoryDataset();
		String s = "Personne";
		// fill dataset with infosPersonnes
		for (java.util.Enumeration e = infosPersonnes.keys(); e
				.hasMoreElements();) {
			String Personnename = (String) e.nextElement();
			defaultCategoryDataset.addValue((Double) infosPersonnes
					.get(Personnename), s, Personnename);
		}
		// create a chart with the dataset
		JFreeChart chart = ChartFactory.createBarChart3D("Personne Chart", // Title
				"Personne", // X-Axis label
				"Nombre d'absences", // Y-Axis label
				(CategoryDataset) defaultCategoryDataset, // Dataset
				PlotOrientation.VERTICAL, true, // Show legend
				true, true);
		// create and return the image with the size specified in the XML design
		return chart.createBufferedImage(500, 220);

	}

	private static Connection getConnection() {
		Connection conn = null;

		try {
			Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
		} catch (ClassNotFoundException e) {

		}
		// connection a la base de données

		try {
			String DBurl = "jdbc:odbc:TestJasperJFreeChart";
			conn = DriverManager.getConnection(DBurl);
		} catch (SQLException e) {
		}

		return conn;
	}
}

A l'exécution de cette Classe, l'état est exporté sous format pdf sur C:\PersonnesHistogramme.pdf et l'objet JasperViewer affiche l'ensemble des enregistrements de la table Personne ainsi qu'un graphe dans le sommaire comme suit :

Image non disponible

IV. Téléchargement du code source

Le code source de l'application est disponible dans l'archive suivant :

Image non disponible Application et Jasper.rar.

Après décompression, vous aurez deux répertoires :

  • JASPER : Contient seulement le fichier Jasper, dans mon cas je l'ai mis dans C:\JASPER.
  • testJasperJFreeChart : Contient le code source de l'application, ainsi que les différents fichiers JAR nécessaires.

V. Conclusion

Cet article a pour objectif de donner une des façons pour coupler les deux API JasperReports et JFreeChart pour illustrer un rapport avec différents types de graphes. L'application pourra être optimisée afin de n'exécuter la même requête qu'une seule fois, chose qui pourra faire l'objet d'une mise à jour de cet article dans l'avenir.

VI. Remerciements

Mes remerciements vont à Baptiste Wicht pour ses remarques et à Fleur-Anne.Blain pour ses remarques et sa relecture précieuse.