IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

 

Développons en Java   2.30  
Copyright (C) 1999-2022 Jean-Michel DOUDOUX    (date de publication : 15/06/2022)

[ Précédent ] [ Sommaire ] [ Suivant ] [Télécharger ]      [Accueil ]

 

108. La génération de documents

 

chapitre    1 0 8

 

Niveau : niveau 4 Supérieur 

 

Il est fréquent qu'une application de gestion doive produire des documents dans différents formats. Ce chapitre présente plusieurs solutions open source pour permettre la génération de documents, notamment aux formats PDF et Excel.

Ce chapitre contient plusieurs sections :

 

108.1. Apache POI

POI est l'acronyme de Poor Obfuscation Implementation. C'est un projet open source du groupe Apache, sous licence Apache V2, dont le but est de permettre la manipulation de fichiers de la suite bureautique Office de Microsoft, dans des applications Java mais sans utiliser Office.

L'implémentation de POI est intégralement réalisée en pur Java.

La manipulation ne peut se faire que sur des documents reposant sur le format Microsoft OLE2 (Object Linking and Embedding) Compound Document ce qui inclus les documents de la suite Office mais aussi les applications qui utilisent les ensembles de propriétés MFC pour sérialiser leurs documents.

Ce projet contient plusieurs composants :

  • POIFS (Poor Obfuscation Implementation File System) : manipulation de fichiers utilisant le format Microsoft OLE 2 Compound Document
  • HSSF (Horrible SpreadSheet Format) : manipulation des fichiers Excel (XLS) en lecture et écriture.
  • HWPF (Horrible Word Processor Format) : manipulation de fichiers Word en lecture et certaines fonctionnalités en écriture.
  • HPSF (Horrible Slide Layout Format) : manipulation de fichiers PowerPoint en lecture et écriture pour certains fonctionnalités mais pas toutes
  • HDGF : lecture et uniquement extraction de texte de fichiers Visio
  • HPSF : API pour manipuler les propriétés d'un fichier au format OLE 2 en lecture et en écriture

La version 3.0.1 a été diffusée en juillet 2007.

La version 3.1 a été diffusée fin juin 2008.

La version 3.5 en cours de développement devrait apporter le support des formats Office Open XML proposés depuis la version 2007 d'Office.

Ce projet est particulièrement intéressant car il permet la manipulation de documents au format Office sans que celui-ci soit installé et cela, même sur des systèmes d'exploitation non Microsoft Windows.

Le site officiel du projet est à l'url https://poi.apache.org/

La version utilisée dans cette section est la 3.1.

Le téléchargement de l'archive contenant la version binaire de POI se fait à l'url :

https://poi.apache.org/download.html

Il faut ensuite décompresser l'archive poi-bin-3.1-FINAL-20080629.zip obtenue dans un répertoire du système.

Pour utiliser PIO, il suffit d'ajouter le fichier poi-3.1-FINAL-20080629.jar au classpath de l'application.

 

108.1.1. POI-HSSF

HSSF permet la manipulation de document Excel de la version 97 à la version 2007 uniquement pour le format OLE2 (fichier avec l'extension .xls). Le format OOXML d'Excel 2007 n'est pas encours supporté (fichier avec l'extension .xlsx)

HSSF est une solution riche en fonctionnalités et fiable pour la manipulation de documents Excel en Java.

Un document Excel est composé de plusieurs éléments : un Dossier (Workbook) qui contient une ou plusieurs Feuilles (WorkSheets) étant elle-mêmes constituées de Lignes (Rows) comportant des cellules (Cells).

Les classes principales de l'API HSSF proposent d'encapsuler chacun de ces éléments. HSSF propose deux API pour manipuler un document Excel :

  • user API : API la plus riche qui permet la lecture et l'écriture mais qui consomme beaucoup de ressources car le document est intégralement représenté dans un graphe d'objets (le pendant pour le traitement de documents XML pourrait être DOM). Les classes de cette API sont regroupées dans le package org.apache.poi.hssf.usermodel
  • event API : API pour la lecture uniquement qui consomme peut de ressources (le pendant pour le traitement de documents XML pourrait être SAX). Les classes de cette API sont regroupées dans le package org.apache.poi.hssf.eventmodel et org.apache.poi.hssf.eventusermodel

La liste des packages de HSSF comprend notamment :

Package

Rôle

org.apache.poi.hssf.eventmodel

Classes pour gérer les événements émis lors de la lecture d'un document

org.apache.poi.hssf.eventusermodel

Classes pour lire un document

org.apache.poi.hssf.extractor

Classes pour extraire le texte d'un document

org.apache.poi.hssf.record.formula

Classes pour le support des formules dans les cellules

org.apache.poi.hssf.usermodel

Classes pour la manipulation de documents

org.apache.poi.hssf.util

Utilitaires pour faciliter la mise en oeuvre de certaines fonctionnalités

 

108.1.1.1. L'API de type usermodel

L'API de HSSF permet de créer, lire et modifier les documents Excel. Pour cela, elle contient de nombreuses classes dont les principales sont :

  • POIFSFileSystem : classe qui permet d'accéder à un document existant
  • HSSFWorkbook : classe qui encapsule un document
  • HSSFSheet : classe qui encapsule une feuille d'un document
  • HSSFRow : classe qui encapsule une ligne d'une feuille
  • HSSFCell : classe qui encapsule une cellule d'une ligne

Cette API est riche en fonctionnalités mais elle consomme beaucoup de ressources notamment pour les gros de fichiers car ceux-ci sont intégralement représentés en mémoire dans une arborescence d'objets.

Parmi les nombreuses fonctionnalités proposées par cette API, il y a :

  • lecture et écriture de document
  • création et modification des différentes entités qui composent un document (document, feuille, ligne, cellule, ...)
  • support de fonctionnalités avancées sur la feuille : sélection, zoom, support des panneaux, ...
  • support des types de données d'une cellule (numérique et date, chaîne de caractère, formule)
  • formatage des cellules (alignement, police, couleur, bordures, formats de données proposés en standard ou personnalisés,
  • fonctionnalités avancées sur les cellules : taille, taille optimale, fusion, commentaires, ...
  • paramètre d'impression d'une page (sélection de la zone d'impression, faire tenir sur une page, bas de page, ...)
  • support graphique : dessin de primitives, d'images, ...

Seules quelques-unes de ces fonctionnalités sont détaillées dans les sections suivantes. Consultez la documentation de l'API pour obtenir des détails sur la mise en oeuvre des autres fonctionnalités.

 

108.1.1.1.1. La création d'un nouveau document

Il suffit d'instancier un objet de type HSSFWorkBook et d'invoquer sa méthode write() pour créer le fichier.

Exemple :
package fr.jmdoudoux.dej.poi;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;

public class TestPOI1 {

  public static void main(String[] args) {
    HSSFWorkbook wb = new HSSFWorkbook();
    FileOutputStream fileOut;
    try {
      fileOut = new FileOutputStream("monfichier.xls");
      wb.write(fileOut);
      fileOut.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

A l'exécution de cet exemple, un document Excel vierge est créé.

 

108.1.1.1.2. La création d'une nouvelle feuille

Une feuille est encapsulée dans la classe HSSFSheet. Pour créer une nouvelle feuille dans un document, il faut invoquer la méthode createSheet() de la classe HSSFWorkBook.

Exemple :
package fr.jmdoudoux.dej.poi;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

public class TestPOI2 {

  public static void main(
      String[] args) {
    
    HSSFWorkbook wb = new HSSFWorkbook();
    HSSFSheet sheet = wb.createSheet("ma feuille");

    FileOutputStream fileOut;
    try {
      fileOut = new FileOutputStream("monfichier.xls");
      wb.write(fileOut);
      fileOut.close();  
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

 

108.1.1.1.3. La création d'une nouvelle cellule

Une cellule d'une feuille est contenue dans une ligne qui est encapsulée dans un objet de type HSSFRow. Pour instancier un objet de ce type, il faut invoquer la méthode createRow() de la classe HSSFSheet. Cette méthode attend en paramètre le numéro de la ligne concernée sous la forme d'un entier de type int sachant que la première ligne possède l'index 0.

Une cellule est encapsulée dans la classe HSSFCell. Pour instancier un objet de ce type, il faut invoquer la méthode createCell() de la classe HSSFRow. Cette méthode attend en paramètre le numéro de la cellule concernée sous la forme d'un entier de type short sachant que la première cellule possède l'index 0.

Exemple :
package fr.jmdoudoux.dej.poi;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

public class TestPOI3 {

  public static void main(
      String[] args) {
    
    HSSFWorkbook wb = new HSSFWorkbook();
    HSSFSheet sheet = wb.createSheet("ma feuille");

    HSSFRow row = sheet.createRow(0);
    HSSFCell cell = row.createCell((short)0);
    cell.setCellValue(10);

    row.createCell((short)1).setCellValue(20);

    FileOutputStream fileOut;
    try {
      fileOut = new FileOutputStream("monfichier.xls");
      wb.write(fileOut);
      fileOut.close();  
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

Remarque : seules les lignes ayant au moins une cellule sont ajoutées à la feuille. Seules les cellules non vides sont ajoutées à une ligne.

La méthode setCellValue() possède plusieurs surcharges pour fournir une valeur à la cellule selon plusieurs formats : int, boolean, double et des objets de type Calendar, Date et chaîne de caractères.

Remarque : pour les chaînes de caractères, la surcharge attendant en paramètre un objet de type String est deprecated au profit de la surcharge attendant en paramètre un objet de type HSSFRichTextString.

La méthode setCellType() permet de préciser le type des données de la cellule. Elle attend en paramètre une des constantes définies dans la classe HSSFCell : CELL_TYPE_BLANK, CELL_TYPE_BOOLEAN, CELL_TYPE_ERROR, CELL_TYPE_FORMULA, CELL_TYPE_NUMERIC, ou CELL_TYPE_STRING

Exemple :
package fr.jmdoudoux.dej.poi;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

public class TestPOI4 {

  public static void main(
      String[] args) {
    
    HSSFWorkbook wb = new HSSFWorkbook();
    HSSFSheet sheet = wb.createSheet("ma feuille");

    HSSFRow row = sheet.createRow(0);
    HSSFCell cell = row.createCell((short)0);
    cell.setCellValue(10);

    row.createCell((short)1).setCellValue(20.5);

    row.createCell((short)2, HSSFCell.CELL_TYPE_STRING)
      .setCellValue(new HSSFRichTextString("ma valeur"));;

    FileOutputStream fileOut;
    try {
      fileOut = new FileOutputStream("monfichier.xls");
      wb.write(fileOut);
      fileOut.close();  
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

Une des grandes forces d'Excel est de permettre l'application de formules plus ou moins complexes sur les données.

Pour assigner une formule à une cellule, il faut lui assigner le type FORMULA. La méthode setCellFormula() permet de définir la formule qui sera associée à la cellule.

Exemple :
package fr.jmdoudoux.dej.poi;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

public class TestPOI13 {

  public static void main(
      String[] args) {

    HSSFWorkbook wb = new HSSFWorkbook();
    HSSFSheet sheet = wb.createSheet("ma feuille");

    HSSFRow row = sheet.createRow(0);
    HSSFCell cell = null;

    cell = row.createCell((short) 0);
    cell.setCellValue(10);

    cell = row.createCell((short) 1);
    cell.setCellValue(20);

    cell = row.createCell((short) 2);
    cell.setCellValue(30);

    cell = row.createCell((short) 3);
    cell.setCellType(HSSFCell.CELL_TYPE_FORMULA);
    cell.setCellFormula("SUM(A1:C1)");

    FileOutputStream fileOut;
    try {
      fileOut = new FileOutputStream("monfichier.xls");
      wb.write(fileOut);
      fileOut.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

 

108.1.1.1.4. Le formatage d'une cellule

Le formatage d'une cellule se fait à l'aide d'un objet de type HSSFCellStyle. La classe HSSFCellStyle permet de définir le format des données, d'aligner les valeurs dans la cellule, de définir ses bordures, ...

La méthode setCellStyle() de la classe HSSFCell permet d'associer un style à la cellule.

Pour définir un style qui permet d'aligner les données, il faut utiliser la méthode setAlignment() de la classe HSSFCellStyle. Celle-ci attend en paramètre une des constantes suivantes : HSSFCellStyle.ALIGN_CENTER, HSSFCellStyle.ALIGN_CENTER_SELECTION, HSSFCellStyle.ALIGN_FILL, HSSFCellStyle.ALIGN_GENERAL, HSSFCellStyle.ALIGN_JUSTIFY, HSSFCellStyle.ALIGN_LEFT, HSSFCellStyle.ALIGN_RIGHT

Exemple :
package fr.jmdoudoux.dej.poi;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

public class TestPOI5 {

  public static void main(
      String[] args) {

    HSSFWorkbook wb = new HSSFWorkbook();
    HSSFSheet sheet = wb.createSheet("ma feuille");

    HSSFRow row = sheet.createRow(0);
    HSSFCell cell = null;
    HSSFCellStyle cellStyle = null;

    cell = row.createCell((short) 0);
    cell.setCellValue(10);
    cellStyle = wb.createCellStyle();
    cellStyle.setAlignment(HSSFCellStyle.ALIGN_LEFT);
    cell.setCellStyle(cellStyle);

    cell = row.createCell((short) 1);
    cell.setCellValue(20);
    cellStyle = wb.createCellStyle();
    cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
    cell.setCellStyle(cellStyle);

    cell = row.createCell((short) 2);
    cell.setCellValue(30);
    cellStyle = wb.createCellStyle();
    cellStyle.setAlignment(HSSFCellStyle.ALIGN_RIGHT);
    cell.setCellStyle(cellStyle);

    FileOutputStream fileOut;
    try {
      fileOut = new FileOutputStream("monfichier.xls");
      wb.write(fileOut);
      fileOut.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

Pour préciser le format des données de la cellule, il faut utiliser la méthode setDataFormat() de la classe HSSFCellStyle. Elle attend en paramètre un entier qui précise le type selon les valeurs gérées par la classe HSSFDataFormat.

La classe HSSFDataFormat propose plusieurs méthodes statiques pour obtenir un des formatages prédéfinis.

Pour utiliser un format personnalisé, il faut invoquer la méthode createDataFormat() de la classe HSSFWorkbook de l'instance qui encapsule le document pour obtenir une instance de la classe HSSFDataFormat. L'invocation de la méthode getFormat() de cette instance permet de définir son format personnalisé.

Exemple :
package fr.jmdoudoux.dej.poi;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFDataFormat;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

public class TestPOI6 {

  public static void main(
      String[] args) {

    HSSFWorkbook wb = new HSSFWorkbook();
    HSSFSheet sheet = wb.createSheet("ma feuille");

    HSSFRow row = sheet.createRow(0);
    HSSFCell cell = null;
    HSSFCellStyle cellStyle = null;

    cell = row.createCell((short) 0);
    cell.setCellValue(1000);
    cellStyle = wb.createCellStyle();
    cellStyle.setDataFormat(HSSFDataFormat.getBuiltinFormat("#,##0"));
    cell.setCellStyle(cellStyle);

    cell = row.createCell((short) 1);
    cell.setCellValue(new Date());
    cellStyle = wb.createCellStyle();
    HSSFDataFormat hssfDataFormat = wb.createDataFormat();
    cellStyle.setDataFormat(hssfDataFormat.getFormat("dd/mm/yyyy h:mm"));
    cell.setCellStyle(cellStyle);

    FileOutputStream fileOut;
    try {
      fileOut = new FileOutputStream("monfichier.xls");
      wb.write(fileOut);
      fileOut.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

Pour modifier le fond et l'apparence d'une cellule, il faut utiliser les méthodes setFillBackgroundColor(), setFillForegroundColor() et setFillPattern() de la classe HSSFCellStyle.

Les méthodes setFillBackgroundColor() et setFillForegroundColor() attendent en paramètre un entier de type short : la classe HSSFColor possède de nombreuses classes filles pour faciliter l'utilisation d'une couleur.

La méthode setFillPattern() attend en paramètre un entier de type short : la classe HSSFCellStyle propose de nombreuses constantes pour faciliter l'utilisation d'un motif de remplissage.

Exemple :
package fr.jmdoudoux.dej.poi;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;

public class TestPOI7 {

  public static void main(
      String[] args) {

    HSSFWorkbook wb = new HSSFWorkbook();
    HSSFSheet sheet = wb.createSheet("ma feuille");

    HSSFRow row = sheet.createRow(0);
    HSSFCell cell = null;
    HSSFCellStyle cellStyle = null;

    cell = row.createCell((short) 0);
    cell.setCellValue(1000);
    cellStyle = wb.createCellStyle();
    cellStyle.setFillForegroundColor(HSSFColor.RED.index);
    cellStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
    cell.setCellStyle(cellStyle);

    cell = row.createCell((short) 1);
    cell.setCellValue(2000);
    cellStyle = wb.createCellStyle();
    cellStyle.setFillForegroundColor(HSSFColor.YELLOW.index);
    cellStyle.setFillPattern(HSSFCellStyle.ALT_BARS);
    cellStyle.setFillForegroundColor(HSSFColor.WHITE.index);
    cell.setCellStyle(cellStyle);

    FileOutputStream fileOut;
    try {
      fileOut = new FileOutputStream("monfichier.xls");
      wb.write(fileOut);
      fileOut.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

Pour mettre des bordures sur les côtés des cellules, la classe HSSFCellStyle propose plusieurs méthodes :

  • setBorderXxx : permet de préciser la forme de la bordure en utilisant les constantes définies dans la classe HSSFCellStyle
  • setXxxBorderColor : permet de préciser la couleur de la bordure
Exemple :
package fr.jmdoudoux.dej.poi;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;

public class TestPOI8 {

  public static void main(
      String[] args) {

    HSSFWorkbook wb = new HSSFWorkbook();
    HSSFSheet sheet = wb.createSheet("ma feuille");

    HSSFRow row = sheet.createRow(1);
    HSSFCell cell = null;
    HSSFCellStyle cellStyle = null;

    cell = row.createCell((short) 1);
    cell.setCellValue(1000);
    cellStyle = wb.createCellStyle();
    cellStyle.setBorderBottom(HSSFCellStyle.BORDER_MEDIUM);
    cellStyle.setBottomBorderColor(HSSFColor.RED.index);
    cellStyle.setBorderLeft(HSSFCellStyle.BORDER_MEDIUM);
    cellStyle.setLeftBorderColor(HSSFColor.RED.index);
    cellStyle.setBorderRight(HSSFCellStyle.BORDER_MEDIUM);
    cellStyle.setRightBorderColor(HSSFColor.RED.index);
    cellStyle.setBorderTop(HSSFCellStyle.BORDER_MEDIUM);
    cellStyle.setTopBorderColor(HSSFColor.RED.index);
    cell.setCellStyle(cellStyle);

    cell = row.createCell((short) 3);
    cell.setCellValue(2000);
    cellStyle = wb.createCellStyle();
    cellStyle.setBorderBottom(HSSFCellStyle.BORDER_MEDIUM_DASHED);
    cellStyle.setBottomBorderColor(HSSFColor.BLACK.index);
    cellStyle.setBorderLeft(HSSFCellStyle.BORDER_MEDIUM_DASHED);
    cellStyle.setLeftBorderColor(HSSFColor.BLACK.index);
    cellStyle.setBorderRight(HSSFCellStyle.BORDER_MEDIUM_DASHED);
    cellStyle.setRightBorderColor(HSSFColor.BLACK.index);
    cellStyle.setBorderTop(HSSFCellStyle.BORDER_MEDIUM_DASHED);
    cellStyle.setTopBorderColor(HSSFColor.BLACK.index);
    cell.setCellStyle(cellStyle);

    FileOutputStream fileOut;
    try {
      fileOut = new FileOutputStream("monfichier.xls");
      wb.write(fileOut);
      fileOut.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

Pour utiliser une police de caractères, il faut utiliser la méthode setFont() de la classe HSSFCellStyle qui attend en paramètre un objet de type HSSFFont encapsulant une police de caractères.

Pour obtenir une instance de la classe HSSFFont, il faut invoquer la méthode createFont() de la classe HSSFWorkbook. La classe HSSFFont possède plusieurs méthodes pour définir les caractéristiques de la police de caractères : famille, taille, gras, souligné, italique, barré, ...

Exemple :
package fr.jmdoudoux.dej.poi;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

public class TestPOI9 {

  public static void main(
      String[] args) {

    HSSFWorkbook wb = new HSSFWorkbook();
    HSSFSheet sheet = wb.createSheet("ma feuille");

    HSSFRow row = sheet.createRow(0);
    HSSFCell cell = null;
    HSSFCellStyle cellStyle = null;

    HSSFFont fonte = wb.createFont();
    fonte.setFontHeightInPoints((short) 18);
    fonte.setFontName("Courier New");
    fonte.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
    fonte.setStrikeout(true);

    cell = row.createCell((short) 0);
    cell.setCellValue(1000);
    cellStyle = wb.createCellStyle();
    cellStyle.setFont(fonte);
    cell.setCellStyle(cellStyle);

    FileOutputStream fileOut;
    try {
      fileOut = new FileOutputStream("monfichier.xls");
      wb.write(fileOut);
      fileOut.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

 

108.1.1.1.5. La fusion de cellules

Pour fusionner un ensemble de cellules, il faut invoquer la méthode addMergedRegion() de la classe HSSFSheet. Elle attend en paramètre un objet de type org.apache.poi.hssf.util.Region qui permet de définir l'ensemble des cellules à fusionner.

Un des constructeurs de la classe Region attend en paramètre quatre entiers qui correspondent respectivement au numéro et à la colonne de la première ligne, au numéro et à la colonne de la dernière ligne de l'ensemble des cellules.

Exemple :
package fr.jmdoudoux.dej.poi;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.Region;

public class TestPOI10 {

  public static void main(
      String[] args) {

    HSSFWorkbook wb = new HSSFWorkbook();
    HSSFSheet sheet = wb.createSheet("ma feuille");

    HSSFRow row = sheet.createRow(0);
    HSSFCell cell = null;

    cell = row.createCell((short) 0);
    cell.setCellValue(1234);

    sheet.addMergedRegion(new Region(0,(short)0,0,(short)3));
    
    FileOutputStream fileOut;
    try {
      fileOut = new FileOutputStream("monfichier.xls");
      wb.write(fileOut);
      fileOut.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

 

108.1.1.1.6. La lecture et la modification d'un document

Pour lire un document, il faut utiliser la classe POIFSFileSystem. Un des constructeurs de cette classe attend en paramètre un objet de type InputStream qui encapsule un flux vers le document à lire.

Il suffit de fournir l'instance de la classe POIFSFileSystem en paramètre du constructeur de la classe HSSFWorkbook pour lire le document et produire une arborescence d'objets qui encapsule son contenu.

Il est ensuite possible d'utiliser ces objets pour modifier le contenu du document et l'enregistrer une fois les modifications terminées.

Les méthodes getNumericCellValue() et getRichStringCellValue() de la classe HSSFCell permettent d'obtenir la valeur de la cellule selon son type.

La méthode setCellType() de la classe HSSFCell permet de préciser le type du contenu de la cellule (CELL_TYPE_BLANK, CELL_TYPE_BOOLEAN, CELL_TYPE_ERROR, CELL_TYPE_FORMULA, CELL_TYPE_NUMERIC, CELL_TYPE_STRING)

Plusieurs surcharges de la méthode setValue() de la classe HSSFCell permettent de fournir la valeur de la cellule.

Exemple :
package fr.jmdoudoux.dej.poi;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;

public class TestPOI11 {

  public static void main(
      String[] args) {

    try {
      FileOutputStream fileOut;

      POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream("monfichier.xls"));
      HSSFWorkbook wb = new HSSFWorkbook(fs);
      HSSFSheet sheet = wb.getSheetAt(0);
      HSSFRow row = sheet.getRow(0);
      
      HSSFCell cell = row.getCell((short) 0);
      if (cell != null)
          row.removeCell(cell);
      cell = row.createCell((short) 0);
      cell.setCellType(HSSFCell.CELL_TYPE_STRING);
      cell.setCellValue(new HSSFRichTextString("données modifiées"));

      fileOut = new FileOutputStream("monfichier.xls");
      wb.write(fileOut);
      fileOut.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

Pour obtenir une donnée, il est préférable de s'assurer du type de données associé à la cellule en utilisant la méthode getCellType().

Une exception est levée si le type de données demandé ne correspond pas à la méthode invoquée, par exemple : appel de la méthode getCellValue() sur une cellule de type STRING.

Remarque : Excel stocke les dates sous une forme numérique. Pour les identifier, il faut regarder le format des données.

 

108.1.1.1.7. Le parcours des cellules d'une feuille

La classe HSSFSheet propose la méthode rowIterator() qui renvoie un objet de type Iterator permettant de parcourir les lignes de la feuille.

Attention : seules les lignes non vides sont contenues dans l'iterator. Ainsi il n'y pas de corrélation entre le numéro de la ligne de l'iterator et le numéro de la ligne dans la feuille. Pour connaître le numéro de la ligne dans la feuille, il faut utiliser la méthode getRowNum() de la classe HSSFRow.

La classe HSSFRow propose la méthode cellIterator() qui renvoie un objet de type Iterator permettant de parcourir les cellules de la ligne.

Attention : seules les cellules non vides sont contenues dans l'iterator. Ainsi il n'y pas de corrélation entre le numéro de la cellule de l'iterator et le numéro de la cellule dans la ligne. Pour connaître le numéro de la colonne dans la ligne, il faut utiliser la méthode getCellNum() de la classe HSSFCell.

L'exemple ci-dessous va utiliser le fichier suivant :

L'application va parcourir les cellules et afficher le total de chaque ligne et le total de toutes les cellules.

Exemple :
package fr.jmdoudoux.dej.poi;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Iterator;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;

public class TestPOI12 {

  public static void main(
      String[] args) {

    try {
      POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream("monfichier.xls"));
      HSSFWorkbook wb = new HSSFWorkbook(fs);
      HSSFSheet sheet = wb.getSheetAt(0);
      HSSFRow row = null;
      HSSFCell cell = null;
      double totalLigne = 0.0;
      double totalGeneral = 0.0;
      int numLigne = 1;
      
      for (Iterator rowIt = sheet.rowIterator(); rowIt.hasNext();) {
        totalLigne = 0;
        row = (HSSFRow) rowIt.next();
        for (Iterator cellIt = row.cellIterator(); cellIt.hasNext();) {
          cell = (HSSFCell) cellIt.next();
          totalLigne += cell.getNumericCellValue();
        }
        System.out.println("total ligne "+numLigne+" = "+totalLigne);
        totalGeneral += totalLigne;
        numLigne++;
      }
      System.out.println("total general "+totalGeneral);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}
Résultat :
total ligne 1 = 10.0
total ligne 2 = 100.0
total ligne 3 = 1000.0
total general 1110.0

Il est aussi possible d'utiliser les generics de Java 5.

Exemple :
package fr.jmdoudoux.dej.poi;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Iterator;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;

public class TestPOI12 {

  public static void main(
      String[] args) {

    try {
      POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream("monfichier.xls"));
      HSSFWorkbook wb = new HSSFWorkbook(fs);
      HSSFSheet sheet = wb.getSheetAt(0);
      HSSFRow row = null;
      HSSFCell cell = null;
      double totalLigne = 0.0;
      double totalGeneral = 0.0;
      int numLigne = 1;
      
      for (Iterator<HSSFRow> rowIt = (Iterator<HSSFRow>) sheet.rowIterator(); 
        rowIt.hasNext();) {
        totalLigne = 0;
        row = rowIt.next();
        for (Iterator<HSSFCell> cellIt = (Iterator<HSSFCell>) row.cellIterator(); 
          cellIt.hasNext();) {
          cell = cellIt.next();
          totalLigne += cell.getNumericCellValue();
        }
        System.out.println("total ligne "+numLigne+" = "+totalLigne);
        totalGeneral += totalLigne;
        numLigne++;
      }
      System.out.println("total general "+totalGeneral);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

 

108.1.1.1.8. La génération d'un document Excel dans une servlet

Il peut être utile de faire générer un document Excel par une servlet pour que celle-ci retourne le document dans sa réponse.

Il est nécessaire de correctement positionner le type mime sur "application/vnd.ms-excel" qui désigne l'application Excel.

Il est aussi utile de définir la propriété "Content-disposition" pour faciliter l'enregistrement du document par l'utilisateur.

Enfin, il faut simplement fournir en paramètre de la méthode write() de la classe HSSFWorkbook le flux de sortie de la réponse HTTP de la servlet.

Exemple :
package fr.jmdoudoux.dej.poi;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

public class GenereExcel extends javax.servlet.http.HttpServlet 
  implements javax.servlet.Servlet {

  public GenereExcel() {
    super();
  }

  protected void doGet(
      HttpServletRequest request,
      HttpServletResponse response) throws ServletException, IOException {
    try {
      OutputStream out = response.getOutputStream();

      response.setContentType("application/vnd.ms-excel");

      response.setHeader("Content-disposition", "inline; filename=monfichier.xls");
      HSSFWorkbook wb = new HSSFWorkbook();

      HSSFSheet sheet = wb.createSheet("ma feuille");

      HSSFRow row = sheet.createRow(0);
      HSSFCell cell = row.createCell((short) 0);
      cell.setCellValue(10);

      row.createCell((short) 1).setCellValue(20);

      wb.write(out);
      out.flush();
      out.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

 

108.1.1.2. L'API de type eventusermodel

L'utilisation de cette API est particulièrement adaptée à la lecture de gros fichiers Excel car elle ne charge pas le document en mémoire mais émet des événements lors de sa lecture. Cette API permet uniquement la lecture de document.

Sa mise en oeuvre n'est cependant pas triviale et nécessite quelques notions sur la structure de bas niveau du document Excel.

Consultez la documentation de POI-HSSF pour le détail de sa mise en oeuvre.

 

108.2. iText

 iText est une API open source qui permet la génération de documents PDF, RTF et HTML. Elle est diffusée sous deux licences : MPL et LGPL.

Le site officiel de cette API est à l'url : https://itextpdf.com

iText contient de très nombreuses classes permettant de réaliser des actions basiques comme avancées, notamment pour la génération de documents de type PDF.

iText est une API qui permet d'intégrer dans une application la génération dynamique de documents : ceci est particulièrement utile lorsque le contenu du document dépend d'informations fournies par l'utilisateur ou encore quand ce contenu est calculé.

La possibilité d'iText d'exporter un document créé avec l'API dans différents formats peut être pratique. Le document exporté peut en outre être envoyé vers différents flux (fichier, réponse http d'une servlet, console, ... ).

iText permet aussi la mise en oeuvre de fonctionnalités avancées sur un document PDF :

  • définition de marque-pages, filigranes, ...
  • signature numérique
  • remplissage de formulaires
  • diviser un document ou assembler plusieurs documents
  • ...

iText requiert un JDK 1.4 minimum et l'API BouncyCastle pour certaines fonctionnalités.

 

108.2.1. Un exemple très simple

L'exemple proposé va créer un document PDF qui contient "Hello World".

La création d'un document PDF avec iText se fait en cinq étapes :

  • Instanciation d'un objet de type Document
  • Instanciation d'un objet de type PdfWriter pour exporter le document
  • Appel de la méthode open() du document
  • Création et ajout des éléments qui composent le document
  • Appel de la méthode close() pour exporter le document
Exemple :
package fr.jmdoudoux.dej.itext;

import java.io.FileOutputStream;
import java.io.IOException;

import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.PageSize;
import com.lowagie.text.Paragraph;
import com.lowagie.text.pdf.PdfWriter;

public class TestIText1 {

  public static void main(String[] args) {

    Document document = new Document(PageSize.A4);
    try {
      PdfWriter.getInstance(document,
          new FileOutputStream("c:/test.pdf"));
      document.open();
      document.add(new Paragraph("Hello World"));
    } catch (DocumentException de) {
      de.printStackTrace();
    } catch (IOException ioe) {
      ioe.printStackTrace();
    }

    document.close();
  }
}

Pour compiler et exécuter cet exemple, il faut ajouter la bibliothèque iText-2.1.3.jar au classpath.

 

108.2.2. L'API de iText

L'API de iText contient des objets qui proposent des fonctionnalités pour la création de documents notamment au format PDF. Ils encapsulent par exemple le document et chacun des éléments qui peuvent le composer tels que les objets de type Font, Paragraph, Chapter, Anchor, Image, List, Table, ...

L'API de iText est composée de nombreuses classes : seules les principales sont présentées dans cette section. Le site officiel et la Javadoc de l'API fournissent des informations détaillées sur l'ensemble des fonctionnalités de chacune des classes.

 

108.2.3. La création d'un document

La création d'un document avec iText se fait en plusieurs étapes :

  • instanciation d'un objet de type Document
  • instanciation d'un objet de type Writer pour exporter le document
  • appel de la méthode open() du document
  • création et ajout des éléments qui composent le document
  • appel de la méthode close() pour exporter le document

 

108.2.3.1. La classe Document

La classe Document est un conteneur pour le contenu d'un document.

L'objet Document possède plusieurs constructeurs :

Constructeur

Rôle

Document()

constructeur par défaut

Document(Rectangle pageSize)

constructeur qui précise la taille des pages du document

Document(Rectangle pageSize, int marginLeft, int marginRight, int marginTop, int marginBottom)

constructeur qui précise la taille des pages du document et leurs marges


La taille des pages peut être définies en utilisant deux des surcharges du constructeur ou en utilisant la méthode setPageSize().

Un objet de type Rectangle permet de définir la taille des pages du document.

L'unité de mesure dans un document est le point. Il y a 72 points dans un pouce et un pouce vaut 2,54 cm. Ainsi par exemple, la taille d'une page A4 vaut :

largeur : (21 / 2,54) * 72 = 595 points

hauteur : (29,7 / 2,54) * 72 = 842 points

La classe PageSize définit de nombreuses constantes de type Rectangle pour les tailles de pages standards (A0 à A10, LETTER, LEGAL, ...).

Par défaut, la taille utilisée est PageSize.A4.

La plupart des tailles prédéfinies sont au format portrait. Pour utiliser une taille au format paysage, il faut utiliser la méthode rotate() de la classe Rectangle.

Exemple :
...
      Document document = new Document(PageSize.A4.rotate());
...

La marge par défaut est de 36 points. La marge par défaut peut être précisée dans la surcharge du constructeur dédiée ou en utilisant la méthode setMargins(). Durant la création du contenu d'un document, il est possible d'utiliser la méthode setMargins() pour modifier les marges : cette modification ne sera effective qu'à partir de la page suivante.

La mise en oeuvre d'un document impose quelques contraintes :

  • les métadonnées doivent impérativement être associées au document avant l'appel de la méthode open()
  • il n'est possible d'ajouter le contenu du document qu'une fois que la méthode open() a été invoquée
  • la modification de l'en-tête et du pied page n'est effective qu'à partir de la page suivante

La classe Document possède plusieurs méthodes pour associer des métadonnées au document :

Méthode

Rôle

boolean addTitle(String title)

ajout du titre du document fourni en paramètre

boolean addSubject(String subject)

ajout du sujet du document fourni en paramètre

boolean addKeywords(String keywords)

ajout du mot clé fourni en paramètre

boolean addAuthor(String author)

ajout de l'auteur fourni en paramètre

boolean addCreator(String creator)

ajout du créateur fourni en paramètre

boolean addProducer()

ajout iText comme outil de production du document

boolean addCreationDate()

ajout de la date actuelle comme date de création

boolean addHeader(String name, String content)

ajout d'une métadonnée personnalisée


Remarque : l'utilisation de la méthode addHeader() n'a pas d'effet si le document est exporté en PDF.

Exemple :
package fr.jmdoudoux.dej.itext;

import java.io.FileOutputStream;
import java.io.IOException;

import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.PageSize;
import com.lowagie.text.Paragraph;
import com.lowagie.text.pdf.PdfWriter;

public class TestIText3 {

  public static void main(String[] args) {

    Document document = new Document(PageSize.A4);
    try {
      PdfWriter.getInstance(document,
          new FileOutputStream("c:/test.pdf"));
      document.addTitle("Hello World");
      document.addAuthor("JM doudoux");
      document.addSubject("Exemple de génération de PDF.");
      document.addKeywords("iText, test");
      document.open();
      document.add(new Paragraph("Hello World"));
    } catch (DocumentException de) {
      de.printStackTrace();
    } catch (IOException ioe) {
      ioe.printStackTrace();
    }

    document.close();
  }
}

Important : l'ajout de métadonnées doit obligatoirement se faire avant l'appel à la méthode open().

Avant de pouvoir ajouter du contenu au document, il faut obligatoirement invoquer la méthode open() de l'instance de la classe Document. Dans le cas contraire, une exception de type DocumentException est levée.

Exemple :
package fr.jmdoudoux.dej.itext;

import java.io.FileOutputStream;
import java.io.IOException;

import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.PageSize;
import com.lowagie.text.Paragraph;
import com.lowagie.text.pdf.PdfWriter;

public class TestIText2 {

  public static void main(String[] args) {

    Document document = new Document(PageSize.A4);
    try {
      PdfWriter.getInstance(document,
          new FileOutputStream("c:/test.pdf"));
      document.add(new Paragraph("Hello World"));
    } catch (DocumentException de) {
      de.printStackTrace();
    } catch (IOException ioe) {
      ioe.printStackTrace();
    }

    document.close();
  }
}
Résultat :
com.lowagie.text.DocumentException: The document is not open yet; you can only add Meta 
information.
               at com.lowagie.text.Document.add(Unknown Source)
               at fr.jmdoudoux.dej.itext.TestIText2.main(TestIText2.java:20)
Exception in thread "main" java.lang.RuntimeException: The document is not open.
               at com.lowagie.text.pdf.PdfWriter.getDirectContent(Unknown Source)
               at com.lowagie.text.pdf.PdfDocument.newPage(Unknown Source)
               at com.lowagie.text.pdf.PdfDocument.close(Unknown Source)
               at com.lowagie.text.Document.close(Unknown Source)
               at fr.jmdoudoux.dej.itext.TestIText2.main(TestIText2.java:27)

La méthode add() permet d'ajouter un élément au contenu du document.

Il est important d'invoquer la méthode close() du document une fois celui-ci complet : la méthode close() va demander la fermeture du ou des flux d'exportation du document.

Attention : la classe Document encapsule le contenu du document mais ne contient aucune information sur son rendu. Le rendu est assuré par différents writers (par exemple un document peut avoir plusieurs pages en PDF mais une seule en HTML) : ainsi il ne faut pas utiliser la méthode getPageNumber() de la classe Document.

 

108.2.3.2. Les objets de type DocWriter

Pour exporter le document, il faut lui associer un ou plusieurs DocWriters. Chaque DocWriter permet l'exportation du document dans un format particulier.

Trois classes héritent de la classe DocWriter. PdfWriter, HtmlWriter et RtfWriter2 exportent respectivement au format Pdf, Html et Rtf.

Pour obtenir une instance d'un objet héritant du type DocWriter, il faut utiliser sa méthode statique getInstance() qui attend en paramètre l'instance du document et le flux vers lequel le document sera exporté. Ce flux peut être de différents types selon les besoins : FileOutputStream pour un fichier, ServletOutputStream pour une réponse d'une servlet, ByteArrayOutputStream pour stocker le document en mémoire, ...

Il est possible d'affecter plusieurs DocWriter à un document utilisant des flux différents.

Il est nécessaire de conserver l'instance retournée par la méthode getInstance() pour mettre en oeuvre quelques fonctionnalités avancées de l'exportation.

 

108.2.3.2.1. La classe PdfWriter

La classe PdfWriter permet l'exportation d'un document au format PDF.

Elle propose de nombreuses méthodes permettant de définir des caractéristiques spécifiques au format PDF.

La méthode setViewerPreferences() permet de préciser le mode d'affichage du document par défaut. Elle attend en paramètre un entier pour lequel plusieurs constantes sont définies.

Plusieurs constantes peuvent être combinées pour préciser le mode d'affichage des éléments du panneau de navigation.

Constante

Rôle

PdfWriter.PageModeFullScreen

affichage en plein écran

PdfWriter.PageModeUseAttachments

afficher les pièces jointes

PdfWriter.PageModeUseNone

n'afficher aucun élément du panneau de navigation

PdfWriter.PageModeUseOC

afficher les calques

PdfWriter.PageModeUseOutlines

afficher l'arborescence

PdfWriter.PageModeUseThumbs

affichage des vignettes


Plusieurs autres constantes peuvent être combinées pour préciser le mode d'affichage des pages.

Constante

Rôle

PdfWriter.PageLayoutSinglePage

affichage d'une seule page à la fois

PdfWriter.PageLayoutOneColumn

affichage des pages dans une colonne

PdfWriter.PageLayoutTwoColumnLeft

affichage des pages dans deux colonnes de gauche à droite

PdfWriter.PageLayoutTwoColumnRight

affichage des pages dans deux colonnes (de droite à gauche)


D'autres constantes peuvent être combinées pour afficher ou non quelques éléments de l'interface graphique d'Adobe Reader.

Constante

Rôle

PdfWriter.HideToolBar

permet de spécifier si la barre d'outils est affichée

PdfWriter.HideMenuBar

permet de spécifier si la barre de menu est affichée

PdfWriter.HideWindowUI

permet de spécifier si les contrôles de navigation sont affichés


Exemple :
package fr.jmdoudoux.dej.itext;

import java.io.FileOutputStream;
import java.io.IOException;

import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.PageSize;
import com.lowagie.text.Paragraph;
import com.lowagie.text.pdf.PdfWriter;

public class TestIText4 {

  public static void main(String[] args) {

    Document document = new Document(PageSize.A4);
    try {
      PdfWriter writer = PdfWriter.getInstance(document,
          new FileOutputStream("c:/test.pdf"));
      writer.setViewerPreferences(PdfWriter.PageLayoutSinglePage
          | PdfWriter.PageModeUseThumbs);

      document.open();
      document.add(new Paragraph("Hello World"));
    } catch (DocumentException de) {
      de.printStackTrace();
    } catch (IOException ioe) {
      ioe.printStackTrace();
    }
    document.close();
  }
}

 

108.2.4. L'ajout de contenu au document

IText propose de nombreuses classes qui encapsulent des éléments qui pourront être ajoutés au contenu d'un document.

Cependant, toutes ces classes ne sont pas supportées par tous les DocWriters : si une classe n'est pas supportée par le DocWriter alors celle-ci est ignorée lors de l'exportation du document qui la contient.

 

108.2.4.1. Les polices de caractères

Par défaut, un document peut utiliser 14 polices de caractères standards : Courier, Courier Bold, Courier Italic, Courier Bold and Italic, Helvetica, Helvetica Bold, Helvetica Italic, Helvetica Bold and Italic, Times Roman, Times Roman Bold, Times Roman Italic, Times Roman Bold and Italic, Symbol et ZapfDingBats.

Chaque variante de type bold, italic et bold italic pour Courier, Helvetica et Times Roman sont proposées chacune sous la forme d'une police dédiée.

Une police de caractères est encapsulée dans un objet de type Font.

La classe Font encapsule les caractéristiques de la police de caractères : la famille, la taille, le style et la couleur. Elle possède de nombreux constructeurs pour définir ces différentes informations.

Elle propose des constantes pour :

  • la famille : COURIER, HELVETICA, SYMBOL, TIMES_ROMAN, ZAPFDINGBATS
  • la taille : DEFAULTSIZE
  • le style : BOLD, BOLDITALIC, ITALIC, NORMAL, STRIKETHRU, UNDERLINE
Exemple :
package fr.jmdoudoux.dej.itext;

import java.awt.Color;
import java.io.FileOutputStream;
import java.io.IOException;

import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Font;
import com.lowagie.text.PageSize;
import com.lowagie.text.Paragraph;
import com.lowagie.text.pdf.PdfWriter;

public class TestIText5 {

  public static void main(String[] args) {

    Document document = new Document(PageSize.A4);
    try {
      PdfWriter writer = PdfWriter.getInstance(document,
          new FileOutputStream("c:/test.pdf"));
      document.open();
      document.add(new Paragraph("Hello World", 
	    new Font(Font.COURIER, 28, Font.BOLD, Color.RED)));
    } catch (DocumentException de) {
      de.printStackTrace();
    } catch (IOException ioe) {
      ioe.printStackTrace();
    }

    document.close();
  }
}

iText propose une fabrique pour instancier des polices de caractères.

Exemple :
package fr.jmdoudoux.dej.itext;

import java.awt.Color;
import java.io.FileOutputStream;
import java.io.IOException;

import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Font;
import com.lowagie.text.FontFactory;
import com.lowagie.text.PageSize;
import com.lowagie.text.Paragraph;
import com.lowagie.text.pdf.PdfWriter;

public class TestIText6 {

  public static void main(String[] args) {

    Document document = new Document(PageSize.A4);
    try {
      PdfWriter.getInstance(document, new FileOutputStream("c:/test.pdf"));
      document.open();
      document.add(new Paragraph("Hello World", FontFactory.getFont(
          FontFactory.COURIER,
            28f,
            Font.BOLD,
            Color.RED)));
    } catch (DocumentException de) {
      de.printStackTrace();
    } catch (IOException ioe) {
      ioe.printStackTrace();
    }

    document.close();
  }
}

Tous les objets retournés par la fabrique héritent de la classe BaseFont. La classe BaseFont propose plusieurs surcharges de la méthode createFont() pour instancier un objet de type Font.

Exemple :
package fr.jmdoudoux.dej.itext;

import java.awt.Color;
import java.io.FileOutputStream;
import java.io.IOException;

import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Font;
import com.lowagie.text.PageSize;
import com.lowagie.text.Paragraph;
import com.lowagie.text.pdf.BaseFont;
import com.lowagie.text.pdf.PdfWriter;

public class TestIText7 {

  public static void main(String[] args) {

    Document document = new Document(PageSize.A4);
    try {
      PdfWriter.getInstance(document, new FileOutputStream("c:/test.pdf"));
      document.open();
      
      BaseFont fonte = BaseFont.createFont(
          BaseFont.COURIER,
          BaseFont.CP1252,
          BaseFont.NOT_EMBEDDED);
      Font maFonte = new Font(fonte);
      maFonte.setColor(Color.RED);
      maFonte.setStyle(Font.BOLD);
      maFonte.setSize(38.0f);
      
      document.add(new Paragraph("Hello World", maFonte));
    } catch (DocumentException de) {
      de.printStackTrace();
    } catch (IOException ioe) {
      ioe.printStackTrace();
    }

    document.close();
  }
}

Il est possible d'utiliser n'importe quelle fonte true type présente sur le système.

Exemple :
package fr.jmdoudoux.dej.itext;

import java.awt.Color;
import java.io.FileOutputStream;
import java.io.IOException;

import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Font;
import com.lowagie.text.PageSize;
import com.lowagie.text.Paragraph;
import com.lowagie.text.pdf.BaseFont;
import com.lowagie.text.pdf.PdfWriter;

public class TestIText8 {

  public static void main(String[] args) {

    Document document = new Document(PageSize.A4);
    try {
      PdfWriter.getInstance(document, new FileOutputStream("c:/test.pdf"));
      document.open();
      
      BaseFont fonte = BaseFont.createFont(
          "C:/Windows/FONTS/ARIAL.TTF",
          BaseFont.CP1252,
          BaseFont.NOT_EMBEDDED);
      Font maFonte = new Font(fonte);
      maFonte.setColor(Color.RED);
      maFonte.setStyle(Font.BOLD);
      maFonte.setSize(38.0f);
      
      document.add(new Paragraph("Hello World", maFonte));
    } catch (DocumentException de) {
      de.printStackTrace();
    } catch (IOException ioe) {
      ioe.printStackTrace();
    }

    document.close();
  }
}

La méthode createFont() possède plusieurs surcharges. Celle utilisée dans l'exemple attend en paramètre le chemin du fichier qui contient la police true type, l'encodage utilisé (plusieurs constantes sont définies : CP1250, CP1252, CP1257, MACROMAN, WINANSI) et un booléen qui précise si la police doit être incluse dans le PDF (deux constantes sont définies : EMBEDDED et NOT_EMBEDDED).

PDF fourni en standard 3 polices de caractères texte avec les styles normal, gras, italique et gras/italique (Courier, Helvetica et Times) et deux polices de symboles (Symbol et Zapf Dingbats). Il est donc inutile d'inclure ces polices dans le fichier PDF.

Il est possible d'utiliser la méthode register() de la classe FontFactory() pour enregistrer une police True Type en précisant le chemin du fichier de la police en paramètre. Une surcharge de cette méthode attend en plus en paramètre un nom d'alias pour accéder à la police.

Exemple :
package fr.jmdoudoux.dej.itext;

import java.awt.Color;
import java.io.FileOutputStream;
import java.io.IOException;

import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Font;
import com.lowagie.text.FontFactory;
import com.lowagie.text.PageSize;
import com.lowagie.text.Paragraph;
import com.lowagie.text.pdf.BaseFont;
import com.lowagie.text.pdf.PdfWriter;

public class TestIText9 {

  public static void main(String[] args) {

    Document document = new Document(PageSize.A4);
    try {
      PdfWriter.getInstance(document, new FileOutputStream("c:/test.pdf"));
      document.open();
      
      FontFactory.register("C:/Windows/FONTS/ARIAL.TTF");

      Font fonte = FontFactory.getFont("arial", BaseFont.WINANSI, 38);
      
      Font maFonte = new Font(fonte);
      maFonte.setColor(Color.RED);
      maFonte.setStyle(Font.BOLD);
      
      document.add(new Paragraph("Hello World", maFonte));
    } catch (DocumentException de) {
      de.printStackTrace();
    } catch (IOException ioe) {
      ioe.printStackTrace();
    }

    document.close();
  }
}

 

108.2.4.2. Le classe Chunk

La classe Chunk encapsule une portion de texte du document affiché avec une certaine police de caractères. C'est la plus petite unité de texte utilisable.

Exemple :
package fr.jmdoudoux.dej.itext;

import java.awt.Color;
import java.io.FileOutputStream;
import java.io.IOException;

import com.lowagie.text.Chunk;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Font;
import com.lowagie.text.FontFactory;
import com.lowagie.text.PageSize;
import com.lowagie.text.pdf.PdfWriter;

public class TestIText10 {

  public static void main(String[] args) {

    Document document = new Document(PageSize.A4);
    try {
      PdfWriter.getInstance(document, new FileOutputStream("c:/test.pdf"));
      document.open();
      
      Chunk chunk = new Chunk("Hello world", 
	    FontFactory.getFont(FontFactory.COURIER, 20, Font.BOLD, Color.BLUE));
      
      document.add(chunk);
      
    } catch (DocumentException de) {
      de.printStackTrace();
    } catch (IOException ioe) {
      ioe.printStackTrace();
    }

    document.close();
  }
}

La méthode setUnderline() permet pour les documents PDF d'avoir un contrôle précis sur les caractéristiques du soulignement de la portion de texte. Le premier paramètre précise l'épaisseur du trait et le second précise la position du trait.

Exemple :
package fr.jmdoudoux.dej.itext;

import java.awt.Color;
import java.io.FileOutputStream;
import java.io.IOException;

import com.lowagie.text.Chunk;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Font;
import com.lowagie.text.FontFactory;
import com.lowagie.text.PageSize;
import com.lowagie.text.pdf.PdfWriter;

public class TestIText11 {

  public static void main(String[] args) {

    Document document = new Document(PageSize.A4);
    try {
      PdfWriter.getInstance(document, new FileOutputStream("c:/test.pdf"));
      document.open();
      
      Chunk chunk = new Chunk("Hello world", 
	    FontFactory.getFont(FontFactory.COURIER, 20, Font.BOLD, Color.BLUE));
      chunk.setUnderline(0.2f,-2f);
      document.add(chunk);
      
      chunk = new Chunk("Hello world", 
	    FontFactory.getFont(FontFactory.COURIER, 20, Font.BOLD, Color.BLUE));
      chunk.setUnderline(2f,5f);
      document.add(chunk);
      
    } catch (DocumentException de) {
      de.printStackTrace();
    } catch (IOException ioe) {
      ioe.printStackTrace();
    }

    document.close();
  }
}

Une surcharge de cette méthode permet de fournir des précisions sur l'apparence du trait.

Exemple :
package fr.jmdoudoux.dej.itext;

import java.awt.Color;
import java.io.FileOutputStream;
import java.io.IOException;

import com.lowagie.text.Chunk;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Font;
import com.lowagie.text.FontFactory;
import com.lowagie.text.PageSize;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfWriter;

public class TestIText12 {

  public static void main(String[] args) {

    Document document = new Document(PageSize.A4);
    try {
      PdfWriter.getInstance(document, new FileOutputStream("c:/test.pdf"));
      document.open();
      
      Chunk chunk = new Chunk("Hello world", 
	    FontFactory.getFont(FontFactory.COURIER, 20, Font.BOLD, Color.BLUE));
      chunk.setUnderline(Color.BLUE, 5.0f, 0.0f, 0.0f, -0.2f, 
	    PdfContentByte.LINE_CAP_ROUND);
      document.add(chunk);

    } catch (DocumentException de) {
      de.printStackTrace();
    } catch (IOException ioe) {
      ioe.printStackTrace();
    }

    document.close();
  }
}

La méthode setBackground() permet de modifier la couleur de fond de la portion de texte.

Exemple :
package fr.jmdoudoux.dej.itext;

import java.awt.Color;
import java.io.FileOutputStream;
import java.io.IOException;

import com.lowagie.text.Chunk;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Font;
import com.lowagie.text.FontFactory;
import com.lowagie.text.PageSize;
import com.lowagie.text.pdf.PdfWriter;

public class TestIText13 {

  public static void main(String[] args) {

    Document document = new Document(PageSize.A4);
    try {
      PdfWriter.getInstance(document, new FileOutputStream("c:/test.pdf"));
      document.open();
      
      Chunk chunk = new Chunk("Hello world", 
	    FontFactory.getFont(FontFactory.COURIER, 20, Font.BOLD, Color.WHITE));
      chunk.setBackground(Color.BLUE);
      document.add(chunk);

      
    } catch (DocumentException de) {
      de.printStackTrace();
    } catch (IOException ioe) {
      ioe.printStackTrace();
    }

    document.close();
  }
}

 

108.2.4.3. La classe Phrase

La classe Phrase encapsule une série d'objets de type Chunk qui forme une ou plusieurs lignes dont l'espacement est défini.

Elle possède de nombreux constructeurs.

Exemple :
package fr.jmdoudoux.dej.itext;

import java.io.FileOutputStream;
import java.io.IOException;

import com.lowagie.text.Chunk;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.PageSize;
import com.lowagie.text.Phrase;
import com.lowagie.text.pdf.PdfWriter;

public class TestIText13 {

  public static void main(String[] args) {

    Document document = new Document(PageSize.A4);
    try {
      PdfWriter.getInstance(document, new FileOutputStream("c:/test.pdf"));
      document.open();

      Phrase phrase = new Phrase(new Chunk("Hello world "));
      phrase
          .add(new Chunk(
              " test de phrase dont la longueur dépasse largement une seule ligne"));
      phrase.add(new Chunk(" grace à un commentaire assez long"));
      document.add(phrase);

    } catch (DocumentException de) {
      de.printStackTrace();
    } catch (IOException ioe) {
      ioe.printStackTrace();
    }

    document.close();
  }
}

La propriété leading de la classe Phrase permet de définir l'espacement entre deux lignes.

Exemple :
package fr.jmdoudoux.dej.itext;

import java.io.FileOutputStream;
import java.io.IOException;

import com.lowagie.text.Chunk;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.PageSize;
import com.lowagie.text.Phrase;
import com.lowagie.text.pdf.PdfWriter;

public class TestIText14 {

  public static void main(String[] args) {

    Document document = new Document(PageSize.A4);
    try {
      PdfWriter.getInstance(document, new FileOutputStream("c:/test.pdf"));
      document.open();

      Phrase phrase = new Phrase(new Chunk("Hello world "));
      phrase.setLeading(20f);
      phrase
          .add(new Chunk(
              " test de pharse dont la longueur dépasse"+
			  " largement une seule ligne"));
      phrase.add(new Chunk(" grace à un commentaire assez long"));
      document.add(phrase);

    } catch (DocumentException de) {
      de.printStackTrace();
    } catch (IOException ioe) {
      ioe.printStackTrace();
    }

    document.close();
  }
}

 

108.2.4.4. La classe Paragraph

La classe Paragraph encapsule un ensemble d'objets de type Chunk et/ou Phrase pour former un paragraphe. Chacun de ces objets peut avoir des polices de caractères différentes.

Un paragraphe commence systématiquement sur une nouvelle ligne.

La propriété leading permet de préciser l'espacement entre deux lignes.

Exemple :
package fr.jmdoudoux.dej.itext;

import java.io.FileOutputStream;
import java.io.IOException;

import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.PageSize;
import com.lowagie.text.Paragraph;
import com.lowagie.text.pdf.PdfWriter;

public class TestIText15 {

  public static void main(String[] args) {

    Document document = new Document(PageSize.A4);
    try {
      PdfWriter.getInstance(document, new FileOutputStream("c:/test.pdf"));
      document.open();

      document.add(new Paragraph("ligne 1"));
      document.add(new Paragraph("ligne 2"));
      document.add(new Paragraph("ligne 3"));

    } catch (DocumentException de) {
      de.printStackTrace();
    } catch (IOException ioe) {
      ioe.printStackTrace();
    }

    document.close();
  }
}

La méthode setAlignment() permet de définir l'alignement du paragraphe grâce à plusieurs constantes : Element.ALIGN_LEFT, Element.ALIGN_CENTER, Element.ALIGN_RIGHT et Element.ALIGN_JUSTIFIED

Exemple :
package fr.jmdoudoux.dej.itext;

import java.io.FileOutputStream;
import java.io.IOException;

import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Element;
import com.lowagie.text.PageSize;
import com.lowagie.text.Paragraph;
import com.lowagie.text.pdf.PdfWriter;

public class TestIText16 {

  public static void main(String[] args) {

    Document document = new Document(PageSize.A4);
    try {
      PdfWriter.getInstance(document, new FileOutputStream("c:/test.pdf"));
      document.open();

      document.add(new Paragraph("ligne 1"));
      Paragraph paragraph = new Paragraph("ligne 2");
      paragraph.setAlignment(Element.ALIGN_CENTER);
      document.add(paragraph);
      document.add(new Paragraph("ligne 3"));

    } catch (DocumentException de) {
      de.printStackTrace();
    } catch (IOException ioe) {
      ioe.printStackTrace();
    }

    document.close();
  }
}

Il est possible de préciser une indentation à gauche et/ou à droite respectivement grâce aux méthodes setIndentationLeft() et setIndentationRight().

Exemple :
package fr.jmdoudoux.dej.itext;

import java.io.FileOutputStream;
import java.io.IOException;

import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.PageSize;
import com.lowagie.text.Paragraph;
import com.lowagie.text.pdf.PdfWriter;

public class TestIText17 {

  public static void main(String[] args) {

    Document document = new Document(PageSize.A4);
    try {
      PdfWriter.getInstance(document, new FileOutputStream("c:/test.pdf"));
      document.open();

      Paragraph paragraph = new Paragraph(
          "ligne 1 test de phrase dont la longueur dépasse"+
		  " largement une seule ligne grace à un commentaire assez long");
      paragraph.setIndentationLeft(20f);
      document.add(paragraph);
      paragraph = new Paragraph(
          "ligne 2 test de phrase dont la longueur dépasse"+
		  " largement une seule ligne grace à un commentaire assez long");
      paragraph.setIndentationRight(20f);
      document.add(paragraph);

    } catch (DocumentException de) {
      de.printStackTrace();
    } catch (IOException ioe) {
      ioe.printStackTrace();
    }

    document.close();
  }
}

Les méthodes setSpacingBefore() et setSpacingAfter() permettent respectivement de préciser l'espace avant et après le paragraphe.

 

108.2.4.5. La classe Chapter

La classe Chapter encapsule un chapitre. Elle hérite de la classe Section.

Un chapitre commence sur une nouvelle page et possède un numéro affiché par défaut.

Exemple :
package fr.jmdoudoux.dej.itext;

import java.io.FileOutputStream;
import java.io.IOException;

import com.lowagie.text.Chapter;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.PageSize;
import com.lowagie.text.Paragraph;
import com.lowagie.text.pdf.PdfWriter;

public class TestIText18 {

  public static void main(String[] args) {

    Document document = new Document(PageSize.A4);
    try {
      PdfWriter.getInstance(document, new FileOutputStream("c:/test.pdf"));
      document.open();

      Chapter chapter = new Chapter(new Paragraph("Premier chapitre"), 1);

      Paragraph paragraph = new Paragraph("ligne 1 test de phrase");
      chapter.add(paragraph);
      paragraph = new Paragraph("ligne 2 test de phrase");
      chapter.add(paragraph);
      document.add(chapter);

      chapter = new Chapter(new Paragraph("Second chapitre"), 1);
      paragraph = new Paragraph("ligne 3 test de phrase");
      chapter.add(paragraph);
      document.add(chapter);
      
    } catch (DocumentException de) {
      de.printStackTrace();
    } catch (IOException ioe) {
      ioe.printStackTrace();
    }

    document.close();
  }
}

Pour ne pas afficher le numéro, il faut invoquer la méthode setNumberDepth() avec la valeur 0 en paramètre.

 

108.2.4.6. La classe Section

La classe Section encapsule une section qui est un sous-ensemble d'un chapitre.

Pour ajouter une section, il faut utiliser la méthode addSection() qui retourne une instance de la Section.

Exemple :
package fr.jmdoudoux.dej.itext;

import java.io.FileOutputStream;
import java.io.IOException;

import com.lowagie.text.Chapter;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.PageSize;
import com.lowagie.text.Paragraph;
import com.lowagie.text.Section;
import com.lowagie.text.pdf.PdfWriter;

public class TestIText19 {

  public static void main(String[] args) {

    Document document = new Document(PageSize.A4);
    try {
      PdfWriter.getInstance(document, new FileOutputStream("c:/test.pdf"));
      document.open();

      Chapter chapter = new Chapter(new Paragraph("Mon chapitre"), 1);

      Section section = chapter.addSection(new Paragraph("Premiere section "), 2);
      section.setChapterNumber(1);
      
      Paragraph paragraph = new Paragraph("ligne 1 test de phrase");
      section.add(paragraph);
      paragraph = new Paragraph("ligne 2 test de phrase");
      section.add(paragraph);

      section = chapter.addSection(new Paragraph("Seconde section "), 2);
      section.setChapterNumber(2);
      
      paragraph = new Paragraph("ligne 3 test de phrase");
      section.add(paragraph);
      
      document.add(chapter);
      
    } catch (DocumentException de) {
      de.printStackTrace();
    } catch (IOException ioe) {
      ioe.printStackTrace();
    }

    document.close();
  }
}

La propriété numberDepth permet de préciser la profondeur de la section.

La méthode setChapterNumber() permet de préciser le numéro de la profondeur de la section.

 

108.2.4.7. La création d'une nouvelle page

Pour créer une nouvelle page, il faut invoquer la méthode newPage() de la classe Document.

Attention, l'appel à la méthode newPage() dans une page vide n'a aucun effet.

Pour créer une page vide, il faut ajouter une ligne

Exemple :
package fr.jmdoudoux.dej.itext;

import java.io.FileOutputStream;
import java.io.IOException;

import com.lowagie.text.Chapter;
import com.lowagie.text.Chunk;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.PageSize;
import com.lowagie.text.Paragraph;
import com.lowagie.text.Section;
import com.lowagie.text.pdf.PdfWriter;

public class TestIText21 {

  public static void main(String[] args) {

    Document document = new Document(PageSize.A4);
    try {
      PdfWriter.getInstance(document, new FileOutputStream("c:/test.pdf"));
      document.open();

      Paragraph paragraph = new Paragraph("ligne 1 test de phrase");
      document.add(paragraph);
      document.newPage();
      document.add(Chunk.NEWLINE);
      document.newPage();
      
      paragraph = new Paragraph("ligne 2 test de phrase");
      document.add(paragraph);
    } catch (DocumentException de) {
      de.printStackTrace();
    } catch (IOException ioe) {
      ioe.printStackTrace();
    }

    document.close();
  }
}

Dans une section, il faut lui ajouter un objet de type Chunk.NEXTPAGE.

Exemple :
package fr.jmdoudoux.dej.itext;

import java.io.FileOutputStream;
import java.io.IOException;

import com.lowagie.text.Chapter;
import com.lowagie.text.Chunk;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.PageSize;
import com.lowagie.text.Paragraph;
import com.lowagie.text.Section;
import com.lowagie.text.pdf.PdfWriter;

public class TestIText20 {

  public static void main(String[] args) {

    Document document = new Document(PageSize.A4);
    try {
      PdfWriter.getInstance(document, new FileOutputStream("c:/test.pdf"));
      document.open();

      Chapter chapter = new Chapter(new Paragraph("Mon chapitre"), 1);

      Section section = chapter.addSection(new Paragraph("Premiere section "), 2);
      section.setChapterNumber(1);
      
      Paragraph paragraph = new Paragraph("ligne 1 test de phrase");
      section.add(paragraph);
      paragraph = new Paragraph("ligne 2 test de phrase");
      section.add(paragraph);
      section.add(Chunk.NEXTPAGE);

      section = chapter.addSection(new Paragraph("Seconde section "), 2);
      section.setChapterNumber(2);
      
      paragraph = new Paragraph("ligne 3 test de phrase");
      section.add(paragraph);
      
      document.add(chapter);
    } catch (DocumentException de) {
      de.printStackTrace();
    } catch (IOException ioe) {
      ioe.printStackTrace();
    }

    document.close();
  }
}

 

108.2.4.8. La classe Anchor

La classe Anchor encapsule un lien hypertexte. Elle hérite de la classe Phrase.

La méthode setReference() permet de préciser l'url externe du lien.

La méthode setName() permet de préciser l'ancre pour un lien interne.

Exemple :
package fr.jmdoudoux.dej.itext;

import java.io.FileOutputStream;
import java.io.IOException;

import com.lowagie.text.Anchor;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.PageSize;
import com.lowagie.text.pdf.PdfWriter;

public class TestIText22 {

  public static void main(String[] args) {

    Document document = new Document(PageSize.A4);
    try {
      PdfWriter.getInstance(document, new FileOutputStream("c:/test.pdf"));
      document.open();

      Anchor anchor = new Anchor("mon site web");
      anchor.setReference("http://www.jmdoudoux.fr/");

      document.add(anchor);

    } catch (DocumentException de) {
      de.printStackTrace();
    } catch (IOException ioe) {
      ioe.printStackTrace();
    }

    document.close();
  }
}

 

108.2.4.9. Les classes List et ListItem

La classe List encapsule une liste d'éléments de type ListeItem.

La classe Liste possède plusieurs constructeurs. La liste peut être ordonnée ou non selon le premier paramètre fourni au constructeur utilisé : true indique une liste ordonnée.

Exemple :
package fr.jmdoudoux.dej.itext;

import java.io.FileOutputStream;
import java.io.IOException;

import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.List;
import com.lowagie.text.ListItem;
import com.lowagie.text.PageSize;
import com.lowagie.text.pdf.PdfWriter;

public class TestIText23 {

  public static void main(String[] args) {

    Document document = new Document(PageSize.A4);
    try {
      PdfWriter.getInstance(document, new FileOutputStream("c:/test.pdf"));
      document.open();

      List liste = new List(true, 20);
      liste.add(new ListItem("Element 1"));
      liste.add(new ListItem("Element 2"));
      liste.add(new ListItem("Element 3"));
      document.add(liste);
      
      liste = new List(false, 30);
      liste.add(new ListItem("Element 1"));
      liste.add(new ListItem("Element 2"));
      liste.add(new ListItem("Element 3"));
      document.add(liste);

    } catch (DocumentException de) {
      de.printStackTrace();
    } catch (IOException ioe) {
      ioe.printStackTrace();
    }

    document.close();
  }
}

La méthode setLettered() permet de préciser si la numérotation d'une liste ordonnée est littérale : la première valeur est dans ce cas A.

La méthode setNumbered() précise si la numérotation d'une liste ordonnée est numérique : la première valeur est dans ce cas 1.

Dans une liste ordonnée, la méthode setFirst() permet d'indiquer la valeur du premier élément pour une numérotation numérique ou littérale.

Dans une liste non ordonnée, la méthode setListeSymbol() permet de préciser le ou les caractères utilisés comme puces.

Exemple :
package fr.jmdoudoux.dej.itext;

import java.awt.Color;
import java.io.FileOutputStream;
import java.io.IOException;

import com.lowagie.text.Chunk;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Font;
import com.lowagie.text.FontFactory;
import com.lowagie.text.List;
import com.lowagie.text.ListItem;
import com.lowagie.text.PageSize;
import com.lowagie.text.pdf.PdfWriter;

public class TestIText24 {

  public static void main(String[] args) {

    Document document = new Document(PageSize.A4);
    try {
      PdfWriter.getInstance(document, new FileOutputStream("c:/test.pdf"));
      document.open();

      List liste = new List(20);
      liste.setListSymbol(new Chunk("B", 
	    FontFactory.getFont(FontFactory.ZAPFDINGBATS, 20, Font.BOLD, Color.BLUE)));
      liste.add(new ListItem("Element 1"));
      liste.add(new ListItem("Element 2"));
      liste.add(new ListItem("Element 3"));
      document.add(liste);
      
    } catch (DocumentException de) {
      de.printStackTrace();
    } catch (IOException ioe) {
      ioe.printStackTrace();
    }

    document.close();
  }
}

 

108.2.4.10. La classe Table

La classe com.lowagie.test.Table encapsule un tableau utilisé comme une matrice. Chaque cellule est encapsulée dans un objet de type Cell.

Il est possible de définir le nombre de lignes et de colonnes en utilisant la surcharge du constructeur adéquat.

Il est impératif de définir le nombre de colonnes ; le nombre de lignes peut croître selon les besoins.

La méthode addCell() permet de fournir la valeur de la cellule courante. Par défaut, c'est la cellule de la première ligne, première colonne. L'appel à la méthode déplace la cellule courante dans la même ligne sur la colonne suivante si elle existe sinon sur la première colonne de la ligne suivante.

Exemple :
package fr.jmdoudoux.dej.itext;

import java.io.FileOutputStream;
import java.io.IOException;

import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.PageSize;
import com.lowagie.text.Table;
import com.lowagie.text.pdf.PdfWriter;

public class TestIText25 {

  public static void main(String[] args) {

    Document document = new Document(PageSize.A4);
    try {
      PdfWriter.getInstance(document, new FileOutputStream("c:/test.pdf"));
      document.open();

      Table tableau = new Table(2,2);
      tableau.addCell("1.1");
      tableau.addCell("1.2");
      tableau.addCell("2.1");
      tableau.addCell("2.2");
      
      document.add(tableau);

      
    } catch (DocumentException de) {
      de.printStackTrace();
    } catch (IOException ioe) {
      ioe.printStackTrace();
    }

    document.close();
  }
}

La classe Table possède une surcharge de la méthode addCell() qui attend en second paramètre un objet de type Point qui permet d'indiquer une cellule bien précise dans le tableau.

La méthode setAutoFillEmptyCell() attend un booléen qui permet de préciser si les cellules non renseignées doivent être automatiquement créées vides.

Exemple :
package fr.jmdoudoux.dej.itext;

import java.awt.Point;
import java.io.FileOutputStream;
import java.io.IOException;

import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.PageSize;
import com.lowagie.text.Table;
import com.lowagie.text.pdf.PdfWriter;

public class TestIText26 {

  public static void main(String[] args) {

    Document document = new Document(PageSize.A4);
    try {
      PdfWriter.getInstance(document, new FileOutputStream("c:/test.pdf"));
      document.open();

      Table tableau = new Table(2,2);
      tableau.addCell("1.0", new Point(1,0));
      tableau.addCell("2.1", new Point(2,1));
      
      document.add(tableau);

      
    } catch (DocumentException de) {
      de.printStackTrace();
    } catch (IOException ioe) {
      ioe.printStackTrace();
    }

    document.close();
  }
}

La classe Table possède de nombreuses méthodes pour modifier son rendu par exemple : setBorderWidth(), setBorderColor(), setBackGroundColor(), setPadding(), ...

Pour obtenir plus de souplesse dans le rendu d'une cellule, il est possible d'instancier une occurrence de la classe Cell et d'invoquer les méthodes qu'elle propose pour configurer son apparence.

Exemple :
package fr.jmdoudoux.dej.itext;

import java.awt.Color;
import java.io.FileOutputStream;
import java.io.IOException;

import com.lowagie.text.Cell;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Element;
import com.lowagie.text.PageSize;
import com.lowagie.text.Table;
import com.lowagie.text.pdf.PdfWriter;

public class TestIText27 {

  public static void main(String[] args) {

    Document document = new Document(PageSize.A4);
    try {
      PdfWriter.getInstance(document, new FileOutputStream("c:/test.pdf"));
      document.open();

      Table tableau = new Table(2,2);
      tableau.setAutoFillEmptyCells(true);
      tableau.setPadding(2);
      
      Cell cell = new Cell("1.1");
      cell.setHorizontalAlignment(Element.ALIGN_CENTER);
      cell.setBackgroundColor(Color.YELLOW);
      tableau.addCell(cell);
      
      tableau.addCell("1.2");
      tableau.addCell("2.1");
      tableau.addCell("2.2");
      
      document.add(tableau);

    } catch (DocumentException de) {
      de.printStackTrace();
    } catch (IOException ioe) {
      ioe.printStackTrace();
    }

    document.close();
  }
}

Il est possible de définir une en-tête pour les colonnes en ajoutant au début des cellules un appel à la méthode setHeader() avec le paramètre true. Une fois toutes les en-têtes définies, il faut invoquer la méthode endHeaders() de la classe Table.

Exemple :
package fr.jmdoudoux.dej.itext;

import java.io.FileOutputStream;
import java.io.IOException;

import com.lowagie.text.Cell;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Element;
import com.lowagie.text.PageSize;
import com.lowagie.text.Table;
import com.lowagie.text.pdf.PdfWriter;

public class TestIText28 {

  public static void main(String[] args) {

    Document document = new Document(PageSize.A4);
    try {
      PdfWriter.getInstance(document, new FileOutputStream("c:/test.pdf"));
      document.open();

      Table tableau = new Table(2, 2);
      tableau.setAutoFillEmptyCells(true);
      tableau.setPadding(2);

      Cell cell = new Cell("colonne 1");
      cell.setHeader(true);
      cell.setHorizontalAlignment(Element.ALIGN_CENTER);
      tableau.addCell(cell);

      cell = new Cell("colonne 2");
      cell.setHeader(true);
      cell.setHorizontalAlignment(Element.ALIGN_CENTER);
      tableau.addCell(cell);
      tableau.endHeaders();

      cell = new Cell("1.1");
      cell.setHorizontalAlignment(Element.ALIGN_CENTER);
      tableau.addCell(cell);

      tableau.addCell("1.2");
      tableau.addCell("2.1");
      tableau.addCell("2.2");

      document.add(tableau);

    } catch (DocumentException de) {
      de.printStackTrace();
    } catch (IOException ioe) {
      ioe.printStackTrace();
    }

    document.close();
  }
}

 

108.2.5. Des fonctionnalités avancées

iText propose de nombreuses fonctionnalités avancées pour générer un document.

 

108.2.5.1. Insérer une image

iText propose le support de plusieurs formats d'images : JPEG, GIF, PNG, BMP, TIFF, WMF et les objets de type java.awt.Image.

La classe Image est une classe abstraite dont hérite chaque classe qui encapsule un type d'images supporté par iText.

La méthode getInstance() de la classe Image permet d'obtenir une instance d'une image. De nombreuses surcharges sont proposées pour fournir par exemple un chemin sur le système de fichiers ou une url.

Exemple :
package fr.jmdoudoux.dej.itext;

import java.io.FileOutputStream;
import java.io.IOException;

import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Image;
import com.lowagie.text.PageSize;
import com.lowagie.text.pdf.PdfWriter;

public class TestIText29 {

  public static void main(String[] args) {

    Document document = new Document(PageSize.A4);
    try {
      PdfWriter.getInstance(document, new FileOutputStream("c:/test.pdf"));
      document.open();

      Image image = Image.getInstance("c:/monimage.jpg");
      document.add(image);

    } catch (DocumentException de) {
      de.printStackTrace();
    } catch (IOException ioe) {
      ioe.printStackTrace();
    }

    document.close();
  }
}

La méthode setAlignment() peut être utilisée pour préciser l'alignement de l'image en passant en paramètre une des constantes : LEFT, MIDDLE ou RIGHT

La classe Image propose plusieurs méthodes pour permettre de redimentionner l'image : scaleAbsolute(), scaleAbsoluteWidth(), scaleAbsoluteHeight(), scalePercent() et scaleToFit().

Les méthodes setRotation() et setRotationDegrees() permettent de faire une rotation de l'image.

 

 


[ Précédent ] [ Sommaire ] [ Suivant ] [Télécharger ]      [Accueil ]

78 commentaires Donner une note à l´article (5)

 

Copyright (C) 1999-2022 Jean-Michel DOUDOUX. Vous pouvez copier, redistribuer et/ou modifier ce document selon les termes de la Licence de Documentation Libre GNU, Version 1.1 ou toute autre version ultérieure publiée par la Free Software Foundation; les Sections Invariantes étant constitués du chapitre Préambule, aucun Texte de Première de Couverture, et aucun Texte de Quatrième de Couverture. Une copie de la licence est incluse dans la section GNU FreeDocumentation Licence. La version la plus récente de cette licence est disponible à l'adresse : GNU Free Documentation Licence.