COP_Comparator / generate_excel.py
Qdonnars's picture
Tableau de bord COP Régionales — 4 régions, 42 KPIs
ce88bcc
#!/usr/bin/env python3
"""
Extraction des KPIs des feuilles de route COP régionales
et génération d'un fichier Excel de comparaison.
Inclut les 4 régions : Grand Est, Occitanie, AURA, Normandie
avec numéros de pages sources.
"""
from openpyxl import Workbook
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
from openpyxl.utils import get_column_letter
wb = Workbook()
# ============================================================
# Couleurs & styles gouvernementaux
# ============================================================
BLEU_MARIANNE = "000091"
BLEU_CLAIR = "E3E3FD"
GRIS_CLAIR = "F5F5F5"
BLANC = "FFFFFF"
NOIR = "161616"
header_font = Font(name="Marianne", bold=True, color=BLANC, size=11)
header_fill = PatternFill(start_color=BLEU_MARIANNE, end_color=BLEU_MARIANNE, fill_type="solid")
category_font = Font(name="Marianne", bold=True, color=BLEU_MARIANNE, size=11)
category_fill = PatternFill(start_color=BLEU_CLAIR, end_color=BLEU_CLAIR, fill_type="solid")
normal_font = Font(name="Marianne", size=10, color=NOIR)
na_font = Font(name="Marianne", size=10, color="929292", italic=True)
link_font = Font(name="Marianne", size=8, color="000091", italic=True)
thin_border = Border(
left=Side(style="thin", color="CCCCCC"),
right=Side(style="thin", color="CCCCCC"),
top=Side(style="thin", color="CCCCCC"),
bottom=Side(style="thin", color="CCCCCC"),
)
wrap_alignment = Alignment(wrap_text=True, vertical="top")
# ============================================================
# URLs des documents sources
# ============================================================
URLS = {
"grand_est": "https://www.prefectures-regions.gouv.fr/grand-est/grand-est/irecontenu/telechargement/120569/895203/file/20240927_Grand_Est_Planification_ecologique_feuille_de_route.pdf",
"occitanie": "https://www.prefectures-regions.gouv.fr/occitanie/irecontenu/telechargement/123908/917834/file/feuille_de_route_cop.pdf",
"aura": "https://www.prefectures-regions.gouv.fr/content/download/133679/980081/version/1/file/COP-AURA_202512-feuilleroute+COP+regional.pdf",
"normandie": "https://www.prefectures-regions.gouv.fr/normandie/irecontenu/telechargement/122983/912028/file/COP%20Normandie_FDR%20vf.pdf",
}
# ============================================================
# Données KPIs extraites des PDFs (avec pages sources)
# ============================================================
kpis = [
# --- TRANSPORTS & MOBILITÉS ---
{
"categorie": "Transports & Mobilités",
"indicateur": "Réduction émissions GES transports",
"unite": "ktCO2eq",
"grand_est": "25% des leviers régionaux",
"grand_est_page": 16,
"occitanie": "-4 967 ktCO2eq d'ici 2030 vs 2019",
"occitanie_page": 21,
"aura": "-30% émissions (14,3 MtCO2eq en 2022)",
"aura_page": 15,
"normandie": "6% de l'effort national GES, enjeux forts transport",
"normandie_page": 3,
},
{
"categorie": "Transports & Mobilités",
"indicateur": "Usage du vélo / mobilité active",
"unite": "% déplacements",
"grand_est": "Non chiffré spécifiquement",
"grand_est_page": 17,
"occitanie": "×4 usage vélo → 12% des déplacements d'ici 2030",
"occitanie_page": 22,
"aura": "Développer mobilité active (pas de cible vélo seul)",
"aura_page": 15,
"normandie": "Voiries cyclables + schéma directeur vélo + tourisme à vélo",
"normandie_page": 8,
},
{
"categorie": "Transports & Mobilités",
"indicateur": "Aménagements cyclables",
"unite": "km",
"grand_est": "Non chiffré",
"grand_est_page": 17,
"occitanie": "7 499 km sécurisés d'ici 2026",
"occitanie_page": 22,
"aura": "Non chiffré spécifiquement",
"aura_page": 15,
"normandie": "Schéma directeur vélo (non chiffré)",
"normandie_page": 8,
},
{
"categorie": "Transports & Mobilités",
"indicateur": "Véhicules électriques",
"unite": "multiplicateur / %",
"grand_est": "1/6 des véhicules (~460 000 VE)",
"grand_est_page": 16,
"occitanie": "×14 le nombre de VE (2021-2030)",
"occitanie_page": 26,
"aura": "15% de VE légers en 2030",
"aura_page": 15,
"normandie": "Décarboner flottes employeurs",
"normandie_page": 8,
},
{
"categorie": "Transports & Mobilités",
"indicateur": "Points de recharge VE",
"unite": "nombre",
"grand_est": "100% territoire maillé",
"grand_est_page": 13,
"occitanie": "17 701 points de recharge d'ici 2026",
"occitanie_page": 26,
"aura": "Non chiffré spécifiquement",
"aura_page": 15,
"normandie": "Infrastructure recharge (électrique, H2, BioGNV)",
"normandie_page": 9,
},
{
"categorie": "Transports & Mobilités",
"indicateur": "Report modal fret (rail & fleuve)",
"unite": "%",
"grand_est": "25% de report modal fret",
"grand_est_page": 16,
"occitanie": "×2 part ferroviaire ; +50% fluvial",
"occitanie_page": 107,
"aura": "-10% transport routier marchandises",
"aura_page": 15,
"normandie": "Multimodalité, ferroutage, réseau ferroviaire/fluvial",
"normandie_page": 8,
},
{
"categorie": "Transports & Mobilités",
"indicateur": "Bus et cars décarbonés",
"unite": "% ou nombre",
"grand_est": "~900 bus/cars décarbonés en 2030",
"grand_est_page": 16,
"occitanie": "15% flotte décarbonée en 2030",
"occitanie_page": 107,
"aura": "Non chiffré spécifiquement",
"aura_page": 15,
"normandie": "Décarboner flottes bus et cars (Bio GNV, H2…)",
"normandie_page": 8,
},
{
"categorie": "Transports & Mobilités",
"indicateur": "Réduction usage voiture individuelle",
"unite": "%",
"grand_est": "-5% conso au 100 des thermiques",
"grand_est_page": 16,
"occitanie": "-4% distance/voiture/an",
"occitanie_page": 107,
"aura": "-15% voiture ; -10% déplacements",
"aura_page": 15,
"normandie": "Covoiturage + télétravail + réduction dépl. domicile-travail",
"normandie_page": 8,
},
# --- BÂTIMENT ---
{
"categorie": "Bâtiment : Résidentiel & Tertiaire",
"indicateur": "Réduction conso énergétique résidentiel",
"unite": "% vs 2019",
"grand_est": "-15%",
"grand_est_page": 18,
"occitanie": "-15% vs 2019",
"occitanie_page": 31,
"aura": "-15% vs 2019",
"aura_page": 16,
"normandie": "Mobilisation SPRH + rénovations performantes",
"normandie_page": 10,
},
{
"categorie": "Bâtiment : Résidentiel & Tertiaire",
"indicateur": "Réduction conso énergétique tertiaire",
"unite": "% vs réf.",
"grand_est": "-33%",
"grand_est_page": 18,
"occitanie": "-40% vs 2010",
"occitanie_page": 31,
"aura": "-30% vs 2019",
"aura_page": 16,
"normandie": "Plate-forme OPERAT + sobriété tertiaire",
"normandie_page": 10,
},
{
"categorie": "Bâtiment : Résidentiel & Tertiaire",
"indicateur": "Passoires thermiques (F et G)",
"unite": "% ou logements/an",
"grand_est": "Non chiffré spécifiquement",
"grand_est_page": 18,
"occitanie": "-60% passoires vs 2021 (178 000 RP)",
"occitanie_page": 31,
"aura": "80 000 logements rénovés/an",
"aura_page": 16,
"normandie": "SPRH ANAH + rénovations performantes",
"normandie_page": 10,
},
{
"categorie": "Bâtiment : Résidentiel & Tertiaire",
"indicateur": "Remplacement chaudières fioul",
"unite": "% vs 2019",
"grand_est": "÷4 résidences avec chaudière fioul",
"grand_est_page": 18,
"occitanie": "-75% chaudières fioul résidentiel",
"occitanie_page": 108,
"aura": "Non chiffré spécifiquement",
"aura_page": 16,
"normandie": "Incitation aux énergies décarbonées",
"normandie_page": 11,
},
{
"categorie": "Bâtiment : Résidentiel & Tertiaire",
"indicateur": "Remplacement chaudières gaz",
"unite": "% vs 2019",
"grand_est": "-25% résidences chaudière gaz",
"grand_est_page": 18,
"occitanie": "-20% chaudières gaz résidentiel",
"occitanie_page": 108,
"aura": "Non chiffré (gaz = 60% émissions bât.)",
"aura_page": 16,
"normandie": "Non chiffré",
"normandie_page": None,
},
# --- ÉNERGIE ---
{
"categorie": "Énergie & Économie circulaire",
"indicateur": "Production ENR - Éolien terrestre",
"unite": "TWh",
"grand_est": "2ᵉ région éolienne (non chiffré)",
"grand_est_page": 22,
"occitanie": "×2,5 (3,2 → 7,9 TWh) d'ici 2031",
"occitanie_page": 108,
"aura": "+50% élec. renouvelable d'ici 2030",
"aura_page": 18,
"normandie": "Zones d'accélération EnR",
"normandie_page": 15,
},
{
"categorie": "Énergie & Économie circulaire",
"indicateur": "Production ENR - Photovoltaïque",
"unite": "TWh / MW",
"grand_est": "Non chiffré",
"grand_est_page": 22,
"occitanie": "×2 PV (4,1 → 9 TWh) ; 7 000 MW",
"occitanie_page": 108,
"aura": "Inclus dans +50% élec. renouvelable",
"aura_page": 18,
"normandie": "Structurer filière PV + autoconsommation",
"normandie_page": 16,
},
{
"categorie": "Énergie & Économie circulaire",
"indicateur": "Production biogaz / biométhane",
"unite": "multiplicateur",
"grand_est": "Non chiffré",
"grand_est_page": 22,
"occitanie": "×10 (0,3 → 3 TWh/an) d'ici 2031",
"occitanie_page": 108,
"aura": "Non chiffré",
"aura_page": 18,
"normandie": "Métha'Normandie + gaz verts",
"normandie_page": 16,
},
{
"categorie": "Énergie & Économie circulaire",
"indicateur": "Chaleur renouvelable",
"unite": "TWh",
"grand_est": "Synergies chaleur fatale",
"grand_est_page": 23,
"occitanie": "×2 à ×4 chaleur livrée",
"occitanie_page": 108,
"aura": ">30 TWh chaleur renouvelable",
"aura_page": 18,
"normandie": "Récupération chaleur fatale industrielle",
"normandie_page": 17,
},
{
"categorie": "Énergie & Économie circulaire",
"indicateur": "ENR citoyens / participatifs",
"unite": "nombre",
"grand_est": "500 GWh ; ×3 capacité EnR citoyens",
"grand_est_page": 23,
"occitanie": "100 000 citoyens ; 500 projets",
"occitanie_page": 39,
"aura": "Non chiffré",
"aura_page": None,
"normandie": "Financements participatifs (Kiwai Normandie)",
"normandie_page": 16,
},
# --- INDUSTRIE ---
{
"categorie": "Industrie & Emploi",
"indicateur": "Réduction émissions industrielles",
"unite": "% ou ktCO2eq",
"grand_est": "27% effort régional ; 14/50 sites",
"grand_est_page": 24,
"occitanie": "-31% (3 446 → 2 390 ktCO2eq)",
"occitanie_page": 108,
"aura": "-40% pour 90 sites",
"aura_page": 17,
"normandie": "Programme ZIBAC-SOCRATE + PACTE Industrie",
"normandie_page": 15,
},
{
"categorie": "Industrie & Emploi",
"indicateur": "Décarbonation gros émetteurs",
"unite": "%",
"grand_est": "14 gros sites accompagnés",
"grand_est_page": 25,
"occitanie": "-40% GES des 70 plus gros",
"occitanie_page": 43,
"aura": "-40% GES des 90 sites",
"aura_page": 17,
"normandie": "Feuilles de route décarbonation gros émetteurs",
"normandie_page": 17,
},
{
"categorie": "Industrie & Emploi",
"indicateur": "Décarbonation PME / industrie diffuse",
"unite": "%",
"grand_est": "Accompagner toutes les entreprises",
"grand_est_page": 25,
"occitanie": "-30% GES secteur diffus",
"occitanie_page": 46,
"aura": "100% mobilisation TPE/PME/ETI",
"aura_page": 17,
"normandie": "Amplifier sensibilisation PME + dispositifs",
"normandie_page": 17,
},
# --- BIODIVERSITÉ ---
{
"categorie": "Biodiversité, Eau & Sols",
"indicateur": "Réduction prélèvements eau",
"unite": "% vs réf.",
"grand_est": "-10%",
"grand_est_page": 14,
"occitanie": "-10% vs 2022",
"occitanie_page": 109,
"aura": "-10% d'ici 2030",
"aura_page": 14,
"normandie": "Études volumes prélevables + eaux non conventionnelles",
"normandie_page": 12,
},
{
"categorie": "Biodiversité, Eau & Sols",
"indicateur": "Réduction artificialisation (ZAN)",
"unite": "% ou ha",
"grand_est": "÷2 conso ENAF d'ici 2031",
"grand_est_page": 14,
"occitanie": "÷2 (max 14 000 ha sur 2021-2030)",
"occitanie_page": 34,
"aura": "-50% conso ENAF ; 1 000 ha désimperméabilisés",
"aura_page": 14,
"normandie": "Désimperméabilisation + renaturation friches",
"normandie_page": 14,
},
{
"categorie": "Biodiversité, Eau & Sols",
"indicateur": "Zones humides / tourbières",
"unite": "ha / opérations",
"grand_est": "10 opérations ; 1 000 ha/an",
"grand_est_page": 29,
"occitanie": "Non chiffré",
"occitanie_page": None,
"aura": "Non chiffré",
"aura_page": None,
"normandie": "Programme régional restauration tourbières",
"normandie_page": 12,
},
{
"categorie": "Biodiversité, Eau & Sols",
"indicateur": "Continuités écologiques - Points noirs",
"unite": "% résorbés",
"grand_est": "100% résorbés d'ici 2030",
"grand_est_page": 30,
"occitanie": "Identifier/résorber d'ici 2030",
"occitanie_page": 110,
"aura": "100% de résorption d'ici 2030",
"aura_page": 14,
"normandie": "Trajectoire écologique habitats naturels",
"normandie_page": 12,
},
# --- AGRICULTURE ---
{
"categorie": "Agriculture, Forêt & Alimentation",
"indicateur": "Plantation d'arbres",
"unite": "millions d'arbres",
"grand_est": "89 millions d'ici 2026",
"grand_est_page": 20,
"occitanie": "11 millions d'ici 2026",
"occitanie_page": 109,
"aura": "Non chiffré",
"aura_page": None,
"normandie": "Renouvellement peuplements forestiers fragilisés",
"normandie_page": 13,
},
{
"categorie": "Agriculture, Forêt & Alimentation",
"indicateur": "Linéaire de haies / bocage",
"unite": "km",
"grand_est": "+4 000 km de haies vs 2019",
"grand_est_page": 20,
"occitanie": "Non chiffré",
"occitanie_page": None,
"aura": "Non chiffré",
"aura_page": None,
"normandie": "Plans d'actions plantation + maintien bocage",
"normandie_page": 12,
},
{
"categorie": "Agriculture, Forêt & Alimentation",
"indicateur": "Surfaces en légumineuses",
"unite": "ha",
"grand_est": "×2 les surfaces",
"grand_est_page": 20,
"occitanie": "+100 000 ha d'ici 2030",
"occitanie_page": 109,
"aura": "Non traité",
"aura_page": None,
"normandie": "Progresser en légumineuses (alimentation animale et humaine)",
"normandie_page": 18,
},
# --- DÉCHETS ---
{
"categorie": "Déchets",
"indicateur": "Réduction déchets ménagers (DMA)",
"unite": "kg/hab/an ou %",
"grand_est": "-85 kg/hab/an vs 2019",
"grand_est_page": 22,
"occitanie": "-108 kg/hab vs 2010",
"occitanie_page": 108,
"aura": "Zéro enfouissement d'ici 2030",
"aura_page": 19,
"normandie": "Prévention + consommation responsable + arrêt collecte déchets verts PAP",
"normandie_page": 20,
},
{
"categorie": "Déchets",
"indicateur": "Valorisation des déchets",
"unite": "kg/hab/an ou %",
"grand_est": "+68 kg/hab/an valorisés vs 2019",
"grand_est_page": 22,
"occitanie": "57% valorisation matière ; 90% bouteilles plastiques",
"occitanie_page": 108,
"aura": "Développer recyclage et réemploi",
"aura_page": 19,
"normandie": "Valorisation BTP + textiles >60% + déchets organiques",
"normandie_page": 20,
},
{
"categorie": "Déchets",
"indicateur": "Tarification incitative",
"unite": "habitants ou %",
"grand_est": "Non chiffré",
"grand_est_page": None,
"occitanie": "2,1M hab. en tarif. incitative d'ici 2031",
"occitanie_page": 108,
"aura": "Non chiffré",
"aura_page": None,
"normandie": "Généraliser la redevance incitative",
"normandie_page": 20,
},
# --- EMPLOI ---
{
"categorie": "Emploi & Formation",
"indicateur": "Professionnels rénovation / BTP",
"unite": "nombre",
"grand_est": "Augmenter nombre RGE",
"grand_est_page": 25,
"occitanie": "Non chiffré",
"occitanie_page": None,
"aura": "Former +2,8M personnes (national)",
"aura_page": 21,
"normandie": "Montée en compétences BTP + rénovateurs BBC + RGE",
"normandie_page": 10,
},
{
"categorie": "Emploi & Formation",
"indicateur": "Accompagnement entreprises transition",
"unite": "nombre",
"grand_est": "Non chiffré",
"grand_est_page": None,
"occitanie": "2 000 entreprises (2025-2027)",
"occitanie_page": 87,
"aura": "100% mobilisation TPE/PME/ETI",
"aura_page": 17,
"normandie": "Identification évolutions métiers + formation continue",
"normandie_page": 24,
},
]
# ============================================================
# Création de la feuille Excel
# ============================================================
ws = wb.active
ws.title = "KPIs COP Régionales"
# En-têtes
headers = ["Catégorie", "Indicateur / KPI", "Unité",
"Grand Est", "Page GE",
"Occitanie", "Page Occ.",
"Auvergne-Rhône-Alpes", "Page AURA",
"Normandie", "Page Norm."]
col_widths = [30, 40, 18, 45, 8, 45, 8, 45, 8, 45, 8]
for col_idx, (header, width) in enumerate(zip(headers, col_widths), 1):
cell = ws.cell(row=1, column=col_idx, value=header)
cell.font = header_font
cell.fill = header_fill
cell.alignment = Alignment(wrap_text=True, vertical="center", horizontal="center")
cell.border = thin_border
ws.column_dimensions[get_column_letter(col_idx)].width = width
ws.row_dimensions[1].height = 30
# Données
current_category = ""
row = 2
for kpi in kpis:
cat = kpi["categorie"]
# Ligne catégorie si nouvelle
if cat != current_category:
if current_category != "":
row += 1 # ligne vide entre catégories
for col_idx in range(1, len(headers) + 1):
cell = ws.cell(row=row, column=col_idx)
cell.fill = category_fill
cell.border = thin_border
if col_idx == 1:
cell.value = cat
cell.font = category_font
cell.alignment = wrap_alignment
ws.row_dimensions[row].height = 25
row += 1
current_category = cat
values = [
cat,
kpi["indicateur"],
kpi["unite"],
kpi["grand_est"],
kpi.get("grand_est_page", ""),
kpi["occitanie"],
kpi.get("occitanie_page", ""),
kpi["aura"],
kpi.get("aura_page", ""),
kpi["normandie"],
kpi.get("normandie_page", ""),
]
for col_idx, val in enumerate(values, 1):
cell = ws.cell(row=row, column=col_idx, value=val if val is not None else "")
cell.border = thin_border
cell.alignment = wrap_alignment
# Page columns
if col_idx in (5, 7, 9, 11) and val:
cell.font = link_font
elif val and ("Non" in str(val) or str(val) == ""):
cell.font = na_font
else:
cell.font = normal_font
# Alternance couleurs
if row % 2 == 0:
cell.fill = PatternFill(start_color=GRIS_CLAIR, end_color=GRIS_CLAIR, fill_type="solid")
ws.row_dimensions[row].height = 50
row += 1
# Freeze panes
ws.freeze_panes = "A2"
ws.auto_filter.ref = f"A1:K{row-1}"
# ============================================================
# Feuille de métadonnées
# ============================================================
ws2 = wb.create_sheet("Sources & Métadonnées")
meta = [
["Région", "URL du document", "Pages"],
["Grand Est", URLS["grand_est"], "71 pages"],
["Occitanie", URLS["occitanie"], "116 pages"],
["Auvergne-Rhône-Alpes", URLS["aura"], "198 pages"],
["Normandie", URLS["normandie"], "31 pages — OCR Mistral (document basé sur images)"],
[],
["Note", "Les objectifs et KPIs sont extraits des documents officiels des COP régionales."],
["Note", "Les horizons temporels varient selon les régions (2030 ou 2031 principalement)."],
["Note", "Les unités et périmètres ne sont pas toujours strictement identiques entre régions."],
["Note", "Le PDF Normandie était basé sur des images : extraction via OCR Mistral (mistral-ocr-latest)."],
["Date", "Extraction réalisée en février 2025"],
]
for r, row_data in enumerate(meta, 1):
for c, val in enumerate(row_data, 1):
cell = ws2.cell(row=r, column=c, value=val)
if r == 1:
cell.font = header_font
cell.fill = header_fill
elif c == 1:
cell.font = Font(bold=True, name="Marianne", size=10)
else:
cell.font = Font(name="Marianne", size=10)
ws2.column_dimensions["A"].width = 25
ws2.column_dimensions["B"].width = 100
ws2.column_dimensions["C"].width = 50
output_path = "/home/qdonnars/projects/chat_perso/COP/KPIs_COP_Regionales.xlsx"
wb.save(output_path)
print(f"Excel sauvegardé : {output_path}")