Formati e fonti di dati 4 min di lettura

Parsing di file Excel: fogli, formule, celle unite ed esempi in vari linguaggi

Come fare il parsing di file Excel da codice: fogli, formule, celle unite, formati di data ed esempi di lettura in Python, JavaScript, PHP e Go.

TW
Team Web-Scraping.it
Raccolta dati per le esigenze del business
Pubblicato il 6 marzo 2025

I file di Excel (.xlsx e, più di rado, il vecchio .xls) sono il formato più comune in cui le aziende inviano i dati: listini prezzi, disponibilità, report, esportazioni dai gestionali. A differenza del CSV, un Excel non è testo semplice ma un documento strutturato: dentro un .xlsx c’è un archivio ZIP con la descrizione XML di fogli, stili e formule. Per questo non si può leggerlo «come righe di testo»: servono librerie che capiscano la struttura interna della cartella di lavoro. L’articolo prosegue la nostra panoramica sul parsing di documenti.

Cosa complica il parsing di Excel

A differenza di un CSV piatto, una cartella di lavoro Excel ha diversi livelli di complessità. Primo, i fogli multipli: i dati possono essere distribuiti su più schede e bisogna scegliere esplicitamente quella giusta. Secondo, le formule: una cella può contenere sia la formula =B2*C2 sia il suo valore calcolato, e quello che ottieni dipende dal modo di lettura. Terzo, le celle unite, per colpa delle quali un’intestazione «pende» sopra più colonne e nei dati compaiono dei vuoti. Quarto, i formati: una data può arrivare non come 2026-06-01 ma come il numero 46184 (il numero seriale con cui Excel memorizza le date), e un prezzo come un numero con il formato valuta salvato a parte. Di tutto questo bisogna tenere conto in fase di estrazione.

Python

Lo strumento di base per gli .xlsx è openpyxl. Dà il controllo completo sulla cartella di lavoro: fogli, celle, celle unite.

python
from openpyxl import load_workbook

wb = load_workbook("prices.xlsx", data_only=True)  # data_only=True → valori al posto delle formule
ws = wb["Listino"]                                 # scegliamo il foglio per nome

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)

Fai attenzione a data_only=True: senza, una cella con formula restituisce il testo della formula e non il risultato. E ricorda che il valore calcolato esiste solo se il file è stato aperto almeno una volta in Excel — openpyxl non calcola le formule da sé.

Quando non serve un’iterazione riga per riga ma un’analisi — filtri, aggregazioni, unione di tabelle — si passa a pandas, che carica il foglio in un DataFrame con una sola riga (sotto il cofano usa openpyxl).

python
import pandas as pd

df = pd.read_excel("prices.xlsx", sheet_name="Listino")
print(df[df["price"] > 3000])

# se serve, conversione in CSV
df.to_csv("prices.csv", index=False, encoding="utf-8-sig")

Per il vecchio formato binario .xls pandas usa un motore a parte, xlrd; i file moderni .xlsx passano per openpyxl.

JavaScript / Node.js

Nell’ecosistema JS lo standard de facto è SheetJS (pacchetto xlsx). Funziona sia in Node sia nel browser, legge quasi tutti i formati di tabella e trasforma comodamente un foglio in un array di oggetti.

javascript
const XLSX = require("xlsx");

const wb = XLSX.readFile("prices.xlsx");
const sheet = wb.Sheets[wb.SheetNames[0]];   // primo foglio
const rows = XLSX.utils.sheet_to_json(sheet); // array di oggetti secondo la riga di intestazione

for (const row of rows) {
  console.log(row.sku, row.name, row.price);
}

Quando oltre a leggere bisogna anche generare cartelle di lavoro complesse con stili, la scelta giusta è ExcelJS.

PHP

La libreria principale è PhpSpreadsheet (l’erede della vecchia PHPExcel). Legge e scrive .xlsx e .xls, capisce formule e formati.

php
<?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) { // saltiamo la riga di intestazione
    echo $row["A"] . " — " . $row["B"] . " — " . $row["C"] . "\n";
}

Go

In Go lo standard de facto è excelize. Legge i fogli come righe e supporta formule, stili e streaming per i file di grandi dimensioni.

go
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("Listino")
    for _, row := range rows[1:] {
        fmt.Println(row[0], row[1], row[2])
    }
}

Consigli pratici

Prima di scrivere il parser conviene aprire il file con i propri occhi e capirne la struttura: dove iniziano i dati (spesso le prime righe sono occupate da intestazione e logo), se ci sono celle unite nelle intestazioni, su quale foglio stanno i dati che servono. Se l’intestazione non è standard, è più semplice indicare al parser la riga di partenza che provare a indovinarla. Date e numeri conviene normalizzarli subito dopo la lettura — portarli a un formato unico, perché nello stesso file compaiono spesso scritti in modi diversi.

Se le cartelle di lavoro sono omogenee ma con più fogli, celle unite e formule, e arrivano con regolarità, configuriamo un parsing automatico di Excel con esportazione in un database o in CSV per l’elaborazione successiva. Quando invece i report non arrivano in Excel ma impaginati per la stampa, quello è già parsing di PDF — vedi l’articolo dedicato.