#!/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 seleziona_data(date_list, piu_recente=False): """ Seleziona la data più vecchia o più recente da una lista, rimuovendo i doppioni. Args: date_list: Lista di stringhe nel formato aaaa-mm-gg piu_recente: Se True, seleziona la data più recente; altrimenti la più vecchia Returns: str: La data selezionata, 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) o l'ultima (più recente) return date_uniche[-1] if piu_recente else 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 stampa_help(): """Stampa il messaggio di aiuto completo.""" help_text = """ ╔══════════════════════════════════════════════════════════════════════════════╗ ║ FIXGAIAEXCEL - Script di aiuto ║ ╚══════════════════════════════════════════════════════════════════════════════╝ DESCRIZIONE: Script per processare file Excel contenenti dati di titoli e qualifiche. Lo script: 1. Cerca la colonna "Titoli - Operativita - Data ottenimento - Data scadenza" 2. Estrae le qualifiche (testo senza date) da ogni cella 3. Estrae tutte le date in formato aaaa-mm-gg 4. Aggiunge due nuove colonne al file Excel: - "Qualifica": testo pulito della qualifica - "Data": data selezionata secondo il criterio scelto 5. Salva un nuovo file con suffisso "_modificato" UTILIZZO: python fixgaiaexcel.py [opzioni] ESEMPI: # Estrae la data più vecchia (comportamento predefinito) python fixgaiaexcel.py "data/report.xlsx" # Estrae la data più recente python fixgaiaexcel.py "data/report.xlsx" --data-recente # Mostra questo aiuto python fixgaiaexcel.py --help OPZIONI: --data-recente, --recente Seleziona la data più RECENTE invece della più VECCHIA per ogni riga. Di default, lo script seleziona sempre la data più vecchia. --help, -h Mostra questo messaggio di aiuto ed esce. FILE DI OUTPUT: Il file originale non viene modificato. Viene creato un nuovo file con il suffisso "_modificato". Esempio: "report.xlsx" → "report_modificato.xlsx" AUTORE: Luigi D'Acunto DATA: 25 novembre 2025 ╚══════════════════════════════════════════════════════════════════════════════╝ """ print(help_text) def main(): """Funzione principale dello script.""" # Controlla se è richiesto l'help if '--help' in sys.argv or '-h' in sys.argv: stampa_help() sys.exit(0) # Controlla gli argomenti da riga di comando if len(sys.argv) < 2: print("Errore: File Excel non specificato\n") print("Uso: python fixgaiaexcel.py [opzioni]") print("\nEsempi:") print(" python fixgaiaexcel.py data/report.xlsx") print(" python fixgaiaexcel.py data/report.xlsx --data-recente") print("\nPer maggiori informazioni: python fixgaiaexcel.py --help") sys.exit(1) # Verifica se è stata richiesta la data più recente usa_data_recente = '--data-recente' in sys.argv or '--recente' in sys.argv # Filtra gli argomenti per trovare il percorso del file (escludendo i flag) file_args = [arg for arg in sys.argv[1:] if not arg.startswith('--') and not arg.startswith('-')] if not file_args: print("Errore: Nessun file specificato") print("\nPer maggiori informazioni: python fixgaiaexcel.py --help") sys.exit(1) file_path = Path(file_args[0]) # 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(f"Modalità: {'Data più RECENTE' if usa_data_recente else 'Data più VECCHIA'}") 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: # Seleziona la data (più vecchia o più recente) data_selezionata = seleziona_data(date_estratte, usa_data_recente) # 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_selezionata print(f" Riga {idx:3d}: Qualifica='{qualifica}' | Data={data_selezionata}") 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()