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▲
II-A. 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 ;
- …
II-B. Téléchargement des bibliothèques nécessaires▲
Ici le site officiel officiel de l'API JFreeChart. Les différentes bibliothèques de l'API JFreeChart peuvent être téléchargées à partir de sourceforge.
II-C. 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 :
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.
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 :
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 :
En plaçant cet objet sur le rapport, ce dernier ressemblera à ceci :
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 :
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.
III-A. 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 bibliothèques y compris celles qu'on a téléchargées précédemment et mettez-les dans le CLASSPATH de l'application.
III-B. Création de la Classe appelant l'état▲
III-B-1. Exemple de graphe en Camembert▲
Créer une Classe MyTestCamembert et y insérer le code suivant :
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'absences 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) {
}
// connexion à la base de données
try
{
String DBurl =
"jdbc:odbc:TestJasperJFreeChart"
;
conn =
DriverManager.getConnection
(
DBurl);
}
catch
(
SQLException e) {
}
return
conn;
}
}
À 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 :
III-B-2. Exemple de graphe en Histogramme en 3D▲
Créer une deuxième Classe MyTestHistogramme et y insérer le code suivant :
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'absences 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) {
}
// connexion à la base de données
try
{
String DBurl =
"jdbc:odbc:TestJasperJFreeChart"
;
conn =
DriverManager.getConnection
(
DBurl);
}
catch
(
SQLException e) {
}
return
conn;
}
}
À 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 :
IV. Téléchargement du code source▲
Le code source de l'application est disponible dans l'archive suivant :
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 à l'avenir.
VI. Remerciements▲
Mes remerciements vont à Baptiste Wicht pour ses remarques et à Fleur-Anne.Blain pour ses remarques et sa relecture précieuse.