Introduction à PHPExcel

Ernaelsten Gérard

Nous allons voir dans cet article une bibliothèque orientée objet (PHP 5), la génération de feuilles de calcul sous différents formats d'exportation et/ou d'enregistrement.
Cette bibliothèque étant assez imposante, et mon apprentissage de celle-ci ne faisant que de commencer, nous aurons un article construit au fil du temps.

Commentez

- Titre : Introduction à PHPExcel

- Auteur : Ernaelsten Gérard

- Parution : 5 février 2009

- Licence : Ce document est issu de http://www.developpez.com et reste la propriété exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise à l'obtention préalable de l'autorisation de l'auteur.

Sommaire

- Avant-propos

- PHPExcel

- Téléchargement

- Spécificités

- Testé sur…

- Premier fichier

- MaitrePylos en A1

- Dans un autre format

- Excel5

- PDF

- HTML

- CSV

- Excel 2007 - compatible 2003

- Afficher le tableur

- Excel 2007 sur le navigateur

- Excel 5

- PDF

- CSV

- HTML

- Pour la suite… créons nos outils

- Étendre PHPExcel

- Petit exemple

- Les formules

- Multifeuilles (sheets)

- Mise en forme

- La classe de style « Font »

- MaitrePylos en vert…

- applyFromArray

- PHPExcel_Style

- applyFromArray de PHPExcel_Style

- Format de cellule

- Alignement de la cellule

- Les autres styles de PHPExcel_Style_Alignment

- Les bordures

- Toutes les bordures

- Le fond de la cellule

- Les images

- Style par défaut

- Dupliquer le style

- Les formats de cellules

- PHPExcel_Cell_DataType

- Vite dit

- Fusion de cellules

- Largeur de colonne

- Hauteur de ligne

- Taille de la page

- Orientation de la page

- Freeze Pane

- Ça existe aussi

- Travailler avec l'existant

- Lire un fichier Excel

- Écrire dans un fichier existant !

- Connaître son fichier

- Le nom des sheets

- L'index des sheets

- Fusionner plusieurs fichiers Excel

- Utiliser plusieurs fois le même sheet

- Extraire des images

- Conclusion

- Merci

- Liens

Avant-propos

Lors de la rédaction de l'article sur Spreadsheet_Excel_Writer en PHP, Yogui, m'avait demandé si j'allais faire un parallèle avec la classe PHPExcel. Ne connaissant pas cette classe, je n'avais pas répondu positivement à cette demande.
Et je ne vais toujours pas le faire ici, parce que nous ne sommes pas à faire un parallèle, mais bien à découvrir un outil puissant qui va nous rendre de grands services dans la génération de nos tableurs.

PHPExcel

PHPExcel va nous proposer la génération des formats suivants :

- Excel 2007 ;

- Excel 2007 - compatible Excel 2003 ;

- Excel 5 - via la librairie Spreadsheet_Excel_Writer ;

- PDF - via la librairie FPDF ;

- CSV ;

- HTML.

En plus, PHPExcel va affiner nos tableurs avec des éléments tels que :

- formater les cellules ;

- ajouter des formules ;

- ajouter des images ;

- protéger les données, les cellules ;

- …

Téléchargement

Pour commencer, nous allons télécharger la librairie PHPExcel, ce fichier comporte la librairie dans le répertoire ./Classes, nous avons également l'API dans le répertoire ./Documentation, ainsi qu'un répertoire ./Tests avec un certain nombre d'exemples.
Il faut extraire le répertoire ./Classes et le déposer dans le répertoire de votre Web serveur.

Spécificités

PHPExcel ne fonctionne qu'avec PHP 5 et réclame des extensions spécifiques pour fonctionner correctement. Ces extensions sont :

- Zip ;

- GD ;

- XML.

Vous pouvez vérifier que vous avez ces extensions avec la fonction.

phpinfo();

Testé sur…

J'ai testé tous les exemples sur différents OS et tableurs :

- O0o 2.4 / Debian ;

- O0o 3.0 / Debian ;

- Excel 2007 /VirtualBox/Windows XP ;

- Excel 2007 /Windows Serveur 2003.

On peut retrouver quelques différences entre les versions de tableurs, notamment au niveau des couleurs de remplissage des cellules, ou encore dans les bordures, Ooo 2.4 ne reconnaît pas les formats type Dash Dot (BORDER_DASHDOT).
Sur le serveur 2003 en production avec PHP 5.2.6, j'ai été confronté à un souci de dll (« php_zip.dll »), cela tronque le fichier.

Sur le forum de PHPExcel, il est conseillé de télécharger une autre version de php_zip.dll, notamment sur http://snaps.php.net

Premier fichier

Nous allons voir comment créer notre premier fichier au format Excel 2007.

MaitrePylos en A1

include 'PHPExcel.php';
include
'PHPExcel/Writer/Excel2007.php';

$workbook = new PHPExcel;

$sheet =
$workbook->getActiveSheet();
$sheet->setCellValue('A1','MaitrePylos');

$writer = new PHPExcel_Writer_Excel2007($workbook);

$records = './fichier.xlsx';

$writer->save($records);

Ce code enregistre un fichier nommé 'fichier.xlsx' sur le disque dur du serveur, il n'apparaîtra pas sur le navigateur.

Il faut d'abord inclure les fichiers nécessaires à la génération du tableur

include 'PHPExcel.php';
include 'PHPExcel/Writer/Excel2007.php';

Ensuite nous instancions notre objet PHPExcel

$workbook = new PHPExcel;

Nous activons la feuille sur laquelle nous allons travailler (la feuille par défaut), grâce à la méthode ->getActiveSheet().

$sheet = $workbook->getActiveSheet();

Lors de l'instanciation de notre objet PHPExcel, le constructeur a également instancié diverses classes, notamment la classe PHPExcel_Worksheet et la méthode getActiveSheet nous donne donc la main sur cet objet.

Nous remplissons notre première cellule avec la méthode ->setCellValue()

$sheet->setCellValue('A1','MaitrePylos');

Vous remarquerez que, pour désigner la cellule, la méthode ->setCellValue() accepte son nom de tableau à double entrée.

Il existe une autre méthode pour désigner la cellule que l'on veut modifier.

$sheet->setCellValueByColumnAndRow(1, 4, 'MaitrePylos');

Cette méthode prend trois paramètres :

- la ligne ;

- la colonne ;

- la valeur.

Notez que dans le cas de cette méthode, la ligne commence à partir de zéro(0), et la colonne commence à un (1).

Enfin pour créer le fichier, nous devons instancier un objet writer, spécifique au type de tableau que nous voulons générer.

$writer = new PHPExcel_Writer_Excel2007($workbook);

Nous donnons un nom à notre fichier, et l'enregistrons

$records = './fichier.xlsx';
$writer->save($records);

Vous prêterez une attention toute particulière à l'extension du fichier, en l'occurrence ici « xlsx ».

Dans un autre format

Pour enregistrer le fichier dans un autre format, il faut juste trois modifications au script précédent.

Excel5

include 'PHPExcel/Writer/Excel5.php';
...
$writer = new PHPExcel_Writer_Excel5();
...
$records = './fichier.xls';

PDF

include 'PHPExcel/Writer/PDF.php';
...
$writer = new PHPExcel_Writer_PDF();
$writer->setSheetIndex(0);//Une seule feuille possible
...
$records = './fichier.pdf';

Dans la génération des fichiers de types PDF, HTML, il n'est possible que de travailler sur une seule feuille, et nous devons lui indiquer laquelle, via la méthode ->setSheetIndex().

HTML

include 'PHPExcel_Writer/HTML.php';
...
$writer = new PHPExcel_Writer_HTML();
$writer->setSheetIndex(0);//Une seule feuille possible

...
$records = './fichier.html';

CSV

include 'PHPExcel/Writer/CSV.php';
...
$writer = new PHPExcel_Writer_CSV();
$writer->setDelimiter(",");//l'opérateur de séparation est la virgule
$writer->setSheetIndex(0);//Une seule feuille possible

...
$records = './fichier.csv';

Dans le cadre d'un fichier de type CSV, il faut en plus noter le séparateur, ce qui est le rôle de la méthode ->setDelimiter().

Excel 2007 - compatible 2003

Pour assurer une compatibilité avec Excel 2003, il suffit de mettre la méthode ->setOffice2003Compatibility(), à true.

$writer = new PHPExcel_Writer_Excel2007($workbook);
$writer->setOffice2003Compatibility(true);

$records = './fichier.xlsx';

$writer->save($records);

Afficher le tableur

Il est également possible de générer un tableur et de l'afficher plutôt que de l'enregistrer.
Pour ce faire, il faut passer les entêtes à la sortie standard.

Excel 2007 sur le navigateur

include 'PHPExcel.php';
include 'PHPExcel/Writer/Excel2007.php';

$workbook = new PHPExcel;

$sheet = $workbook->getActiveSheet();
$sheet->setCellValue('A1','MaitrePylos');

$writer = new PHPExcel_Writer_Excel2007($workbook);

header('Content-type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition:inline;filename=Fichier.xlsx ');
$writer->save('php://output');

Ici, le fichier va demander à être ouvert via votre logiciel de tableur.
Les autres possibilités sont…

Excel 5

header('Content-type: application/vnd.ms-excel');

PDF

header('Content-type: application/pdf');

CSV

header('Content-type: text/csv');

HTML

header('Content-type: text/html');

Pour la suite… créons nos outils

Pour la suite de cet article, je me baserai sur l'affichage du tableur.
Afin de ne pas réécrire l'ensemble des codes, je vais étendre la classe PHPExcel, et commencer à créer des outils personnalisés pour la génération des fichiers.

Étendre PHPExcel

Soit la nouvelle classe suivante :

/**
* Classe étendue de PHPExcel.
* Cette classe permet la génération dynamique
* de fichier tableur suivant différent format.
*
* @copyright 2008 MaitrePylos Technologies (Formatux.be)
* @author   Ernaelsten Gerard
* @license  GPL
* @version  Release: 0.1
*/

require 'PHPExcel.php';
class MaitrePylosExcel extends PHPExcel {

public function __construct() {
parent::__construct();
}

/**
* Méthode englobant une fonction switch pour le choix du format de tableur.
* @method affiche
* @param String $format
* @param String $nomFichier
* @example $workbook->affiche('Excel2007','MonFichier');
*/
public function affiche($format = 'Excel5',$nomFichier = 'Tableur'){

switch($format){
case 'Excel2007' :
include 'PHPExcel/Writer/Excel2007.php';
$writer = new PHPExcel_Writer_Excel2007($this);
$ext = 'xlsx';
$header = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
//supprime le précalcul
$writer->setPreCalculateFormulas(false);
break;
case 'Excel2003' :
include 'PHPExcel/Writer/Excel2007.php';
$writer = new PHPExcel_Writer_Excel2007($this);
$writer->setOffice2003Compatibility(true);
$ext = 'xlsx';
$header = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
//supprime le précalcul
$writer->setPreCalculateFormulas(false);
break;
case 'Excel5' :
include 'PHPExcel/Writer/Excel5.php';
$writer = new PHPExcel_Writer_Excel5($this);
$ext = 'xls';
$header = 'application/vnd.ms-excel';
break;
case 'CSV' :
include 'PHPExcel/Writer/CSV.php';
$writer = new PHPExcel_Writer_CSV($this);
$writer->setDelimiter(",");//l'opérateur de séparation est la virgule
$writer->setSheetIndex(0);//Une seule feuille possible
$ext = 'csv';
$header = 'text/csv';
break;
case 'PDF' :
include 'PHPExcel/Writer/PDF.php';
$writer = new PHPExcel_Writer_PDF($this);
$writer->setSheetIndex(0);//Une seule feuille possible
$ext = 'pdf';
$header = 'application/pdf';
break;
case 'HTML' :
include 'PHPExcel/Writer/HTML.php';
$writer = new PHPExcel_Writer_HTML($this);
$writer->setSheetIndex(0);//Une seule feuille possible
$ext = 'html';
$header = 'text/html';
break;

}

header('Content-type:'.$header);
header('Content-Disposition:inline;filename='.$nomFichier.'.'.$ext);
$writer->save('php://output');
}

/**
* Méthode englobant une fonction switch pour le choix du format de tableur.
* @method enregistre
* @param String $format
* @param String $nomFichier
* @example $workbook->enregistre('Excel2007','MonFichier');
*/
public function enregistre($format = 'Excel5',$nomFichier = 'Tableur'){

switch($format){
case 'Excel2007' :
include 'PHPExcel/Writer/Excel2007.php';
$writer = new PHPExcel_Writer_Excel2007($this);
$ext = 'xlsx';
//supprime le précalcul
$writer->setPreCalculateFormulas(false);
break;
case 'Excel2003' :
include 'PHPExcel/Writer/Excel2007.php';
$writer = new PHPExcel_Writer_Excel2007($this);
$writer->setOffice2003Compatibility(true);
$ext = 'xlsx';
//supprime le précalcul
$writer->setPreCalculateFormulas(false);
break;
case 'Excel5' :
include 'PHPExcel/Writer/Excel5.php';
$writer = new PHPExcel_Writer_Excel5($this);
$ext = 'xls';
break;
case 'CSV' :
include 'PHPExcel/Writer/CSV.php';
$writer = new PHPExcel_Writer_CSV($this);
$writer->setDelimiter(",");//l'opérateur de séparation est la virgule
$writer->setSheetIndex(0);//Une seule feuille possible
$ext = 'csv';
break;
case 'PDF' :
include 'PHPExcel/Writer/PDF.php';
$writer = new PHPExcel_Writer_PDF($this);
$writer->setSheetIndex(0);//Une seule feuille possible
$ext = 'pdf';
break;
case 'HTML' :
include 'PHPExcel/Writer/HTML.php';
$writer = new PHPExcel_Writer_HTML($this);
$writer->setSheetIndex(0);//Une seule feuille possible
$ext = 'html';
break;

}

$writer->save($nomFichier.'.'.$ext);

}
}

Petit exemple

Nous utiliserons cette classe de cette façon :

include 'MaitrePylosExcel.php';

$workbook = new MaitrePylosExcel();

$sheet = $workbook->getActiveSheet();
$sheet->setCellValue('A1','MaitrePylos');

$workbook->affiche('Excel2007','MonPremierFichier');

Vous prêterez attention au fait que dans l'article j'utilise la variable $sheet, qui sera le remplacement de $workbook->getActiveSheet(), dans les exemples fournis par l'application, ils utiliseront plus l'écriture $workbook->getActiveSheet()->getFont(), or je privilégie $sheet->getFont(), gardez bien cela à l'esprit.

Les formules

Pour introduire des formules dans le fichier, il suffit de passer en argument ladite formule.

include 'MaitrePylosExcel.php';

$workbook = new MaitrePylosExcel();

$sheet = $workbook->getActiveSheet();
$sheet->setCellValue('A1',4);
$sheet->setCellValue('A2',5);
$sheet->setCellValue('A3','=SUM(A1:A2)');

$workbook->affiche('Excel2007','MaPremiereFormule');

Multifeuilles (sheets)

Ici nous allons voir comment faire pour avoir plusieurs feuilles dans le tableur.

Le fait d'avoir plusieurs feuilles ne vous permettra pas de générer le tableur dans les formats suivants :

- PDF ;

- CSV ;

- HTML.

Ces formats ne permettant que la génération d'une seule feuille.

Lors de la création de votre document, une feuille est automatiquement créée, et nous en prenons possession avec la méthode getActiveSheet().

include 'MaitrePylosExcel.php';

$workbook = new MaitrePylosExcel();

$sheet = $workbook->getActiveSheet();

$workbook->affiche('Excel2007','MaPremiereFormule');

Pour donner un nom à cette feuille, on utilise la méthode setTitle()

$sheet->setTitle('feuille 1');

Pour créer de nouvelles feuilles, nous utiliserons la méthode createSheet() de la classe PHPExcel, qui elle-même instancie la classe PHPExcel_WoorkSheet.

/*********************************************************
*
* Création de la deuxième feuille
*******************************************************/
//création de la nouvelle feuille
$sheet2 = $workbook->createSheet();
//nom de la feuille
$sheet2->setTitle('feuille 2');

/*********************************************************
*
* Création de la troisième feuille
*******************************************************/
$sheet3 = $workbook->createSheet();
$sheet3->setTitle('feuille 3');

/*********************************************************
*
* Création de la quatrième feuille
*******************************************************/
$sheet4 = $workbook->createSheet();
$sheet4->setTitle('feuille 4');

Mise en forme

PHPExcel nous offre huit classes pour mettre en forme nos cellules :

- PHPExcel_Style ;

- PHPExcel_Style_Fill ;

- PHPExcel_Style_Font ;

- PHPExcel_Style_Border ;

- PHPExcel_Style_Borders ;

- PHPExcel_Style_Alignment ;

- PHPExcel_Style_NumberFormat ;

- PHPExcel_Style_Protection.

Nous n'allons pas voir l'ensemble des classes, mais nous verrons les 2-3 approches qu'il est possible de faire, ensuite je vous renvoie vers la documentation officielle, pour explorer plus en avant l'ensemble des classes.

La classe de style « Font »

Dans la classe PHPExcel_Style_Font, les méthodes importantes sont les suivantes :

- setName() ;

- setBold() ;

- setItalic() ;

- setUnderline() ;

- setStriketrough() ;

- getColor() ;

- setSize() ;

- setSuperScript() ;

- setSubScript().

La plupart de celles-ci sont assez explicites.

MaitrePylos en vert…

Nous allons mettre en forme une cellule en fonction des critères suivants :

- en gras ;

- de taille 12 ;

- de police 'Arial' ;

- de couleur verte.

Pour ce faire il suffit d'écrire le code suivant :

$workbook = new MaitrePylosExcel();

$sheet = $workbook->getActiveSheet();

$styleA1 = $sheet->getStyle('A1');
$styleFont = $styleA1->getFont();
$styleFont->setBold(true);
$styleFont->setSize(12);
$styleFont->setName('Arial');
$styleFont->getColor()->setARGB(PHPExcel_Style_Color::COLOR_GREEN);
$sheet->setCellValue('A1','MaitrePylos');

$workbook->affiche('Excel2007','MonPremierFichier');

Nous allons passer en revue ce code bien comprendre ce qu'il se passe.

$styleA1 = $sheet->getStyle('A1');

getStyle() est une méthode de la classe PHPExcel_Worksheet qui instancie la classe PHPExcel_Style (que nous verrons plus tard), on lui passe en paramètre la cellule visée.

$styleFont = $styleA1->getFont();

getFont() est donc une méthode de la classe PHPExcel_Style, qui instancie la classe PHPExcel_Style_Font.
À partir de cette instanciation, nous pouvons utiliser les méthodes de PHPExcel_Style_Font.

$styleFont->setBold(true);//passage à true de façon à activer la graisse.
$styleFont->setSize(12);//taille de la police
$styleFont->setName('Arial');//nom de la police
$styleFont->getColor()->setARGB(PHPExcel_Style_Color::COLOR_GREEN);

Pour la couleur, c'est un peu plus compliqué, il faut repasser par une nouvelle classe PHPExcel_Style_Color
Celle-ci définit un certain nombre de constantes que voici :

Constante

Valeur

COLOR_BLACK

'FF000000'

COLOR_WHITE

'FFFFFFFF'

COLOR_RED

'FFFF0000'

COLOR_DARKRED

'FF800000'

COLOR_BLUE

'FF0000FF'

COLOR_DARKBLUE

'FF000080'

COLOR_GREEN

'FF00FF00'

COLOR_DARKGREEN

'FF008000'

COLOR_YELLOW

'FFFFFF00'

COLOR_DARKYELLOW

'FF808000'

Ainsi que deux méthodes : setARGB(), que vous connaissez déjà (voir exemple ci-dessus) et qui prend en paramètre une des constantes.
setRGB(), qui, elle prend en paramètre le code HTML de la couleur :

$styleFont->getColor()->setRGB('FF00FF00');

applyFromArray

Il y a moyen d'alléger ce code. En effet, la classe PHPExcel_Style_Font propose une méthode applyFromArray() qui prend un tableau en paramètre afin de ne pas utiliser les setter et getter de la classe et de rendre le code plus lisible.
Les mots clés de ce tableau sont :

- name ;

- bold ;

- italic ;

- underline ;

- strike ;

- color ;

- size ;

- superScript ;

- subScript.

Les noms sont fort proches des méthodes, et pour cause, elles utiliseront celles-ci, pour définir notre style de cellule.
Notre nouveau code sera donc :

$styleA1 = $sheet->getStyle('A1');
$styleFont = $styleA1->getFont()
->applyFromArray(array(
'bold'=>true,
'size'=>12,
'name'=>Arial,
'color'=>array(
'rgb'=>'FF00FF00')));

Ce simple tableau remplace tous les appels aux méthodes de PHPExcel_Style_Font, puisqu'il le fait lui-même.
Vous remarquerez que color demande un nouveau tableau, parce que la classe PHPExcel_Style_Color a également une méthode applyFromArray, avec soit rgb ou argb.

PHPExcel_Style

PHPExcel_Style est la classe qui nous permet de travailler avec les autres classes de 'style'.
Quand nous appelons la méthode getStyle(), en fait nous instancions la classe PHPExcel_Style, celle-ci dispose de méthodes nous permettant d'instancier les autres classes de styles, les méthodes sont :

- getFill() ;

- getFont() ;

- getBorders() ;

- getAlignment() ;

- getNumberFormat() ;

- getProtection().

Chaque méthode instancie la classe par rapport à son nom :
- getFont() instancie PHPExcel_Style_Font ;
- getAlignment() instancie PHPExcel_Style_Alignment.
…

applyFromArray de PHPExcel_Style

PHPExcel_Style dispose également d'une méthode applyFromArray contenant le tableau suivant :

- fill ;

- font ;

- borders ;

- alignment ;

- numberformat ;

- protection.

Notre code deviendra dès lors :

$styleA1 = $sheet->getStyle('A1');
$styleA1->applyFromArray(array(
'font'=>array(
'bold'=>true,
'size'=>12,
'name'=>Arial,
'color'=>array(
'rgb'=>'FF00FF00'))
));

Format de cellule

On veut parfois obtenir un format d'affichage spécifique pour une cellule, par exemple les dates, on pourrait vouloir le format « yy-mm-dd » ou encore « dd/mm/yyyy ».
Pour cela la classe PHPExcel_Style_NumberFormat vient à notre secours, et ce, de la même façon que vu au chapitre 4, traitant de la mise en forme.

$sheet->getStyle('B43')->getNumberFormat()->applyFromArray(
array(
'code' => PHPExcel_Style_NumberFormat::FORMAT_DATE_DDMMYYYY
)
);
$sheet->setCellValue('B43', '=TODAY()');

De nouveau de façon très simple, la librairie PHPExcel, nous permet de définir un format précis, grâce à un certain nombre de constantes prédéfinies.

Constante

Valeur

FORMAT_GENERAL

'General'

FORMAT_NUMBER

'0'

FORMAT_NUMBER_00

'0.00'

FORMAT_NUMBER_COMMA_SEPARATED1

'#,##0.00'

FORMAT_NUMBER_COMMA_SEPARATED2

'#,##0.00_-'

FORMAT_PERCENTAGE

'0%'

FORMAT_PERCENTAGE_00

'0.00%'

FORMAT_DATE_YYYYMMDD

'yy-mm-dd'

FORMAT_DATE_DDMMYYYY

'dd/mm/yy'

FORMAT_DATE_DMYSLASH

'd/m/y'

FORMAT_DATE_DMYMINUS

'd-m-y'

FORMAT_DATE_DMMINUS

'd-m'

FORMAT_DATE_MYMINUS

'm-y'

FORMAT_DATE_DATETIME

'd/m/y h:mm'

FORMAT_DATE_TIME1

'h:mm AM/PM'

FORMAT_DATE_TIME2

'h:mm:ss AM/PM'

FORMAT_DATE_TIME3

'h:mm'

FORMAT_DATE_TIME4

'h:mm:ss'

FORMAT_DATE_TIME5

'mm:ss'

FORMAT_DATE_TIME6

'h:mm:ss'

FORMAT_DATE_TIME7

'i:s.S'

FORMAT_DATE_TIME8

'h:mm:ss;@'

FORMAT_DATE_YYYYMMDDSLASH

'yy/mm/dd;@'

FORMAT_CURRENCY_USD_SIMPLE

'« $ »#,##0.00_-'

FORMAT_CURRENCY_USD

'$#,##0_-'

FORMAT_CURRENCY_EUR_SIMPLE

'[$EUR ]#,##0.00_-'

Il peut paraître fastidieux de retenir toutes ces constantes, ou de devoir aller dans l'API pour retrouver le format qui nous convient.
Dans ce cas, il suffit de passer un string en paramètre plutôt qu'une constante.

$sheet->getStyle('B43')->getNumberFormat()->applyFromArray(
array(
'code' => 'dd/mm/yyyy'
)
);

Alignement de la cellule

Pour aligner nos cellules, nous avons deux méthodes de la classe PHPExcel_Style_Alignment :
setHorizontal() - prenant en paramètre :

Constantes

Valeur

HORIZONTAL_GENERAL

'general'

HORIZONTAL_LEFT

'left'

HORIZONTAL_RIGHT

'right'

HORIZONTAL_CENTER

'center'

HORIZONTAL_JUSTIFY

'justify'

setVertical() - prenant en paramètre :

Constante

Valeur

VERTICAL_BOTTOM

'bottom'

VERTICAL_TOP

'top'

VERTICAL_CENTER

'center'

VERTICAL_JUSTIFY

'justify'

Voici un exemple d'utilisation

$sheet->duplicateStyleArray(array(
'alignment'=>array(
'horizontal'=>PHPExcel_Style_Alignment::HORIZONTAL_CENTER), 'A21:F37');

Les autres styles de PHPExcel_Style_Alignment

Pour la rotation du texte, il suffit de passer l'angle voulu dans la méthode rotation().

$sheet->duplicateStyleArray(array(
'alignment'=>array(
'rotation'=>90), 'A21:F37');

Si vous utilisez une version inférieure à Excel 2007, seules les valeurs « 0,90,180,270 » seront acceptées.

La passage automatique à la ligne : 'Wrap'

$sheet->duplicateStyleArray(array(
'alignment'=>array(
'wrap'=>true), 'A21:F37');

Ajuster les cellules : 'shrinkToFit'

$sheet->duplicateStyleArray(array(
'alignment'=>array(
'shrinkToFit'=>true), 'A21:F37');

Tout en même temps :

$sheet->duplicateStyleArray(array(
'alignment'=>array(
'shrinkToFit'=>true,
'wrap'=>true,
'rotation'=>90,
'horizontal'=>PHPExcel_Style_Alignment::HORIZONTAL_CENTER)
, 'A21:F37');

Les bordures

Les bordures possèdent deux classes PHPExcel_Style_Border et PHPExcel_Style_Borders.
PHPExcel_Style_Borders définit notamment quatre méthodes :

- getLeft() ;

- getRight() ;

- getTop() ;

- getBottom().

Ces méthodes instancient un objet de la classe PHPExcel_Style_Border, qui permet de définir le style de bordure (via des constantes définies), et le style de couleur de la bordure via les méthodes de la classe PHPExcel_Style_Color dont j'ai déjà parlé plus haut.
Voici un petit exemple :

$styleA11 = $sheet->getStyle('A11');
$styleA11->applyFromArray(array(
'borders'=>array(
'top'=>array(
'style'=>PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT),
'bottom'=>array(
'style'=>PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT,
'color'=>array(
'rgb' => '808080')))));

Les constantes définies sont les suivantes :

Constante

Valeur

BORDER_NONE

'none'

BORDER_DASHDOT

'dashDot'

BORDER_DASHDOTDOT

'dashDotDot'

BORDER_DASHED

'dashed'

BORDER_DOTTED

'dotted'

BORDER_DOUBLE

'double'

BORDER_HAIR

'hair'

BORDER_MEDIUM

'medium'

BORDER_MEDIUMDASHDOT

'mediumDashDot'

BORDER_MEDIUMDASHDOTDOT

'mediumDashDotDot'

BORDER_MEDIUMDASHED

'mediumDashed'

BORDER_SLANTDASHDOT

'slantDashDot'

BORDER_THICK

'thick'

BORDER_THIN

'thin'

Toutes les bordures

Définir chaque ligne peut être vite fastidieux, il est possible de définir les quatre côtés de la cellule en une seule array(), grâce au mot clé 'allborders'.

$sheet->getStyle('B2')->getBorders()->applyFromArray(
array(
'allborders' => array(
'style' => PHPExcel_Style_Border::BORDER_DASHDOT,
'color' => array(
'rgb' => '808080'
)
)
)
);

Le fond de la cellule

Nous pourrions avoir besoin de mettre une cellule en couleur, pour ce faire nous utiliserons la classe PHPExcel_Style_Fill.
Cette classe nous permet de définir le style de fond, si elle doit être solide,linéaire, etc.
En fonction du style choisi, nous pourrons définir une rotation, un dégradé ou une couleur de fond.

Les dégradés ne fonctionnent que sur Excel 2007.

Comme pour les autres méthodes, une série de constantes sont définies, pour le style de fond de la cellule.

Constante

Valeur

FILL_NONE

'none'

FILL_SOLID

'solid'

FILL_GRADIENT_LINEAR

'linear'

FILL_GRADIENT_PATH

'path'

FILL_PATTERN_DARKDOWN

'darkDown'

FILL_PATTERN_DARKGRAY

'darkGray'

FILL_PATTERN_DARKGRID

'darkGrid'

FILL_PATTERN_DARKHORIZONTAL

'darkHorizontal'

FILL_PATTERN_DARKTRELLIS

'darkTrellis'

FILL_PATTERN_DARKUP

'darkUp'

FILL_PATTERN_DARKVERTICAL

'darkVertical'

FILL_PATTERN_GRAY0625

'gray0625'

FILL_PATTERN_GRAY125

'gray125'

FILL_PATTERN_LIGHTDOWN

'lightDown'

FILL_PATTERN_LIGHTGRAY

'lightGray'

FILL_PATTERN_LIGHTGRID

'lightGrid'

FILL_PATTERN_LIGHTHORIZONTAL

'lightHorizontal'

FILL_PATTERN_LIGHTTRELLIS

'lightTrellis'

FILL_PATTERN_LIGHTUP

'lightUp'

FILL_PATTERN_LIGHTVERTICAL

'lightVertical'

FILL_PATTERN_MEDIUMGRAY

'mediumGray'

Pour la couleur, c'est toujours la classe PHPExcel_Style_Color, qui fournit les méthodes.
Exemple :

$sheet->getStyle('A9')->applyFromArray(array(

'fill'=>array(
'type'=>PHPExcel_Style_Fill::FILL_SOLID,
'color'=>array(
'argb'=>'FFCC99'))));

Voici un exemple avec un dégradé :

$sheet->getStyle('B2')->getFill()->applyFromArray(
array(
'type'    => PHPExcel_Style_Fill::FILL_GRADIENT_LINEAR,
'rotation'  => 0,
'startcolor' => array(
'rgb' => '000000'
),
'endcolor'  => array(
'argb' => 'FFFFFFFF'
)
)
);

Les images

Il est également possible d'insérer des images dans notre document.
La classe est PHPExcel_Worksheet_Drawing.

Je n'ai à l'heure actuelle encore jamais testé cette classe.

Le code est sorti tout droit des exemples fournis avec la librairie.

$objDrawing = new PHPExcel_Worksheet_Drawing();
$objDrawing->setName('PHPExcel logo');
$objDrawing->setDescription('PHPExcel logo');
$objDrawing->setPath('./images/phpexcel_logo.gif');
$objDrawing->setHeight(36);
$objDrawing->setCoordinates('D24');
$objDrawing->setOffsetX(-10);
$objDrawing->setWorksheet($sheet);

Style par défaut

La classe PHPExcel_Worksheet nous offre une méthode qui permet d'appliquer un style à tout le tableur par défaut.
Ce style défini par défaut pourra soit être complété, soit remplacé en fonction des besoins.

include 'MaitrePylosExcel.php';

$workbook = new MaitrePylosExcel();

$sheet = $workbook->getActiveSheet();

$sheet->getDefaultStyle()
->applyFromArray(array(
'font'=>array(
'name'   => 'Arial',
'size'   => 12,
'bold'   => true),
'alignment'=>array(
'horizontal'=>PHPExcel_Style_Alignment::HORIZONTAL_CENTER),
'borders' => array(
'allborders'=>array(
'style' => PHPExcel_Style_Border::BORDER_DASHDOT))
)
);

$workbook->affiche('Excel2007','MonPremierFichier');

Par défaut donc mon tableur sera fixé comme suit :
la police Arial sera de taille 12 en gras ;
le contenu des cellules sera centré horizontalement ;
les cellules seront encadrées par des bordures.

Dupliquer le style

Dans la classe PHPExcel_Worksheet, nous avons une méthode qui nous permet de dupliquer le style appliqué à une cellule.

$sheet->duplicateStyle($styleA1,'E5:F6');

Nous appliquons le style de la cellule A1 aux cellules E5-E6-F5-F6, et voici un petit code pour vérifier nos dires.

include 'MaitrePylosExcel.php';

$workbook = new MaitrePylosExcel();

$sheet = $workbook->getActiveSheet();

$styleA1 = $sheet->getStyle('A1');
$styleA1->applyFromArray(array(
'font'=>array(
'bold'=>true,
'size'=>12,
'name'=>Arial,
'color'=>array(
'rgb'=>'FF00FF00'))
));
$sheet->duplicateStyle($styleA1,'E5:F6');

$sheet->setCellValue('A1','MaitrePylos');

$sheet->setCellValue('E5','MaitrePylos');
$sheet->setCellValue('E6','MaitrePylos');
$sheet->setCellValue('F5','MaitrePylos');
$sheet->setCellValue('F6','MaitrePylos');

$workbook->affiche('Excel2007','MonPremierFichier');

Vous pouvez également propager directement un style vers un ensemble de cellules via la méthode duplicateStyleArray(), dans le code suivant, nous allons appliquer un style aux cellules allant de A3 jusqu'à E3.

$sheet->duplicateStyleArray(
array(
'font'  => array(
'bold'   => true
),
'alignment' => array(
'horizontal' => PHPExcel_Style_Alignment::HORIZONTAL_RIGHT,
),
'borders' => array(
'top'   => array(
'style' => PHPExcel_Style_Border::BORDER_THIN
)
),
'fill' => array(
'type'    => PHPExcel_Style_Fill::FILL_GRADIENT_LINEAR,
'rotation'  => 90,
'startcolor' => array(
'argb' => 'FFA0A0A0'
),
'endcolor'  => array(
'argb' => 'FFFFFFFF'
)
)
),
'A3:E3'
);

Les formats de cellules

Par défaut les cellules prennent le format qui leur a été envoyé par les méthodes setCellValue et setCellValueByColumnAndRow.

PHPExcel_Cell_DataType

Cette classe va nous permettre de fixer le type de données, grâce aux méthodes setCellValueExplicit() et setCellValueByColumnAndRowExplicit().
Ces deux méthodes prennent un troisième argument définissant le type de la cellule.

$sheet->setCellValue('A1','MaitrePylos',PHPEcel_Cell_DataType::TYPE_STRING);

Nous définissons ici explicitement une cellule en A1 contenant 'MaitrePylos' et la cellule sera fixée au type string.
Les différents types définis sont :

Constante

Valeur

TYPE_STRING

's'

TYPE_FORMULA

'f'

TYPE_NUMERIC

'n'

TYPE_BOOL

'b'

TYPE_NULL

's'

TYPE_INLINE

'inlineStr'

TYPE_ERROR

'e'

Vite dit

Fusion de cellules

//on fusionne les cellules de A1 à D1
$sheet->mergeCells('A1:D1');

Largeur de colonne

$sheet->getColumnDimension('A')->setWidth(28);

Hauteur de ligne

$sheet->getRowDimension('2')->setRowHeight(70);

Taille de la page

$sheet->getPageSetup()->setPaperSize(PHPExcel_Worksheet_PageSetup::PAPERSIZE_A4);

Les formats possibles sont :

Type

Constante

Valeur

Letter paper (8.5 in. by 11 in.)

PAPERSIZE_LETTER

1

Letter small paper (8.5 in. by 11 in.)

PAPERSIZE_LETTER_SMALL

2

Tabloid paper (11 in. by 17 in.)

PAPERSIZE_TABLOID

3

Ledger paper (17 in. by 11 in.)

PAPERSIZE_LEDGER

4

Legal paper (8.5 in. by 14 in.)

PAPERSIZE_LEGAL

5

Statement paper (5.5 in. by 8.5 in.)

PAPERSIZE_STATEMENT

6

Executive paper (7.25 in. by 10.5 in.)

PAPERSIZE_EXECUTIVE

7

A3 paper (297 mm by 420 mm)

PAPERSIZE_A3

8

A4 paper (210 mm by 297 mm)

PAPERSIZE_A4

9

A4 small paper (210 mm by 297 mm)

PAPERSIZE_A4_SMALL

10

A5 paper (148 mm by 210 mm)

PAPERSIZE_A5

11

B4 paper (250 mm by 353 mm)

PAPERSIZE_B4

12

B5 paper (176 mm by 250 mm)

PAPERSIZE_B5

13

Folio paper (8.5 in. by 13 in.)

PAPERSIZE_FOLIO

14

Quarto paper (215 mm by 275 mm)

PAPERSIZE_QUARTO

15

Standard paper (10 in. by 14 in.)

PAPERSIZE_STANDARD_1

16

Standard paper (11 in. by 17 in.)

PAPERSIZE_STANDARD_2

17

Note paper (8.5 in. by 11 in.)

PAPERSIZE_NOTE

18

Envelope (3.875 in. by 8.875 in.)

PAPERSIZE_NO9_ENVELOPE

19

Envelope (4.125 in. by 9.5 in.)

PAPERSIZE_NO10_ENVELOPE

20

Envelope (4.5 in. by 10.375 in.)

PAPERSIZE_NO11_ENVELOPE

21

Envelope (4.75 in. by 11 in.)

PAPERSIZE_NO12_ENVELOPE

22

Envelope (5 in. by 11.5 in.)

PAPERSIZE_NO14_ENVELOPE

23

C paper (17 in. by 22 in.)

PAPERSIZE_C

24

Etc..

Vour retrouverez l'ensemble des formats dans le fichier PHPExcel_Worksheet_PageSetup.php.

Orientation de la page

$sheet->getPageSetup()->setOrientation(PHPExcel_Worksheet_PageSetup::ORIENTATION_LANDSCAPE);

Les orientations possibles sont :

Constante

Valeur

ORIENTATION_DEFAULT

'default'

ORIENTATION_LANDSCAPE

'landscape'

ORIENTATION_PORTRAIT

'portrait'

Freeze Pane

Pour geler une cellule

//mettre la cellule en paramètres.
$sheet->freezePane('A2');

Ça existe aussi

PHPExcel offre vraiment une panoplie de possibilités, cet article n'étant qu'une approche sommaire, je vous laisse le soin d'aller plus loin dans l'exploration de ces classes.
Vous pourriez découvrir notamment :

- la protection des documents et cellules ;

- les entêtes et pieds de pages ;

- les zones d'impression ;

- les sauts de page ;

- les méta-informations sur les cellules/fichiers ;

- tout ce que je n'ai pas lu ou aperçu :)

Travailler avec l'existant

Suite à la publication de cet article, une des demandes était de savoir si on pouvait modifier un fichier Excel existant ?
La réponse est oui ! Et nous allons voir comment faire, pour lire le fichier, récupérer les données et en ajouter ou modifier.

Lire un fichier Excel

La première action à faire est de lire le fichier Excel.
Pour ce faire nous allons créer un environnement de travail correct pour les exemples.
PHPExcel respectant la convention de nommage de PEAR, cela va nous faciliter le travail, en effet je vais partir du principe que nous travaillons dans le répertoire 'Classes', fourni par l'archive de PHPExcel.
Au cœur de ce répertoire, nous allons créer un fichier 'read.php' avec le contenu suivant :

$path = './';
set_include_path(get_include_path() . PATH_SEPARATOR . $path);

function __autoload($classe)
{
$fichier = str_replace
(
'_',      # Caractère à remplacer.
DIRECTORY_SEPARATOR, # Caractère de remplacement.
$classe       # Cible du remplacement.
) . '.php' ;
require_once($fichier) ; # Chargement de la classe.
}

$objet = new PHPExcel_Reader_Excel5();

$excel = $objet->load('Exemple14.xls');

$writer = new PHPExcel_Writer_Excel5($excel);

$writer->save('autreFichier.xls');

Voici quelques explications de ce code. On précise d'abord où on travaille, la racine des classes.

$path = './';
set_include_path(get_include_path() . PATH_SEPARATOR . $path);

Ensuite, on met en place la fonction autoload standard de la SPL.
Cela nous évitera de mettre en place les require nécessaires.

function __autoload($classe)
{
$fichier = str_replace
(
'_',      # Caractère à remplacer.
DIRECTORY_SEPARATOR, # Caractère de remplacement.
$classe       # Cible du remplacement.
) . '.php' ;
require_once($fichier) ; # Chargement de la classe.
}

On instancie un objet de lecture de PHPExcel

$objet = new PHPExcel_Reader_Excel5();

Ici j'ai pris le pli de travailler avec un fichier Excel non XML (.xls), mais nous disposons des possibilités suivantes :

- CSV ;

- Excel2003(XML) ;

- Excel2007 ;

- Excel5 ;

- SYLK ;

- OoCalc.

Ensuite nous lisons le fichier Excel, pour les exemples, je me base sur un fichier (le 14) généré par les démos de PHPExcel.

$excel = $objet->load('Exemple14.xls');

Nous disposons donc d'un objet, possédant le contenu de notre fichier Excel.
À partir de ce moment, nous pouvons travailler sur le fichier Excel. Une fois le travail terminé nous l'enregistrons ou créons un nouveau document.

$writer = new PHPExcel_Writer_Excel5($excel);

$writer->save('autreFichier.xls')

Ici nous avons tout simplement enregistré le fichier sous un autre nom.
Pour faciliter le travail avec cette librairie, les développeurs de PHPExcel, ont mis en place un pattern factory.

$objet = PHPExcel_IOFactory::createReader('Excel5');

$excel = $objet->load('Exemple14.xls');

$writer = PHPExcel_IOFactory::createWriter($excel);
$writer->save('Exemple14.xls');

Écrire dans un fichier existant !

Un des aspects les plus intéressants est de pouvoir écrire dans un fichier existant.
Cela se fait très facilement, en fait de la même façon que de créer un document, il faut juste signaler à PHPExcel où l'on veut écrire !

$objet = PHPExcel_IOFactory::createReader('Excel5');

$excel = $objet->load('Exemple14.xls');

$sheet = $excel->getSheet(0);

$sheet->setCellValue('A50', 'MaitrePylos');

$writer = PHPExcel_IOFactory::createWriter($excel);
$writer->save('Exemple14.xls');

Ici nous devons donc savoir sur quelles feuilles travailler

$sheet = $excel->getSheet(0);

La méthode getSheet(), renvoie donc un sheet indexé, mais si nous connaissons son nom, il est également possible de la récupérer

$sheet = $excel->getSheetByName('Invoice');

Ensuite nous écrivons dedans

$sheet->setCellValue('A35', 'MaitrePylos');

Connaître son fichier

Dans la perspective où vous ne connaîtriez pas le fichier avec lequel vous travaillez, il est possible de récupérer une série d'information sur ce fichier.

Le nom des sheets

La méthode getSheetNames() retourne un tableau contenant le nom des sheets

$name_sheet = $excel->getSheetNames();

L'index des sheets

La méthode getSheetCount() retourne le nombre de sheets suivant son index

$count_sheet = $excel->getSheetCount();

Fusionner plusieurs fichiers Excel

Maintenant que nous savons lire un fichier Excel, rien ne nous empêche d'en fusionner plusieurs

$objet1 = new PHPExcel_Reader_Excel5();

$excel1 = $objet1->load('Exemple14.xls');

$objet2 = new PHPExcel_Reader_Excel5();

$excel2 = $objet2->load('autreFichier.xls');

$writer = new PHPExcel();
//insertion des sheets du premier fichier

for ($i=0;$i<$excel1->getSheetCount();$i++){
$writer->addSheet($excel1->getSheet($i));
}
//insertion des sheets du second fichier
for ($i=0;$i<$excel2->getSheetCount();$i++){
$writer->addSheet($excel2->getSheet($i));
}
//je modifie un sheet pour voir la différence
$sheet = $writer->getSheet(3);
$sheet->setCellValue('A50', 'MaitrePylos');

$save = new PHPExcel_Writer_Excel5($writer);
$save->save('Exemple_gg.xls');

Utiliser plusieurs fois le même sheet

On peut vouloir dupliquer le même sheet, dans ce cas il faut utiliser la méthode copy de l'objet Reader

$objet1 = new PHPExcel_Reader_Excel5();

$excel1 = $objet1->load('Exemple14.xls');

$sheet1 = $excel1->getSheet(0);
$sheet2 = $sheet1->copy();
$sheet2->setTitle('Cloned Worksheet');

$writer = new PHPExcel();
$writer->addSheet($sheet1);
$writer->addSheet($sheet2);
$sheet2 = $writer->getSheet(2);
$sheet2->setCellValue('A2', 2);
$save = new PHPExcel_Writer_Excel5($writer);
$save->save('bugResult1.xls');

Nous avons ici copié deux fois le même sheet.
Une autre possibilité est d'utiliser la fonction Clone de PHP

$objet1 = new PHPExcel_Reader_Excel5();

$excel1 = $objet1->load('Exemple14.xls');

$sheet1 = $excel1->getSheet(0);
$sheet2 = clone $sheet1;
$sheet2->setTitle('Cloned Worksheet');

$writer = new PHPExcel();
$writer->addSheet($sheet1);
$writer->addSheet($sheet2);
$sheet2 = $writer->getSheet(2);
$sheet2->setCellValue('A2', 2);
$save = new PHPExcel_Writer_Excel5($writer);
$save->save('bugResult1.xls');

Mes essais concernant cette seconde méthode ne sont pas très concluants quand le sheet que l'on veut copier contient des images. En effet lors de la copie je perds toute trace des images.
Dans ce cas, je préfère réaliser une fusion de deux fichiers, en utilisant deux fois le même fichier d'origine. Je terminerai ici ce paragraphe sur la lecture des fichiers.

Extraire des images

Lors d'échanges sur le forum, @objectifweb un posteur, nous a soumis une difficulté qu'il rencontrait, c'est-à-dire extraire des photos d'un fichier existant.
Il nous a orienté vers une solution, que l'on peut retrouver dans les archives de PHPExcel. À la lecture d'un fichier Excel, une des méthodes qui recense les images est getDrawingCollection(). Dans un premier temps, créer un répertoire /images pour réceptionner toutes les images, ensuite il faut boucler sur getDrawingCollection() et créer les images avec la fonction image/jpeg/gif() de PHP

$objet1 = new PHPExcel_Reader_Excel5();

$excel1 = $objet1->load('Exemple14.xls');

$sheet1 = $excel1->getSheet(0);

foreach ($sheet1->getDrawingCollection() as $drawing) {
// $drawing->getCoordinates();

// we have an ordinary drawing (case xlsx)
if ($drawing instanceof PHPExcel_Worksheet_Drawing) {

$filename = $drawing->getPath();

copy($filename, 'images/' . $drawing->getIndexedFilename());

// we have a memory drawing (case xls)
} else if ($drawing instanceof PHPExcel_Worksheet_MemoryDrawing) {

$image = $drawing->getImageResource();

// save image to disk
$renderingFunction = $drawing->getRenderingFunction();

switch ($renderingFunction) {

case PHPExcel_Worksheet_MemoryDrawing::RENDERING_JPEG:
imagejpeg($image, 'images/' . $drawing->getIndexedFilename());
break;

case PHPExcel_Worksheet_MemoryDrawing::RENDERING_GIF:
imagegif($image, 'images/' . $drawing->getIndexedFilename());
break;

case PHPExcel_Worksheet_MemoryDrawing::RENDERING_PNG:
case PHPExcel_Worksheet_MemoryDrawing::RENDERING_DEFAULT:
imagepng($image, 'images/' . $drawing->getIndexedFilename());
break;
}
}
}

Conclusion

Pour finir, je dirai que nous avons là une librairie qui va nous rendre de grands services dans le développement de nos activités.
Il ne nous reste plus qu'à injecter des données venant de nos bases de données.

Merci

Que soient remerciés ici tous ceux qui m'ont apporté une aide précieuse à la confection de cet article (Frédérique, Yogui, Celira… ).
Je voudrais aussi remercier Magali Contensin et Cécile Odero du CNRS, pour leur article sur PHPExcel paru dans le Phpsolutions du mois de mai 2008, s'il vous est possible de vous procurer cet article, je vous en conseille la lecture.

Liens

PHPExcel
Spreadsheet_Excel_Writer en PHP
Spreadsheet_Excel_Writer
FPDF
http://snaps.php.net/