Export massif de rapports avec BIRT🔗
Introduction
BIRT nous a permit d'élaborer nos modèles de rapports avec la mise en page qui nous convient. Nous sommes à même de produire un rapport sur une commune donnée. Néanmoins, il reste à générer des rapports pour toutes les communes du département. Il est clair qu'on ne va pas le faire à la main car ça signifie faire au moins 360 clics pour le département de Maine-et-Loire.
Il faut donc trouver un moyen d'automatiser le processus.
Une solution consiste à utiliser le viewer BIRT qui est disponible dans le fichier de runtime de BIRT. Il s'agit d'une application J2EE qui génère un rapport en fonction des paramètres d'entrées et du fichier de modèle de rapport. L'intérêt de ce viewer est qu'on peut l'interroger par un script.
Une autre solution consiste à développer un script qui utilise le moteur de rapport de BIRT. En effet, ce dernier permet à toute application Java de produire des rapports. C'est une solution tout à fait envisageable et qui serait d'ailleurs préférrable: les personnes qui utilisent BIRT utilisent également Eclipse qui est prévu pour faire du développement JAVA. De plus, avec le script sous la main, les personnes peuvent gérer elles-même leurs productions…
Méthode avec développement
La démarche
BIRT dispose d'un moteur de rapport (BIRT Report Engine). il est possible d'utiliser ce moteur de rapport directement dans une application JAVA. Nos besoins sont ultrasimples:
- Disposer d'un outil permettant de paramétrer (dans le code): le rapport et les valeurs des paramètres.
- Faire varier la valeur de ces paramètres suivant une plage donnée.
- Pour chaque occurence du paramètre variable, produire un rapport dans un format donné !
D'un point de vue algorithme, on a vu plus complexe. Nous allons donc développer un script en Java qui utilise le moteur de rapport de BIRT. Ca tombe finalement assez bien car BIRT est basé sur Eclipse qui est une plateforme de développement initialement créée pour coder en Java !!!
Pré-requis: installation du runtime
Vous devez d'abord télécharger le paquet du runtime BIRT sur la page de téléchargement de BIRT. Ce fichier est une archive compressée de près de 100Mo. Ca peut paraître surprenant car nous disposons déjà de ce moteur dans Eclipse lors de l'installation de BIRT. Néanmoins, notre script va s'appuyer sur ce moteur et vous devez, non seulement, disposer des bonnes bibliothèques (JAR) mais aussi d'indiquer, dans la configuration du moteur de rapport, où sont situées ces bibliothèques.
Vous devez donc télécharger et décompresser cette archive dans un répertoire donné. Pour la suite, ce répertoire sera /opt/BIRT_RE/. La démarche est la même sous MS-Windows mais le nom du répertoire sera différent.
La décompression extrait l'arborescence suivante:
birt-runtime-3_7_2 | \-------------------ReportEngine | | | \-----lib | \-----samples | | \-------------------WebViewerExample
Globalement, ce qui nous intéresse est dans le répertoire ReportEngine. Nous verrons qu'il sera utilisé dans le source du script de génération massive.
Source du script
Voici le code source d'un script qui est à minima paramétrable. Attention, ça juste marche dans Eclipse et je ne suis pas un développeur Java très expérimenté. En plus, j'avais moins d'une demi-journée à consacrer à ce travail donc c'est du code pas très propre (pas très bien organisé) mais ça correspond à mes besoins simples et c'est facilement récupérable, même pour un non développeur Java (typiquement un simple utilisateur de BIRT).
L'idée principale est de disposer d'une fonction paramétrable qui permet de produire des rapports:
- dans un format donné
- dans un répertoire ciblé
- avec des noms pré-formatés
- en utilisant toutes les valeurs d'un paramètre (il y aura donc autant de rapports que de valeurs de paramètre).
// Script pour générer autant de documents que de valeurs de paramètre différent import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.logging.Level; import org.eclipse.birt.core.framework.Platform; import org.eclipse.birt.report.engine.api.EngineConfig; import org.eclipse.birt.report.engine.api.EngineException; import org.eclipse.birt.report.engine.api.IGetParameterDefinitionTask; import org.eclipse.birt.report.engine.api.IParameterDefnBase; import org.eclipse.birt.report.engine.api.IParameterGroupDefn; import org.eclipse.birt.report.engine.api.IParameterSelectionChoice; import org.eclipse.birt.report.engine.api.IRenderOption; import org.eclipse.birt.report.engine.api.IReportEngine; import org.eclipse.birt.report.engine.api.IReportEngineFactory; import org.eclipse.birt.report.engine.api.IReportRunnable; import org.eclipse.birt.report.engine.api.IRunAndRenderTask; import org.eclipse.birt.report.engine.api.RenderOption; import org.eclipse.birt.report.engine.api.IScalarParameterDefn; import org.eclipse.birt.report.model.api.CascadingParameterGroupHandle; import org.eclipse.birt.report.model.api.ScalarParameterHandle; public class MassiveBirt { @SuppressWarnings("unchecked") public void runReport(String path, String filename, String format, String parameter) throws EngineException { IReportEngine engine=null; EngineConfig config = null; IRunAndRenderTask task=null; HashMap parmValues = new HashMap(); try { config = new EngineConfig( ); config.setBIRTHome("/opt/BIRT_RE/birt-runtime-3_7_2/"); config.setLogConfig(null, Level.OFF); Platform.startup( config ); IReportEngineFactory factory = (IReportEngineFactory) Platform.createFactoryObject( IReportEngineFactory.EXTENSION_REPORT_ENGINE_FACTORY ); engine = factory.createReportEngine( config ); } catch( Exception ex){ ex.printStackTrace(); } IReportRunnable design = null; // Ouverture du rapport design = engine.openReportDesign("/opt/BIRT_RE/birt-runtime-3_7_2/ReportEngine/rapports/test_RE.rptdesign"); // Récupération de la liste des paramètres // Attention, si vos paramètres sont sous forme de groupes, ça ne fonctionnera pas forcément IGetParameterDefinitionTask param_task = engine.createGetParameterDefinitionTask( design ); Collection params = param_task.getParameterDefns( true ); Iterator iter = params.iterator( ); while ( iter.hasNext( ) ) { IParameterDefnBase param = (IParameterDefnBase) iter.next( ); IScalarParameterDefn scalar = (IScalarParameterDefn) param; //Si c'est le paramètre qu'on cherche if(param.getName().equals(parameter)) { // Si le paramètre est une liste déroulante if(scalar.getControlType() == IScalarParameterDefn.LIST_BOX) { Collection selectionList = param_task.getSelectionList( param.getName() ); //On remplit un HashMap avec les valeurs et les identifiants if ( selectionList != null ) { for ( Iterator sliter = selectionList.iterator( ); sliter.hasNext( ); ) { IParameterSelectionChoice selectionItem = (IParameterSelectionChoice) sliter.next( ); String value = (String)selectionItem.getValue( ); String label = selectionItem.getLabel( ); parmValues.put(value, label); } } } } } param_task.close(); // Préparation de la génération du rapport IRenderOption options = new RenderOption(); options.setOutputFormat(format); // Boucle de génération for (Iterator it = parmValues.keySet().iterator(); it.hasNext();) { task = engine.createRunAndRenderTask(design); Object key = it.next(); Object value = parmValues.get(key); String fullname=path+filename+key+"-"+value+"."+format; System.out.println("Generating "+fullname+" ..."); options.setOutputFileName(fullname); task.setParameterValue(parameter, key); task.validateParameters(); // Lancement de la génération task.setRenderOption(options); task.run(); task.close(); } // On ferme tout proprement engine.destroy(); Platform.shutdown(); System.out.println("Finished in "+path); System.exit(0); } public static void main(String[] args) { try { MassiveBirt ex = new MassiveBirt( ); ex.runReport("/opt/BIRT_RE/birt-runtime-3_7_2/ReportEngine/", "Fiche_Agricole_", "odt","Commune"); } catch ( Exception e ) { e.printStackTrace(); } } }
Installer le script
Nous avons donc un fichier source Java (le script ci-dessus) ainsi que le runtime BIRT déployé dans un répertoire (/opt/BIRT_RE/…). Nous devons créer un projet Java dans Eclipse et le compiler.
D'abord, assurez-vous de disposer d'une perspective Java:
Ensuite, créer un nouveau projet:
Ensuite, il faut ajouter les bibliothèques du ReportEngine:
Puis, vous devez créer une nouvelle classe nommée MassiveBirt (vous pouvez la laisser dans le package par défaut) et y copier le code ci-dessus:
Enfin, vous devrez adapter la fin du script avec les paramètres indiqués pour que ça fonctionne chez vous !
Génération des rapports
Attention, la génération de rapports est un processus gourmand en mémoire (en fait c'est le cas avec JAVA en général). Avec 2Go de RAM sur une machine et un rapport de seulement une page, la génération de mes 300 rapports déclenche l'utilisation du swap.
Au delà de cet aspect, si vous avez intégré les bons arguments d'appel du script, vous devriez retrouver tous vos rapports dans le répertoire indiqué.
Références
Voici les références en ligne que j'ai utilisé pour découvrir l'API de BIRT: