Initial commit
This commit is contained in:
commit
97f0793f0d
4 changed files with 528 additions and 0 deletions
71
.gitignore
vendored
Normal file
71
.gitignore
vendored
Normal file
|
|
@ -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
|
||||||
185
README.md
Normal file
185
README.md
Normal file
|
|
@ -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 <percorso_file_excel>
|
||||||
|
```
|
||||||
|
|
||||||
|
**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.
|
||||||
271
fixgaiaexcel.py
Normal file
271
fixgaiaexcel.py
Normal file
|
|
@ -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 <percorso_file_excel>")
|
||||||
|
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()
|
||||||
1
requirements.txt
Normal file
1
requirements.txt
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
openpyxl>=3.0.0
|
||||||
Loading…
Add table
Add a link
Reference in a new issue