PythonAutomationData AnalysisPandasMatplotlibReporting

Comment Automatiser vos Rapports avec Python et Gagner 15 Heures par Mois

GP
Gaël Penessot
Comment Automatiser vos Rapports avec Python et Gagner 15 Heures par Mois

Vous passez 3 heures chaque semaine à créer les mêmes rapports ?

  • Télécharger les données depuis 5 sources différentes
  • Les nettoyer dans Excel
  • Créer les graphiques dans PowerPoint
  • Copier-coller les chiffres clés
  • Envoyer par email à 15 personnes

Total : 12 heures par mois de travail répétitif et ennuyeux.

Aujourd'hui, je vais vous montrer comment automatiser ce processus de A à Z avec Python et récupérer ces 15 heures pour du travail à valeur ajoutée.

Le Problème du Reporting Manuel

Voici le cycle infernal que vivent 80% des analystes data :

Lundi matin, 9h00 : "Il faut envoyer le rapport hebdo avant 11h"

  1. Ouvrir 5 fichiers Excel différents
  2. Copier les données dans un fichier maître
  3. Vérifier qu'il n'y a pas d'erreurs (il y en a toujours)
  4. Créer les graphiques manuellement
  5. Formater le tout dans PowerPoint
  6. Écrire l'email de synthèse
  7. Envoyer à toute l'équipe

Résultat : 3 heures de perdues, et la semaine prochaine, vous recommencerez exactement la même chose.

Le Coût Réel Pour Votre Équipe

Pour un analyste à 45€/heure qui passe 3 heures/semaine sur ce type de tâches :

3 heures × 50 semaines = 150 heures/an
150 heures × 45€ = 6 750€

Pour une équipe de 3 personnes : 20 250€/an

Et ce n'est que le coût direct. Le coût indirect ? Le temps que vous ne passez pas à analyser, à trouver des insights, à créer de la valeur.

La Solution : Pipeline d'Automatisation Python

Voici le workflow que nous allons construire :

Extraction → Transformation → Analyse → Visualisation → Diffusion

Temps manuel : 3 heures/semaine Temps automatisé : 5 minutes/semaine (juste vérifier que tout s'est bien passé)

Gain : 2h55 par semaine = 147 heures par an = 6 615€ économisés

Étape 1 : Extraction Automatique des Données

Depuis des Fichiers Excel

import pandas as pd
from pathlib import Path

def extract_excel_data(folder_path: str) -> pd.DataFrame:
    """Extrait et consolide tous les fichiers Excel d'un dossier"""

    folder = Path(folder_path)
    all_files = folder.glob("*.xlsx")

    dataframes = []
    for file in all_files:
        df = pd.read_excel(file, sheet_name="Data")
        df['source_file'] = file.name
        dataframes.append(df)

    # Consolider tous les fichiers
    consolidated = pd.concat(dataframes, ignore_index=True)

    return consolidated

# Utilisation
data = extract_excel_data("./data/weekly_reports/")

Gain : Au lieu de copier-coller manuellement, vous consolidez automatiquement tous les fichiers en 2 secondes.

Depuis une API

import requests
import pandas as pd

def extract_api_data(api_url: str, api_key: str) -> pd.DataFrame:
    """Extrait les données depuis une API REST"""

    headers = {"Authorization": f"Bearer {api_key}"}
    response = requests.get(api_url, headers=headers)

    if response.status_code == 200:
        data = response.json()
        df = pd.DataFrame(data['results'])
        return df
    else:
        raise Exception(f"API Error: {response.status_code}")

# Utilisation
sales_data = extract_api_data(
    api_url="https://api.example.com/sales",
    api_key="your_api_key"
)

Depuis une Base de Données

import duckdb

def extract_database_data(db_path: str, query: str) -> pd.DataFrame:
    """Extrait les données depuis une base DuckDB"""

    con = duckdb.connect(db_path)
    df = con.execute(query).df()
    con.close()

    return df

# Utilisation
query = """
    SELECT
        date,
        region,
        SUM(revenue) as total_revenue,
        COUNT(DISTINCT customer_id) as unique_customers
    FROM sales
    WHERE date >= CURRENT_DATE - INTERVAL '7 days'
    GROUP BY date, region
    ORDER BY date DESC
"""

weekly_sales = extract_database_data("./data/sales.duckdb", query)

Gain : Connexion directe aux sources de données, pas de fichier intermédiaire.

Étape 2 : Transformation et Nettoyage

def clean_and_transform(df: pd.DataFrame) -> pd.DataFrame:
    """Nettoie et transforme les données"""

    # 1. Supprimer les doublons
    df = df.drop_duplicates()

    # 2. Gérer les valeurs manquantes
    df['revenue'] = df['revenue'].fillna(0)

    # 3. Corriger les types de données
    df['date'] = pd.to_datetime(df['date'])

    # 4. Créer des colonnes calculées
    df['week'] = df['date'].dt.isocalendar().week
    df['month'] = df['date'].dt.month
    df['revenue_per_customer'] = df['revenue'] / df['customer_count']

    # 5. Filtrer les données aberrantes
    # Supprimer les revenus négatifs (erreurs de saisie)
    df = df[df['revenue'] >= 0]

    return df

# Utilisation
cleaned_data = clean_and_transform(data)

Gain : Nettoyage systématique et reproductible, pas d'oubli.

Étape 3 : Analyse et KPIs

def calculate_kpis(df: pd.DataFrame) -> dict:
    """Calcule les indicateurs clés de performance"""

    kpis = {
        # Revenus
        'total_revenue': df['revenue'].sum(),
        'avg_revenue_per_day': df.groupby('date')['revenue'].sum().mean(),

        # Clients
        'total_customers': df['customer_id'].nunique(),
        'new_customers': df[df['is_new_customer'] == True].shape[0],

        # Croissance
        'revenue_growth': calculate_growth(df, metric='revenue'),
        'customer_growth': calculate_growth(df, metric='customer_id'),

        # Performance par région
        'top_region': df.groupby('region')['revenue'].sum().idxmax(),
        'worst_region': df.groupby('region')['revenue'].sum().idxmin(),
    }

    return kpis

def calculate_growth(df: pd.DataFrame, metric: str) -> float:
    """Calcule le taux de croissance semaine N vs N-1"""

    current_week = df['week'].max()
    previous_week = current_week - 1

    current_value = df[df['week'] == current_week][metric].sum()
    previous_value = df[df['week'] == previous_week][metric].sum()

    if previous_value > 0:
        growth = ((current_value - previous_value) / previous_value) * 100
    else:
        growth = 0

    return round(growth, 2)

# Utilisation
kpis = calculate_kpis(cleaned_data)

print(f"Chiffre d'affaires : {kpis['total_revenue']:,.0f}€")
print(f"Croissance : {kpis['revenue_growth']:+.1f}%")
print(f"Meilleure région : {kpis['top_region']}")

Gain : KPIs calculés en millisecondes avec 0% d'erreur de calcul.

Étape 4 : Visualisations Automatiques

import matplotlib.pyplot as plt
import seaborn as sns
from datetime import datetime

def create_report_charts(df: pd.DataFrame, output_folder: str = "./reports"):
    """Génère tous les graphiques du rapport"""

    # Style professionnel
    sns.set_style("whitegrid")
    plt.rcParams['figure.figsize'] = (12, 6)

    # 1. Évolution du CA par jour
    fig, ax = plt.subplots()
    daily_revenue = df.groupby('date')['revenue'].sum()
    ax.plot(daily_revenue.index, daily_revenue.values, marker='o', linewidth=2)
    ax.set_title("Évolution du chiffre d'affaires - 7 derniers jours", fontsize=14, fontweight='bold')
    ax.set_xlabel("Date")
    ax.set_ylabel("Chiffre d'affaires (€)")
    ax.grid(True, alpha=0.3)
    plt.xticks(rotation=45)
    plt.tight_layout()
    plt.savefig(f"{output_folder}/revenue_trend.png", dpi=300)
    plt.close()

    # 2. Répartition par région
    fig, ax = plt.subplots()
    region_revenue = df.groupby('region')['revenue'].sum().sort_values(ascending=False)
    colors = sns.color_palette("viridis", len(region_revenue))
    ax.bar(region_revenue.index, region_revenue.values, color=colors)
    ax.set_title("Chiffre d'affaires par région", fontsize=14, fontweight='bold')
    ax.set_xlabel("Région")
    ax.set_ylabel("Chiffre d'affaires (€)")
    plt.xticks(rotation=45, ha='right')
    plt.tight_layout()
    plt.savefig(f"{output_folder}/revenue_by_region.png", dpi=300)
    plt.close()

    # 3. Top 10 produits
    fig, ax = plt.subplots()
    top_products = df.groupby('product')['revenue'].sum().nlargest(10).sort_values()
    ax.barh(top_products.index, top_products.values, color='steelblue')
    ax.set_title("Top 10 Produits - CA Hebdomadaire", fontsize=14, fontweight='bold')
    ax.set_xlabel("Chiffre d'affaires (€)")
    plt.tight_layout()
    plt.savefig(f"{output_folder}/top_products.png", dpi=300)
    plt.close()

    print(f"✅ Graphiques sauvegardés dans {output_folder}/")

# Utilisation
create_report_charts(cleaned_data, output_folder="./reports/2024-09-22")

Gain : Graphiques générés automatiquement avec un style cohérent, pas de mise en forme manuelle.

Étape 5 : Génération du Rapport PDF

from fpdf import FPDF
from datetime import datetime

class WeeklyReport(FPDF):
    """Template PDF pour rapport hebdomadaire"""

    def header(self):
        self.set_font('Arial', 'B', 16)
        self.cell(0, 10, 'Rapport Hebdomadaire - Ventes', 0, 1, 'C')
        self.set_font('Arial', '', 10)
        self.cell(0, 10, f"Généré le {datetime.now().strftime('%d/%m/%Y à %H:%M')}", 0, 1, 'C')
        self.ln(10)

    def footer(self):
        self.set_y(-15)
        self.set_font('Arial', 'I', 8)
        self.cell(0, 10, f'Page {self.page_no()}', 0, 0, 'C')

def generate_pdf_report(kpis: dict, charts_folder: str, output_path: str):
    """Génère un rapport PDF complet"""

    pdf = WeeklyReport()
    pdf.add_page()

    # Section KPIs
    pdf.set_font('Arial', 'B', 14)
    pdf.cell(0, 10, 'Indicateurs Clés', 0, 1)
    pdf.ln(5)

    pdf.set_font('Arial', '', 12)
    pdf.cell(0, 8, f"Chiffre d'affaires : {kpis['total_revenue']:,.0f} €", 0, 1)
    pdf.cell(0, 8, f"Croissance vs semaine précédente : {kpis['revenue_growth']:+.1f}%", 0, 1)
    pdf.cell(0, 8, f"Nombre de clients : {kpis['total_customers']:,}", 0, 1)
    pdf.cell(0, 8, f"Nouveaux clients : {kpis['new_customers']:,}", 0, 1)
    pdf.ln(10)

    # Section Graphiques
    pdf.set_font('Arial', 'B', 14)
    pdf.cell(0, 10, 'Analyses Visuelles', 0, 1)
    pdf.ln(5)

    # Ajouter les images
    pdf.image(f"{charts_folder}/revenue_trend.png", x=10, w=190)
    pdf.add_page()
    pdf.image(f"{charts_folder}/revenue_by_region.png", x=10, w=190)
    pdf.add_page()
    pdf.image(f"{charts_folder}/top_products.png", x=10, w=190)

    # Sauvegarder
    pdf.output(output_path)
    print(f"✅ Rapport PDF généré : {output_path}")

# Utilisation
generate_pdf_report(
    kpis=kpis,
    charts_folder="./reports/2024-09-22",
    output_path="./reports/weekly_report_2024-09-22.pdf"
)

Gain : Rapport PDF professionnel généré automatiquement, format cohérent chaque semaine.

Étape 6 : Diffusion Automatique par Email

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders

def send_report_email(
    kpis: dict,
    pdf_path: str,
    recipients: list,
    smtp_server: str = "smtp.gmail.com",
    smtp_port: int = 587,
    sender_email: str = "your_email@example.com",
    sender_password: str = "your_app_password"
):
    """Envoie le rapport par email avec pièce jointe"""

    # Créer le message
    msg = MIMEMultipart()
    msg['From'] = sender_email
    msg['To'] = ", ".join(recipients)
    msg['Subject'] = f"Rapport Hebdomadaire - Semaine du {datetime.now().strftime('%d/%m/%Y')}"

    # Corps de l'email avec KPIs en résumé
    body = f"""
    Bonjour,

    Voici le rapport hebdomadaire des ventes.

    📊 Indicateurs Clés :
    - Chiffre d'affaires : {kpis['total_revenue']:,.0f}
    - Croissance : {kpis['revenue_growth']:+.1f}%
    - Clients : {kpis['total_customers']:,}
    - Nouveaux clients : {kpis['new_customers']:,}
    - Meilleure région : {kpis['top_region']}

    Le rapport complet est en pièce jointe.

    Cordialement,
    L'équipe Data
    """

    msg.attach(MIMEText(body, 'plain'))

    # Attacher le PDF
    with open(pdf_path, "rb") as attachment:
        part = MIMEBase('application', 'octet-stream')
        part.set_payload(attachment.read())
        encoders.encode_base64(part)
        part.add_header(
            'Content-Disposition',
            f'attachment; filename= {Path(pdf_path).name}',
        )
        msg.attach(part)

    # Envoyer l'email
    with smtplib.SMTP(smtp_server, smtp_port) as server:
        server.starttls()
        server.login(sender_email, sender_password)
        server.send_message(msg)

    print(f"✅ Email envoyé à {len(recipients)} destinataires")

# Utilisation
recipients = [
    "manager@example.com",
    "team@example.com",
    "sales@example.com"
]

send_report_email(
    kpis=kpis,
    pdf_path="./reports/weekly_report_2024-09-22.pdf",
    recipients=recipients,
    sender_email="data.reports@example.com",
    sender_password="your_secure_app_password"
)

Gain : Diffusion automatique le lundi à 9h, plus besoin de penser à envoyer manuellement.

Projet Complet : Script d'Automatisation

Voici le script final qui orchestre tout :

# weekly_report_automation.py
import pandas as pd
from pathlib import Path
from datetime import datetime
from loguru import logger

# Configuration
logger.add("reports.log", rotation="1 week")

def main():
    """Pipeline complet d'automatisation du rapport hebdomadaire"""

    logger.info("🚀 Démarrage du pipeline de reporting automatisé")

    try:
        # 1. Extraction
        logger.info("📥 Extraction des données...")
        data = extract_excel_data("./data/weekly_reports/")
        logger.success(f"✅ {len(data)} lignes extraites")

        # 2. Transformation
        logger.info("🔧 Nettoyage et transformation...")
        cleaned_data = clean_and_transform(data)
        logger.success(f"✅ {len(cleaned_data)} lignes après nettoyage")

        # 3. Analyse
        logger.info("📊 Calcul des KPIs...")
        kpis = calculate_kpis(cleaned_data)
        logger.success("✅ KPIs calculés")

        # 4. Visualisations
        logger.info("📈 Génération des graphiques...")
        today = datetime.now().strftime("%Y-%m-%d")
        charts_folder = f"./reports/{today}"
        Path(charts_folder).mkdir(parents=True, exist_ok=True)
        create_report_charts(cleaned_data, charts_folder)
        logger.success("✅ Graphiques générés")

        # 5. Rapport PDF
        logger.info("📄 Génération du PDF...")
        pdf_path = f"./reports/weekly_report_{today}.pdf"
        generate_pdf_report(kpis, charts_folder, pdf_path)
        logger.success("✅ PDF généré")

        # 6. Diffusion
        logger.info("📧 Envoi du rapport...")
        recipients = ["manager@example.com", "team@example.com"]
        send_report_email(kpis, pdf_path, recipients)
        logger.success("✅ Rapport envoyé")

        logger.success("🎉 Pipeline terminé avec succès")

    except Exception as e:
        logger.error(f"❌ Erreur : {e}")
        raise

if __name__ == "__main__":
    main()

Automatisation avec Cron (Linux/Mac) ou Task Scheduler (Windows)

Linux/Mac : Crontab

# Éditer le crontab
crontab -e

# Ajouter cette ligne pour exécuter chaque lundi à 8h00
0 8 * * 1 /usr/bin/python3 /path/to/weekly_report_automation.py

Windows : Task Scheduler

# Créer une tâche planifiée
schtasks /create /tn "Weekly Report" /tr "python C:\path\to\weekly_report_automation.py" /sc weekly /d MON /st 08:00

Résultat : Le lundi matin à 8h, le rapport se génère et s'envoie automatiquement. Vous arrivez au bureau à 9h, tout est déjà prêt.

ROI : Le Calcul Qui Justifie l'Investissement

Investissement Initial

  • Temps de développement : 8 heures (1 journée)
  • Temps de test et ajustements : 2 heures
  • Total : 10 heures @ 45€/h = 450€

Gains Annuels

Sans automatisation :

  • 3 heures/semaine × 50 semaines = 150 heures/an
  • 150 heures × 45€ = 6 750€/an

Avec automatisation :

  • 15 minutes/semaine × 50 semaines = 12,5 heures/an
  • 12,5 heures × 45€ = 562,5€/an

Économie nette : 6 750€ - 562,5€ = 6 187,5€/an

ROI : (6 187,5€ - 450€) / 450€ = 1 275%

Retour sur investissement : 3 semaines

Et ce n'est que pour UN rapport. Si vous automatisez 3 rapports différents, multipliez ces chiffres par 3.

🚀 Maîtrisez l'Automatisation avec Python

L'automatisation de rapports n'est qu'un début. Imaginez ce que vous pourriez faire en automatisant tous vos workflows data.

Dans ma formation Streamlit Unleashed, je vous montre comment créer des dashboards automatisés interactifs :

Ce que vous allez apprendre :

Automatisation Complète

  • Pipelines ETL automatisés
  • Génération de rapports programmée
  • Dashboards qui se mettent à jour seuls

Dashboards Streamlit Interactifs

  • Remplacement des rapports statiques par des apps web
  • Filtres dynamiques en temps réel
  • Exportation PDF automatique

Intégration Production

  • Déploiement cloud (Streamlit Cloud, AWS)
  • Alertes automatiques sur anomalies
  • Logging et monitoring

Projets Concrets

  • Dashboard de ventes temps réel
  • App de reporting automatisée
  • Système d'alertes intelligentes

🚀 Formation Streamlit Unleashed

Automatisez vos analyses et créez des dashboards professionnels

20 heures de contenu pratique • Projets concrets • Accès à vie

297€ 197€

Découvrir la Formation →

Conclusion : Libérez Votre Temps

Chaque heure passée à créer manuellement un rapport est une heure perdue pour :

  • Analyser en profondeur vos données
  • Trouver des insights actionnables
  • Développer de nouveaux projets
  • Apprendre de nouvelles compétences

En 2025, ne pas automatiser ses rapports, c'est gaspiller son potentiel.

L'automatisation n'est pas réservée aux ingénieurs. Avec Python et les bons outils, n'importe quel analyste peut créer des pipelines robustes en quelques heures.

La question n'est plus "Est-ce que je dois automatiser ?" mais "Combien de temps vais-je encore perdre avant d'automatiser ?".


Prêt à automatiser vos analyses ?

👉 Découvrez Streamlit Unleashed

Envie d'aller plus loin ? Rejoignez ma newsletter DataGyver où je partage chaque mois des scripts d'automatisation, case studies et templates prêts à l'emploi.

Des questions sur l'automatisation ? Contactez-moi sur LinkedIn où 25K+ professionnels partagent leurs tips d'automatisation quotidiennement.

Livre Business Intelligence avec Python

📚 Approfondir avec mon livre

"Business Intelligence avec Python" - Le guide complet pour maîtriser l'analyse de données

Voir sur Amazon →

📬 Ne manquez rien de l'actualité data

Rejoignez +1000 professionnels qui reçoivent chaque semaine mes analyses, conseils et découvertes data.

S'abonner gratuitement
Prochaine révision : Trimestre prochain