From 97f0793f0d5e40f87fc7bf0c09070628a26a4f76 Mon Sep 17 00:00:00 2001 From: Luigi D'Acunto Date: Tue, 25 Nov 2025 00:12:26 +0100 Subject: [PATCH] Initial commit --- .gitignore | 71 +++++++++++++ README.md | 185 ++++++++++++++++++++++++++++++++ fixgaiaexcel.py | 271 +++++++++++++++++++++++++++++++++++++++++++++++ requirements.txt | 1 + 4 files changed, 528 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 fixgaiaexcel.py create mode 100644 requirements.txt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..43c1b70 --- /dev/null +++ b/.gitignore @@ -0,0 +1,71 @@ +# Python +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# Virtual Environment +venv/ +env/ +ENV/ +.venv + +# IDE +.vscode/ +.idea/ +*.swp +*.swo +*~ +.DS_Store + +# Jupyter Notebook +.ipynb_checkpoints + +# PyCharm +.idea/ + +# Excel files (dati sensibili) +*.xlsx +*.xls +*.xlsm +*.csv + +# Eccezione: permetti file Excel di esempio se necessario +# !example.xlsx + +# Directory dati +data/ +output/ +backup/ + +# Log files +*.log + +# OS +Thumbs.db +.DS_Store + +# Temporanei +*.tmp +*.bak +~$*.xlsx +~$*.xls diff --git a/README.md b/README.md new file mode 100644 index 0000000..15cb25c --- /dev/null +++ b/README.md @@ -0,0 +1,185 @@ +# Fix Gaia Excel - Script Python + +Script per leggere e processare file Excel con struttura specifica, cercando e estraendo dati dalla colonna "Titoli - Operativita - Data ottenimento - Data scadenza". + +## Requisiti + +- Python 3.6 o superiore +- pip (gestore pacchetti Python) + +## Installazione + +### 1. Creare l'ambiente virtuale + +```powershell +# Crea l'ambiente virtuale nella cartella venv +python -m venv venv +``` + +### 2. Attivare l'ambiente virtuale + +**Su Windows (PowerShell):** +```powershell +.\venv\Scripts\Activate.ps1 +``` + +**Su Windows (CMD):** +```cmd +.\venv\Scripts\activate.bat +``` + +**Su Linux/macOS:** +```bash +source venv/bin/activate +``` + +> **Nota:** Se ricevi un errore di policy su PowerShell, esegui: +> ```powershell +> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser +> ``` + +### 3. Installare le dipendenze + +```powershell +pip install -r requirements.txt +``` + +Se il file `requirements.txt` non esiste, installa manualmente: +```powershell +pip install openpyxl +``` + +### 4. Generare il file requirements.txt (opzionale) + +Se vuoi aggiornare il file delle dipendenze: +```powershell +pip freeze > requirements.txt +``` + +## Utilizzo + +### Eseguire lo script + +```powershell +python fixgaiaexcel.py +``` + +**Esempio:** +```powershell +python fixgaiaexcel.py data\report.xlsx +``` + +### Output + +Lo script: +1. Apre il file Excel specificato +2. Cerca la colonna con intestazione "Titoli - Operativita - Data ottenimento - Data scadenza" +3. Estrae e stampa tutti i dati sotto quella colonna +4. Mostra il conteggio totale degli elementi trovati + +### Esempio di output + +``` +Apertura file: data\report.xlsx +---------------------------------------------------------------------- +Foglio attivo: Foglio1 +Dimensioni: 150 righe x 10 colonne +---------------------------------------------------------------------- +Colonna target trovata: posizione 5 +Intestazione: Titoli - Operativita - Data ottenimento - Data scadenza +---------------------------------------------------------------------- + +Dati trovati (10 elementi): + + 1. Valore 1 + 2. Valore 2 + 3. Valore 3 + ... + +---------------------------------------------------------------------- +Totale elementi letti: 10 +``` + +## Reinstallazione su nuovo PC + +### Passaggi completi + +1. **Clona o copia il progetto** sul nuovo PC + +2. **Verifica che Python sia installato:** + ```powershell + python --version + ``` + + Se Python non è installato, scaricalo da [python.org](https://www.python.org/downloads/) + +3. **Crea l'ambiente virtuale:** + ```powershell + python -m venv venv + ``` + +4. **Attiva l'ambiente virtuale:** + ```powershell + .\venv\Scripts\Activate.ps1 + ``` + +5. **Installa le dipendenze:** + ```powershell + pip install -r requirements.txt + ``` + +6. **Verifica l'installazione:** + ```powershell + pip list + ``` + + Dovresti vedere `openpyxl` nella lista dei pacchetti installati. + +7. **Testa lo script:** + ```powershell + python fixgaiaexcel.py --help + ``` + +## Struttura del progetto + +``` +cripy/ +├── venv/ # Ambiente virtuale (NON committare in git) +├── data/ # Cartella per i file Excel +├── fixgaiaexcel.py # Script principale +├── requirements.txt # Dipendenze Python +└── README.md # Questo file +``` + +## Troubleshooting + +### Errore: "Il file non esiste" +Verifica che il percorso del file Excel sia corretto e che il file esista. + +### Errore: "Colonna non trovata" +Lo script cerca l'intestazione esatta nella prima riga. Verifica che il file Excel contenga la colonna "Titoli - Operativita - Data ottenimento - Data scadenza" nella prima riga. + +### Errore di importazione openpyxl +Assicurati di aver attivato l'ambiente virtuale e installato le dipendenze: +```powershell +.\venv\Scripts\Activate.ps1 +pip install openpyxl +``` + +## Disattivare l'ambiente virtuale + +Quando hai finito di lavorare: +```powershell +deactivate +``` + +## Note + +- L'ambiente virtuale (`venv/`) non dovrebbe essere committato in git. Aggiungi al `.gitignore`: + ``` + venv/ + __pycache__/ + *.pyc + ``` + +- Il file `requirements.txt` dovrebbe essere committato per facilitare l'installazione su altri PC. diff --git a/fixgaiaexcel.py b/fixgaiaexcel.py new file mode 100644 index 0000000..6bd62ad --- /dev/null +++ b/fixgaiaexcel.py @@ -0,0 +1,271 @@ +#!/usr/bin/env python3 +""" +Script per processare file Excel con dati di titoli e qualifiche. + +Cerca la colonna con intestazione "Titoli - Operativita - Data ottenimento - Data scadenza", +estrae le qualifiche e le date, e aggiunge due nuove colonne al file Excel: +- "Qualifica": contiene il testo della qualifica senza date +- "Data": contiene la data più vecchia trovata per ogni riga + +Il file modificato viene salvato con il suffisso "_modificato". + +Autore: Luigi D'Acunto +Data: 25 novembre 2025 +""" + +import sys +import re +import openpyxl +from pathlib import Path + + +def trova_colonna_target(sheet): + """ + Trova la colonna che contiene l'intestazione target nella prima riga. + + Args: + sheet: Il foglio Excel da analizzare + + Returns: + int: L'indice della colonna (1-based) o None se non trovata + """ + target_header = "Titoli - Operativita - Data ottenimento - Data scadenza" + + # Cerca nella prima riga + for col_idx in range(1, sheet.max_column + 1): + cell_value = sheet.cell(row=1, column=col_idx).value + if cell_value and target_header.lower() in str(cell_value).lower(): + return col_idx + + return None + + +def estrai_date(testo): + """ + Estrae tutte le date nel formato aaaa-mm-gg da una stringa. + + Args: + testo: Stringa da cui estrarre le date + + Returns: + list: Lista di date trovate nel formato aaaa-mm-gg + """ + # Pattern per date nel formato aaaa-mm-gg + pattern = r'\b\d{4}-\d{2}-\d{2}\b' + + if testo is None: + return [] + + # Converti in stringa se non lo è già + testo_str = str(testo) + + # Trova tutte le occorrenze del pattern + date_trovate = re.findall(pattern, testo_str) + + return date_trovate + + +def trova_data_piu_vecchia(date_list): + """ + Trova la data più vecchia da una lista di date, rimuovendo i doppioni. + + Args: + date_list: Lista di stringhe nel formato aaaa-mm-gg + + Returns: + str: La data più vecchia, o None se la lista è vuota + """ + if not date_list: + return None + + # Rimuove i doppioni convertendo in set e poi tornando a lista + date_uniche = list(set(date_list)) + + # Ordina le date (come stringhe funziona perché il formato aaaa-mm-gg è ordinabile) + date_uniche.sort() + + # Ritorna la prima (più vecchia) + return date_uniche[0] + + +def estrai_qualifica(testo): + """ + Estrae la qualifica (testo senza date) dalla prima riga della cella. + + Args: + testo: Stringa da cui estrarre la qualifica + + Returns: + str: La qualifica pulita senza date + """ + if testo is None: + return "" + + testo_str = str(testo) + + # Prende solo la prima riga se ci sono più righe + prima_riga = testo_str.split('\n')[0].strip() + + # Rimuove tutte le date nel formato aaaa-mm-gg + pattern = r'\b\d{4}-\d{2}-\d{2}\b' + qualifica_pulita = re.sub(pattern, '', prima_riga) + + # Rimuove spazi multipli e strisce che potrebbero rimanere + qualifica_pulita = re.sub(r'\s+', ' ', qualifica_pulita) + qualifica_pulita = re.sub(r'\s*-\s*$', '', qualifica_pulita) # Rimuove trattini finali + qualifica_pulita = qualifica_pulita.strip() + + return qualifica_pulita + + +def trova_prima_colonna_vuota(sheet): + """ + Trova la prima colonna completamente vuota nella prima riga. + + Args: + sheet: Il foglio Excel da analizzare + + Returns: + int: L'indice della prima colonna vuota (1-based) + """ + for col_idx in range(1, sheet.max_column + 2): # +2 per andare oltre l'ultima colonna + cell_value = sheet.cell(row=1, column=col_idx).value + if cell_value is None or str(cell_value).strip() == "": + return col_idx + + # Se tutte le colonne sono piene, ritorna la successiva + return sheet.max_column + 1 + + +def leggi_dati_colonna(sheet, col_idx): + """ + Legge tutti i dati dalla colonna specificata (escludendo l'intestazione). + + Args: + sheet: Il foglio Excel + col_idx: L'indice della colonna da leggere + + Returns: + list: Lista di tuple (row_idx, valore) per ogni riga con dati + """ + dati = [] + + # Legge dalla riga 2 in poi (riga 1 è l'intestazione) + for row_idx in range(2, sheet.max_row + 1): + cell_value = sheet.cell(row=row_idx, column=col_idx).value + if cell_value is not None: # Ignora celle vuote + dati.append((row_idx, cell_value)) + + return dati + + +def main(): + """Funzione principale dello script.""" + + # Controlla gli argomenti da riga di comando + if len(sys.argv) < 2: + print("Uso: python fixgaiaexcel.py ") + print("Esempio: python fixgaiaexcel.py data/report.xlsx") + sys.exit(1) + + file_path = Path(sys.argv[1]) + + # Verifica che il file esista + if not file_path.exists(): + print(f"Errore: Il file '{file_path}' non esiste") + sys.exit(1) + + # Verifica che sia un file Excel + if file_path.suffix not in ['.xlsx', '.xls', '.xlsm']: + print(f"Errore: Il file deve essere un file Excel (.xlsx, .xls, .xlsm)") + sys.exit(1) + + print(f"Apertura file: {file_path}") + print("-" * 70) + + try: + # Carica il file Excel + workbook = openpyxl.load_workbook(file_path, data_only=True) + sheet = workbook.active + + print(f"Foglio attivo: {sheet.title}") + print(f"Dimensioni: {sheet.max_row} righe x {sheet.max_column} colonne") + print("-" * 70) + + # Trova la colonna target + col_idx = trova_colonna_target(sheet) + + if col_idx is None: + print("Errore: Colonna 'Titoli - Operativita - Data ottenimento - Data scadenza' non trovata") + print("\nIntestazioni trovate nella prima riga:") + for col in range(1, sheet.max_column + 1): + header = sheet.cell(row=1, column=col).value + if header: + print(f" Colonna {col}: {header}") + sys.exit(1) + + print(f"Colonna target trovata: posizione {col_idx}") + print(f"Intestazione: {sheet.cell(row=1, column=col_idx).value}") + print("-" * 70) + + # Legge i dati dalla colonna + dati = leggi_dati_colonna(sheet, col_idx) + + print(f"\nDati trovati ({len(dati)} righe Excel):\n") + + # Trova la prima colonna vuota + col_qualifica = trova_prima_colonna_vuota(sheet) + col_data = col_qualifica + 1 + + print(f"Colonna 'Qualifica' sarà aggiunta in posizione: {col_qualifica}") + print(f"Colonna 'Data' sarà aggiunta in posizione: {col_data}") + print("-" * 70) + + # Aggiungi intestazioni + sheet.cell(row=1, column=col_qualifica).value = "Qualifica" + sheet.cell(row=1, column=col_data).value = "Data" + + # Estrae e scrive qualifica e data per ogni riga + contatore_righe_con_date = 0 + + for idx, (row_idx, valore) in enumerate(dati, start=1): + # Estrae la qualifica + qualifica = estrai_qualifica(valore) + + # Estrae le date + date_estratte = estrai_date(valore) + + if date_estratte: + # Trova la data più vecchia + data_piu_vecchia = trova_data_piu_vecchia(date_estratte) + + # Scrivi i dati nelle nuove colonne + sheet.cell(row=row_idx, column=col_qualifica).value = qualifica + sheet.cell(row=row_idx, column=col_data).value = data_piu_vecchia + + print(f" Riga {idx:3d}: Qualifica='{qualifica}' | Data={data_piu_vecchia}") + contatore_righe_con_date += 1 + else: + # Scrivi solo la qualifica se non ci sono date + sheet.cell(row=row_idx, column=col_qualifica).value = qualifica + print(f" Riga {idx:3d}: Qualifica='{qualifica}' | Nessuna data trovata") + + print("-" * 70) + print(f"Totale righe Excel processate: {len(dati)}") + print(f"Righe con date trovate: {contatore_righe_con_date}") + + # Salva il file modificato + output_path = file_path.parent / f"{file_path.stem}_modificato{file_path.suffix}" + workbook.save(output_path) + print("-" * 70) + print(f"File salvato in: {output_path}") + + workbook.close() + + except Exception as e: + print(f"Errore durante la lettura del file: {e}") + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..21ff66e --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +openpyxl>=3.0.0