Hai presente quel file Excel? Quello che pesa ormai troppo, pieno di celle colorate a mano, con formule lunghe tre righe che se ne tocchi una per sbaglio esplode tutto il report mensile? Ecco. È il momento di lasciarselo alle spalle.
Non siamo qui per dire che Excel è morto; è ancora il re dei fogli di calcolo. Ma usarlo come database, motore di calcolo e strumento di presentazione tutto insieme è il modo migliore per impazzire. Oggi vediamo come delegare la parte noiosa del lavoro “sporco” a Python.
L’obiettivo non è farti diventare un programmatore puro, ma un analista “aumentato”: qualcuno che lancia uno script e in due secondi ottiene quello che i colleghi fanno in tre ore di copia-incolla. Costruiremo un sistema che prende dati grezzi, li pulisce e restituisce un report finanziario elegante, pronto per essere inviato al manager.
Partiremo dalla generazione di dati sintetici (per simulare un ambiente aziendale reale) e arriveremo a un file Excel formattato, pronto per essere presentato.
Preparazione dell’Ambiente: Generazione dei Dati
Il primo passo è creare il nostro database di test. Utilizziamo pandas per la struttura e numpy per simulare la stagionalità delle vendite e la casualità delle spese.
import pandas as pd
import numpy as np
from datetime import datetime
np.random.seed(1122)
# Crea dati per 12 mesi
mesi = ['Gennaio', 'Febbraio', 'Marzo', 'Aprile', 'Maggio', 'Giugno',
'Luglio', 'Agosto', 'Settembre', 'Ottobre', 'Novembre', 'Dicembre']
# --- FOGLIO VENDITE ---
# Vendite con stagionalità
vendite_base = [120000, 115000, 130000, 125000, 140000, 135000,
150000, 145000, 160000, 155000, 170000, 165000]
# Aggiungi variazioni casuali
vendite_importo = [base * np.random.uniform(0.9, 1.1) for base in vendite_base]
vendite_importo = [round(x, 2) for x in vendite_importo]
df_vendite = pd.DataFrame({
'Mese': mesi,
'Importo': vendite_importo,
'Clienti_Attivi': np.random.randint(150, 250, 12),
'Nuovi_Clienti': np.random.randint(10, 30, 12)
})
# --- FOGLIO SPESE ---
# Spese per categoria
categorie_spese = ['Personale', 'Affitto', 'Utilità', 'Marketing', 'IT', 'Varie']
spese_mensili = []
for mese in mesi:
spese_mese = []
for cat in categorie_spese:
if cat == 'Personale':
base = 60000
elif cat == 'Affitto':
base = 12000
elif cat == 'Marketing':
base = np.random.randint(8000, 15000)
elif cat == 'IT':
base = np.random.randint(3000, 7000)
else:
base = np.random.randint(1000, 5000)
# Variazione mensile
spese_mese.append(base * np.random.uniform(0.95, 1.05))
spese_mensili.append(spese_mese)
df_spese = pd.DataFrame(spese_mensili, columns=categorie_spese)
df_spese['Mese'] = mesi
df_spese['Importo'] = df_spese[categorie_spese].sum(axis=1).round(2)
# Riordina colonne
df_spese = df_spese[['Mese', 'Importo'] + categorie_spese]
# --- FOGLIO PERSONALE ---
# Dipendenti con dettagli
dipendenti = ['Mario Rossi', 'Luigi Bianchi', 'Giulia Verdi', 'Anna Neri',
'Paolo Gialli', 'Laura Blu', 'Marco Viola', 'Sara Rosa']
stipendi_base = [45000, 42000, 38000, 35000, 32000, 30000, 28000, 26000]
mansioni = ['Dirigente', 'Manager', 'Sviluppatore Senior', 'Sviluppatore',
'Marketing', 'Vendite', 'Amministrazione', 'Supporto']
# Crea dati mensili per personale
dati_personale = []
for mese in mesi:
for i, (nome, stipendio, mansione) in enumerate(zip(dipendenti, stipendi_base, mansioni)):
# Aggiungi bonus occasionali
stipendio_mensile = stipendio / 12
if np.random.random() < 0.2: # 20% probabilità bonus
stipendio_mensile *= 1.1
dati_personale.append({
'Mese': mese,
'Dipendente': nome,
'Mansione': mansione,
'Stipendio_Mensile': round(stipendio_mensile, 2),
'Ore_Lavorate': np.random.randint(140, 180)
})
df_personale = pd.DataFrame(dati_personale)
# Somma per mese per il foglio principale
df_personale_tot = df_personale.groupby('Mese')['Stipendio_Mensile'].sum().reset_index()
df_personale_tot.columns = ['Mese', 'Importo']
# --- SALVA TUTTI I FOGLI ---
with pd.ExcelWriter('azienda_dati.xlsx', engine='openpyxl') as writer:
# Fogli principali per l'esercizio
df_vendite.to_excel(writer, sheet_name='Vendite', index=False)
df_spese.to_excel(writer, sheet_name='Spese', index=False)
df_personale_tot.to_excel(writer, sheet_name='Personale', index=False)
# Fogli aggiuntivi per dati dettagliati
df_personale.to_excel(writer, sheet_name='Dettaglio_Personale', index=False)
# Foglio di configurazione/metadati
metadati = {
'Anno': [2024, 2024, 2024],
'Report_Generato': [datetime.now().strftime("%Y-%m-%d %H:%M:%S")] * 3,
'Versione': ['1.0', '1.0', '1.0'],
'Note': ['Dati di vendita', 'Dati di spesa', 'Dati personale']
}
pd.DataFrame(metadati).to_excel(writer, sheet_name='Metadati', index=False)
print("File 'azienda_dati.xlsx' creato con successo!")
print("Contiene 5 fogli: Vendite, Spese, Personale, Dettaglio_Personale, Metadati")
print(f"Vendite totali: €{df_vendite['Importo'].sum():,.2f}")
print(f"Spese totali: €{df_spese['Importo'].sum():,.2f}")
Spiegazione
Crea 3 fogli principali
Foglio “Vendite”
-
Genera vendite mensili con stagionalità crescente verso fine anno
-
Aggiunge una variazione casuale del ±10% per simulare fluttuazioni
-
Include metriche aggiuntive:
-
Clienti_Attivi: tra 150-250 clienti/mese -
Nuovi_Clienti: tra 10-30 nuovi clienti/mese
-
Foglio “Spese”
-
Crea spese per 6 categorie: Personale, Affitto, Utilità, Marketing, IT, Varie
-
Ogni categoria ha un valore base realistico
-
Aggiunge variazioni casuali del ±5% mensili
-
Calcola il totale mensile delle spese
Foglio “Personale”
-
Simula 8 dipendenti con nomi, mansioni e stipendi diversi
-
Calcola stipendio mensile (annuale/12)
-
Aggiunge occasionali bonus del 10% (20% di probabilità)
-
Tiene traccia delle ore lavorate (140-180 ore/mese)
-
Crea sia una versione aggregata mensile che una dettagliata
Fogli aggiuntivi
-
Dettaglio_Personale: dati completi per ogni dipendente ogni mese
-
Metadati: informazioni sul report (anno, data generazione, versione, note)
Output finale
Salva tutto in un file Excel chiamato azienda_dati.xlsx con 5 fogli separati.
A questo punto abbiamo un file Excel che, pur essendo generato automaticamente, riproduce la complessità di un vero ambiente aziendale.
La fase successiva non riguarda più la generazione dei dati, ma la loro interpretazione.
Il “Cervello”: Elaborazione e Normalizzazione
Questa è la fase più critica del processo. Il codice deve essere in grado di interpretare i fogli di calcolo e comprenderne la struttura semantica in modo autonomo, senza necessità di configurazioni manuali ripetitive.
Il progetto completo, organizzato per moduli e sezioni, è disponibile qui:
👉Dashboard_Aziendale_Python_Codice_Completo

1. Pulizia Dinamica delle Colonne
Utilizziamo le Regex (Espressioni Regolari) e le funzioni di manipolazione delle stringhe per normalizzare i nomi delle colonne. Ad esempio, se un utente inserisce “Mese ” (con uno spazio finale), il sistema lo correggerà automaticamente in “mese”.
# Normalizzazione: minuscolo, rimuovi spazi e caratteri speciali
df_foglio.columns = (
df_foglio.columns
.astype(str)
.str.lower()
.str.replace(' ', '_', regex=False)
.str.replace(r'[^\w_]', '', regex=True)
)
2. Unione dei Dati (Merge)
Invece di una semplice concatenazione, utilizziamo una merge di tipo “outer”. Questa scelta è strategica: se in un determinato mese non sono state registrate vendite ma sono presenti delle spese, vogliamo che quel mese appaia comunque nel report finale per garantire l’integrità del bilancio.
3. Calcolo del Profitto e dei Margini
Implementiamo una logica basata su keyword per distinguere i flussi in entrata (Ricavi) da quelli in uscita (Costi). Una volta mappati i dati, applichiamo le formule finanziarie standard:
[math]\displaystyle \text{Profitto} = \sum \text{Ricavi} – \sum \text{Costi}[/math]
[math]\displaystyle \text{Margine %} = \left( \frac{\text{Profitto}}{\text{Ricavi}} \right) \cdot 100[/math]
4. Visualizzazione: Il Grafico Ibrido
Per la dashboard non utilizziamo un grafico standard, ma un sistema a doppio asse Y per gestire ordini di grandezza differenti:
- Asse Primario (Barre): Per visualizzare i volumi monetari di Ricavi e Costi.
- Asse Secondario (Linea): Per monitorare il trend del profitto.
fig, ax1 = plt.subplots(figsize=(12, 7))
# Barre per i volumi
ax1.bar(x, ricavi, color='green', alpha=0.7, label='Ricavi')
ax1.bar(x + width, costi, color='red', alpha=0.7, label='Costi')
# Linea per il profitto (asse gemello)
ax2 = ax1.twinx()
ax2.plot(x, profitto, 'b-^', linewidth=3, label='Profitto')
5. Crafting dell’Excel: Estetica e Funzionalità
Grazie alla libreria openpyxl, il documento finale non è un semplice dump di dati, ma un report professionale:
- Formattazione Condizionale: Se il profitto è negativo, la cella viene evidenziata in rosso automaticamente.
- Ancoraggio Immagini: Il grafico generato in Matplotlib viene inserito dinamicamente in una cella specifica (es.
A{riga}). - Stili di Cella: Applicazione di bordi, font grassetti per le intestazioni e totalizzatori annuali.
🏁 Il Risultato Finale
Eseguendo lo script, il sistema genererà un file denominato azienda_dashboard.xlsx contenente:
- Un foglio Dashboard con i dati unificati e puliti.
- Totalizzatori annuali a fondo pagina.
- Un Grafico ad alta risoluzione integrato nel foglio Excel.
- Un riepilogo testuale nel terminale con l’indicazione del miglior e peggior mese dell’anno.
🛠️ Il Tuo Toolkit
Per questo progetto abbiamo utilizzato la “Trinità” della data automation in Python:
-
Pandas: Per la manipolazione e pulizia dei dati.
-
Matplotlib: Per la creazione del motore grafico.
-
Openpyxl: Per “scrivere” fisicamente dentro Excel, gestendo stili, colori e immagini.
Formattazione Professionale con Openpyxl
L’output non è un semplice dump di dati. Utilizziamo openpyxl per trasformare un foglio bianco in un report pronto per una riunione direzionale:
| Funzionalità | Descrizione |
| Styling Titoli | Font grandi, grassetto e sfondo blu navy. |
| Formattazione Valuta | Numeri formattati automaticamente con il simbolo € e separatore delle migliaia. |
| Highlighting Condizionale | Celle dei profitti in Verde se positive, in Rosso se negative. |
| Inserimento Immagini | Il grafico generato viene ancorato esattamente sotto la tabella dei totali. |
Conclusione
Grazie a questo flusso, quello che prima richiedeva 30 minuti di lavoro manuale ora viene eseguito in meno di 2 secondi. Hai creato un sistema che non solo calcola dati, ma li interpreta e li presenta.
👉 Ultimo passo: inviare automaticamente il report via email
Articoli di approfondimento
👉 Excel + Python: un’accoppiata vincente
👉 Python e Excel: automatizzare analisi dati in 10 minuti (case study)
👉 Excel e Python per l’analisi dati: guida completa
👉 Excel e Python: perché l’integrazione è il futuro della data analysis
👉 Cos’è il Risolutore di Excel?
👉 Power BI & Python: analisi dati avanzata e machine learning
👉Ottimizza vendite & marketing: probabilità e break-even con Excel + Python
👉Python ed Excel: Guida Pratica all’Automazione con Pandas e OpenPyXL (Esercizi Reali)




