Exemple de code Python pour convertir des fichiers CSV en fichiers Excel (XLSX) tout en détectant automatiquement l’encodage, le délimiteur, et en formatant les colonnes contenant des dates selon un format défini dans un fichier de configuration JSON.
Ce script inclut un menu interactif, une gestion avancée des erreurs, et une journalisation détaillée pour faciliter le suivi des opérations.
Prérequis :
– Modifier le fichier csv_2_xlsx.json
pour y définir les colonnes de date et le format de date à utiliser.
– Avoir Python 3.6 ou supérieur installé et les modules ci-dessous.
pip install pandas chardet openpyxl
csv_2_xlsx.json
{ "Date_format": "%Y-%m-%d %H:%M:%S", "columns_with_date": [ "Last Logon", "Account Expiration Date", "Account Creation Date" ] }
csv_2_xlsx.py
# csv_2_xlsx.py
import os # Pour les opérations liées au système de fichiers
import logging # Pour gérer les logs d'exécution
import pandas as pd # Pour manipuler des données structurées (CSV, Excel)
import chardet # Pour détecter l'encodage des fichiers
import csv # Pour lire et écrire des fichiers CSV
import json # Pour lire et écrire des fichiers JSON
from datetime import datetime # Pour manipuler les dates et heures
import sys # Pour interagir avec le système et rediriger la sortie
# Configuration du système de logging
def configurer_logging():
"""
Configure le système de logging pour enregistrer les informations et les erreurs.
Crée un fichier de log horodaté dans un dossier 'logs'.
"""
os.makedirs('logs', exist_ok=True) # Crée le dossier 'logs' s'il n'existe pas
nom_fichier_log = f"logs/conversion_csv_{datetime.now().strftime('%Y%m%d_%H%M%S')}.log" # Nom du fichier de log
logging.basicConfig(
level=logging.INFO, # Niveau de log : INFO
format='%(asctime)s - %(levelname)s: %(message)s', # Format des messages de log
datefmt='%Y-%m-%d %H:%M:%S', # Format de la date dans les logs
handlers=[
logging.FileHandler(nom_fichier_log, encoding='utf-8'), # Enregistre les logs dans un fichier
logging.StreamHandler(sys.stdout) # Affiche les logs dans la console
]
)
def charger_configuration_json(fichier_json='csv_2_xlsx.json'):
"""
Charge la configuration du fichier JSON (colonnes de date et format de date).
Retourne les colonnes contenant des dates et le format de date.
"""
try:
with open(fichier_json, 'r', encoding='utf-8') as f: # Ouvre le fichier JSON en lecture
config = json.load(f) # Charge le contenu JSON sous forme de dictionnaire
logging.info(f"Configuration JSON chargée : {config}")
date_columns = config.get("columns_with_date", []) # Liste des colonnes contenant des dates
date_format = config.get("Date_format", "%Y-%m-%d %H:%M:%S") # Format de date
return date_columns, date_format
except Exception as e:
logging.error(f"Erreur lors du chargement du fichier JSON : {e}")
return [], "%Y-%m-%d %H:%M:%S" # Retourne des valeurs par défaut en cas d'erreur
def detecter_encodage(chemin_fichier):
"""
Détecte l'encodage d'un fichier en utilisant la bibliothèque chardet.
Retourne l'encodage détecté ou 'utf-8' par défaut en cas d'erreur.
"""
try:
with open(chemin_fichier, 'rb') as fichier: # Ouvre le fichier en mode binaire
resultat = chardet.detect(fichier.read()) # Analyse l'encodage
logging.info(f"Encodage détecté : {resultat['encoding']} (confiance : {resultat['confidence']*100:.2f}%)")
return resultat['encoding'] or 'utf-8'
except Exception as e:
logging.error(f"Erreur lors de la détection de l'encodage : {e}")
return 'utf-8'
def detecter_delimiteur(chemin_fichier, encodage='utf-8'):
"""
Détecte le délimiteur d'un fichier CSV en testant plusieurs options possibles.
Retourne le délimiteur détecté ou ',' par défaut.
"""
delimiteurs_possibles = [',', ';', '\t', '|'] # Liste des délimiteurs possibles
for delimiteur in delimiteurs_possibles:
try:
with open(chemin_fichier, 'r', encoding=encodage) as fichier: # Ouvre le fichier avec l'encodage spécifié
lecteur = csv.reader(fichier, delimiter=delimiteur) # Teste le délimiteur
sample = list(lecteur) # Charge quelques lignes pour validation
if len(sample) > 1 and len(sample[0]) > 1: # Vérifie si le fichier est valide avec ce délimiteur
logging.info(f"Délimiteur détecté : '{delimiteur}'")
return delimiteur
except Exception as e:
logging.warning(f"Erreur lors du test du délimiteur {delimiteur} : {e}")
logging.warning("Aucun délimiteur spécifique détecté. Utilisation du délimiteur par défaut ','")
return ','
def lister_csvs(dossier_source='.'):
"""
Liste tous les fichiers CSV dans le dossier source.
Retourne une liste des chemins des fichiers trouvés.
"""
fichiers_csv = [
os.path.join(dossier_source, fichier) # Construit le chemin complet des fichiers
for fichier in os.listdir(dossier_source) # Liste les fichiers dans le dossier source
if fichier.lower().endswith('.csv') # Filtre les fichiers avec l'extension .csv
]
return fichiers_csv
def choisir_fichier_csv(fichiers_csv):
"""
Affiche une liste de fichiers CSV disponibles et permet à l'utilisateur de faire un choix.
Retourne le numéro du fichier choisi, 0 pour tous, ou -1 pour quitter.
"""
print("\nFichiers CSV disponibles :")
for i, fichier in enumerate(fichiers_csv, start=1): # Affiche chaque fichier avec un numéro
print(f"{i}. {os.path.basename(fichier)}")
print("0. Convertir tous les fichiers CSV")
print("-1. Quitter le programme")
while True:
try:
choix = int(input("\nEntrez le numéro du fichier à convertir (ou 0 pour tous, -1 pour quitter) : "))
if -1 <= choix <= len(fichiers_csv): # Vérifie que le choix est valide return choix else: print("Choix invalide. Veuillez entrer un numéro valide.") except ValueError: print("Entrée invalide. Veuillez entrer un numéro.") def traiter_fichier_csv(chemin_source, date_columns, date_format): """ Convertit un fichier CSV en fichier XLSX, en appliquant les traitements nécessaires sur les colonnes de date. Retourne True si la conversion est réussie, False sinon. """ logging.info(f"Traitement du fichier : {chemin_source}") encodage = detecter_encodage(chemin_source) # Détecte l'encodage du fichier delimiteur = detecter_delimiteur(chemin_source, encodage) # Détecte le délimiteur du fichier chemin_destination = os.path.splitext(chemin_source)[0] + '.xlsx' # Construit le nom de fichier destination try: # Lecture du fichier CSV dans un DataFrame df = pd.read_csv( chemin_source, encoding=encodage, delimiter=delimiteur, quotechar='"', quoting=csv.QUOTE_ALL, engine='python', on_bad_lines='skip', ) # Traitement des colonnes de date for col in date_columns: if col in df.columns: try: df[col] = pd.to_datetime(df[col], dayfirst=True, errors='coerce').dt.strftime(date_format) # Formate les colonnes de date logging.info(f"Colonne '{col}' formatée avec succès.") except Exception as e: logging.warning(f"Erreur lors de la conversion de la colonne '{col}' : {e}") # Sauvegarde du DataFrame dans un fichier Excel df.to_excel(chemin_destination, index=False) logging.info(f"Conversion réussie : {chemin_source} -> {chemin_destination}")
return True
except Exception as e:
logging.error(f"Erreur lors de la conversion de {chemin_source} : {e}")
return False
def convertir_csv_to_xlsx(dossier_source='.', fichier_json='csv_2_xlsx.json'):
"""
Convertit les fichiers CSV en fichiers XLSX, avec un menu interactif.
Gère la sélection des fichiers et affiche un résumé de la conversion.
"""
date_columns, date_format = charger_configuration_json(fichier_json) # Charge les configurations JSON
while True:
fichiers_csv = lister_csvs(dossier_source) # Liste les fichiers CSV dans le dossier source
if not fichiers_csv:
logging.info("Aucun fichier CSV trouvé dans le dossier.")
print("Aucun fichier CSV trouvé dans le dossier.")
break
choix = choisir_fichier_csv(fichiers_csv) # Demande à l'utilisateur de choisir un fichier
if choix == -1: # Quitte le programme si l'utilisateur le demande
print("Au revoir!")
logging.info("Fin du programme.")
break
total_fichiers = 0 # Compteur du nombre total de fichiers
fichiers_convertis = 0 # Compteur des fichiers convertis avec succès
fichiers_echoues = 0 # Compteur des fichiers ayant échoué
if choix == 0: # Convertit tous les fichiers
total_fichiers = len(fichiers_csv)
for fichier_csv in fichiers_csv:
if traiter_fichier_csv(fichier_csv, date_columns, date_format):
fichiers_convertis += 1
else:
fichiers_echoues += 1
else: # Convertit uniquement le fichier choisi
total_fichiers = 1
fichier_selectionne = fichiers_csv[choix - 1]
if traiter_fichier_csv(fichier_selectionne, date_columns, date_format):
fichiers_convertis += 1
else:
fichiers_echoues += 1
# Résumé final
logging.info("=" * 50)
logging.info("Résumé de la conversion :")
logging.info(f"Total fichiers CSV : {total_fichiers}")
logging.info(f"Fichiers convertis : {fichiers_convertis}")
logging.info(f"Fichiers en échec : {fichiers_echoues}")
logging.info("=" * 50)
print("\nRetour à la liste des choix.")
def main():
"""
Point d'entrée principal, avec un menu interactif.
Configure le logging et lance la conversion.
"""
configurer_logging() # Configure les logs
logging.info("Début du script de conversion CSV vers XLSX")
convertir_csv_to_xlsx() # Lance le processus de conversion
# Point d'entrée du script
if __name__ == "__main__":
main() # Appelle la fonction principale