Les fichiers Excel (.xlsx, plus rarement l'ancien .xls) sont le format le plus courant dans lequel les entreprises transmettent leurs données : listes de prix, stocks, rapports, exports de systèmes de gestion. Contrairement au CSV, Excel n'est pas du texte mais un document structuré : un fichier .xlsx est en réalité une archive ZIP contenant la description XML des feuilles, des styles et des formules. Impossible donc de le lire « ligne par ligne » comme du texte brut — il faut des bibliothèques qui comprennent la structure interne du classeur. Cet article poursuit notre tour d'horizon du parsing de documents.
Ce qui complique le parsing d'Excel
Contrairement à un CSV plat, un classeur Excel comporte plusieurs couches de complexité. Premièrement, plusieurs feuilles — les données peuvent être réparties entre les onglets, et il faut sélectionner explicitement la bonne feuille. Deuxièmement, les formules : une cellule peut contenir aussi bien la formule =B2*C2 que sa valeur calculée, et ce que vous obtiendrez dépend de la méthode de lecture. Troisièmement, les cellules fusionnées, à cause desquelles un en-tête « chevauche » plusieurs colonnes et des vides apparaissent dans les données. Quatrièmement, les formats : une date peut arriver non pas sous la forme 2026-06-01, mais comme le nombre 46184 (numéro de série de date Excel), et un prix comme un nombre associé à un format monétaire. Tout cela doit être pris en compte lors de l'extraction.
Python
L'outil de base pour le .xlsx est openpyxl. Il offre un contrôle complet sur le classeur : feuilles, cellules, fusions.
from openpyxl import load_workbook
wb = load_workbook("prices.xlsx", data_only=True) # data_only=True → valeurs au lieu des formules
ws = wb["Tarifs"] # sélection de la feuille par son nom
for row in ws.iter_rows(min_row=2, values_only=True):
sku, name, price = row[0], row[1], row[2]
print(sku, name, price)
Notez le paramètre data_only=True : sans lui, une cellule contenant une formule renverra le texte de la formule et non le résultat. Et rappelez-vous que la valeur calculée n'existe que si le fichier a été ouvert au moins une fois dans Excel — openpyxl ne calcule pas les formules lui-même.
Lorsqu'il faut non pas un parcours ligne par ligne mais de l'analyse — filtres, agrégats, jointures de tableaux — on utilise pandas, qui lit une feuille dans un DataFrame en une seule ligne (il s'appuie sur openpyxl en interne).
import pandas as pd
df = pd.read_excel("prices.xlsx", sheet_name="Tarifs")
print(df[df["price"] > 3000])
# si besoin — conversion en CSV
df.to_csv("prices.csv", index=False, encoding="utf-8-sig")
Pour l'ancien format binaire .xls, pandas utilise un moteur distinct, xlrd ; les fichiers modernes .xlsx sont traités via openpyxl.
JavaScript / Node.js
Dans l'écosystème JS, le standard de facto est SheetJS (paquet xlsx). Il fonctionne aussi bien dans Node que dans le navigateur, lit presque tous les formats de tableurs et transforme commodément une feuille en tableau d'objets.
const XLSX = require("xlsx");
const wb = XLSX.readFile("prices.xlsx");
const sheet = wb.Sheets[wb.SheetNames[0]]; // première feuille
const rows = XLSX.utils.sheet_to_json(sheet); // tableau d'objets d'après les en-têtes
for (const row of rows) {
console.log(row.sku, row.name, row.price);
}
Lorsqu'il faut non seulement lire mais aussi générer des classeurs complexes avec des styles, ExcelJS fera l'affaire.
PHP
La bibliothèque principale est PhpSpreadsheet (successeur de l'ancienne PHPExcel). Elle lit et écrit les formats .xlsx et .xls, et comprend les formules et les formats.
<?php
require "vendor/autoload.php";
use PhpOffice\PhpSpreadsheet\IOFactory;
$spreadsheet = IOFactory::load("prices.xlsx");
$rows = $spreadsheet->getActiveSheet()->toArray(null, true, true, true);
foreach (array_slice($rows, 1) as $row) { // on saute l'en-tête
echo $row["A"] . " — " . $row["B"] . " — " . $row["C"] . "\n";
}
Go
En Go, le standard de facto est excelize. Il lit les feuilles sous forme de lignes et prend en charge les formules, les styles et le streaming pour les gros fichiers.
package main
import (
"fmt"
"github.com/xuri/excelize/v2"
)
func main() {
f, err := excelize.OpenFile("prices.xlsx")
if err != nil {
panic(err)
}
defer f.Close()
rows, _ := f.GetRows("Tarifs")
for _, row := range rows[1:] {
fmt.Println(row[0], row[1], row[2])
}
}
Conseils pratiques
Avant d'écrire un parseur, il est utile d'ouvrir le fichier et d'en comprendre la structure : où commencent les données (les premières lignes sont souvent occupées par un en-tête et un logo), y a-t-il des cellules fusionnées dans les intitulés, sur quelle feuille se trouvent les données recherchées. Si l'en-tête est atypique, il est plus simple d'indiquer au parseur la ligne de départ que d'essayer de la deviner. Il vaut mieux normaliser les dates et les nombres dès la lecture — les ramener à un format unique, car dans un même fichier ils sont souvent saisis de manières différentes.
Si les classeurs sont de structure identique mais multi-feuilles, avec des cellules fusionnées et des formules, et qu'ils arrivent régulièrement — nous mettrons en place un parsing Excel automatisé avec export vers une base de données ou en CSV pour un traitement ultérieur. Et lorsque les rapports n'arrivent pas en Excel mais sont mis en page pour l'impression, il s'agit alors de parsing de PDF — consultez l'article dédié.