POWERQUERY :: Remplacements multiples dans plusieurs colonnes avec traitements de nettoyage et de conversion de casse

Boostez vos compétences Excel avec notre communauté !

Rejoignez Excel Downloads, le rendez-vous des passionnés où l'entraide fait la force. Apprenez, échangez, progressez – et tout ça gratuitement ! 👉 Inscrivez-vous maintenant !

oguruma

XLDnaute Impliqué
Bonjour Le Forum,
dans la précédente publication ICI j'avais évoqué qu'il était possible d'appliquer des traitements particuliers sur les colonnes. C'est donc chose faite dans cette nouvelle version.

Cette nouvelle version permet aussi soit d'importer un fichier Excel soit un fichier .CSV.

IMPORTATION D'UN FICHIER .CSV
On passe toujours par un tableau de paramètres comme celui-ci
1761162507807.png

Cette fois nous avons le choix sur le type de fichier
1761162554107.png


Les paramètres ITEM et KIND sont eux utilisés pour les fichiers Excel que nous verrons plus bas.

Puis nous avons les deux tables de traitements et nettoyage
1761162652881.png


L'organisation de PowerQuery est la suivante :
1761162735207.png


RQ_IMPORT_DONNEES est une requête de connexion qui va se charger de produire la table finale chargée dans TB_FINALE.
PowerQuery:
let
    Source = RQ_IMPORT_DONNEES
in
    Source

Selon les besoins les évolutions se feront dans cette table TB_FINALE.
Le fait de découper les traitements PowerQuery permet d'alléger le code. RQ_IMPORT_DONNEES est une requête de préparation des données.

Préalable : afin de connaître le nom des colonnes il faudra ouvrir le fichier .CSV et identifier les noms des colonnes dans la 1ère ligne.

Le fait de passer par une table de nettoyage offre beaucoup de souplesse pour la maintenance. Ceci évite d'ouvrir le code de la requête pour ajouter ou supprimer des colonnes à nettoyer.
La logique est la même si on a besoin d'effectuer des remplacements de valeurs dans les colonnes. On passera par la table des critères de remplacement.

Voici le code qui est aussi identique pour les importations de fichiers EXCEL. C'est juste le paramétrage qui diffère.
Je vous invite à bien lire les commentaires.

PowerQuery:
let

    //******************************************************************************
    //                      FONCTIONS SECTION
    //******************************************************************************

    //*******************************************************************************
    // Fonction permettant d'importer le fichier mentionné dans les paramètres
    //*******************************************************************************
    GET_DATA_SOURCE = () as any =>
        let
            //Csv.Document(File.Contents(STR_DOSSIER & "\" & STR_FICHIER ),[Delimiter=STR_SEPARATEUR, Encoding=65001, QuoteStyle=QuoteStyle.Csv]),
            TblSource=if STR_TYPE="CSV" or STR_TYPE is null then
                            Csv.Document(File.Contents(STR_DOSSIER & "\" & STR_FICHIER ),[Delimiter=STR_SEPARATEUR, Encoding=65001, QuoteStyle=QuoteStyle.Csv])
                      else
                            let
                                Source = Excel.Workbook(File.Contents(STR_DOSSIER & "\" & STR_FICHIER ), null, true),
                                SourceExcel = Source{[Item=STR_ITEM,Kind=STR_KIND]}[Data]
                            in
                                SourceExcel
        in
            TblSource,

    //*******************************************************************************
    // Opération de nettoyage
    //*******************************************************************************
    TRAITEMENT_NETTOYAGE = () as any =>
        let
            // NETTOYAGE    SUPPR_ESPACE    TEXTE    CONVERSION
            // Récupération des opérations de nettoyage - identification des colonnes et peu importe le nom
            // il faut juste respecter l'ordre préciser ci-dessus dans les commentaires
            STR_COL_NETTOYAGE = LST_COLUMNS_TRAITEMENTS{1},                        // option de nettoyage
            STR_COL_SUPPR_ESPACE = LST_COLUMNS_TRAITEMENTS{2},                    // option de suppression des espaces
            STR_COL_CONV_TEXTE = LST_COLUMNS_TRAITEMENTS{3},                      // optin de conversion en texte
            STR_COL_CONVERSION=LST_COLUMNS_TRAITEMENTS{4},                        // option de conversion de la casse

            // Boucle de traitement sur les opérations de nettoyage à effectuer
            //------------------------------------------------------------------
            LST_ACCUMULATE=List.Accumulate(
                TBL_TRAITEMENTS_TO_RECORDS,  // Liste des enregistrements à traiter
                TBL_DATA,                    // On récupère le fichier à l'issue de l'importation
                (state,current)=>            // variables de boucle - state = accumulateur au fil des traitement -- current = record en cours de traitement
                    let
                        // On récupère les options de nettoyage et de conversion si elles sont mentionnées
                        //--------------------------------------------------------------------------------
                        IsNettoyage=Record.Field(current, STR_COL_NETTOYAGE),
                        IsSupprEspace=Record.Field(current, STR_COL_SUPPR_ESPACE),
                        ISConvTexte=Record.Field(current, STR_COL_CONV_TEXTE),
                        TypeConversion=Record.Field(current, STR_COL_CONVERSION),
                       
                        // phase de nettoyage
                        //-------------------
                        TblNettoyage=if IsNettoyage = "NON" or IsNettoyage is null or Record.Field(current, STR_NOM_COLONNE_TRAITEMENT) is null then TBL_DATA
                                     else Table.TransformColumns(state,{{Record.Field(current, STR_NOM_COLONNE_TRAITEMENT), Text.Clean, type text}}),

                        TblSpprEspace=if IsSupprEspace ="NON" or IsSupprEspace is null  or Record.Field(current, STR_NOM_COLONNE_TRAITEMENT) is null then TblNettoyage
                                      else Table.TransformColumns(TblNettoyage,{{Record.Field(current, STR_NOM_COLONNE_TRAITEMENT), Text.Trim, type text}}),                      
                       
                        TblText=if ISConvTexte = "NON" or ISConvTexte is null  or Record.Field(current, STR_NOM_COLONNE_TRAITEMENT) is null then TblSpprEspace
                                else  Table.TransformColumnTypes(TblSpprEspace,{{Record.Field(current, STR_NOM_COLONNE_TRAITEMENT), type text}}),

                        // phase de conversion majuscule, minuscule, nom propre
                        //-------------------------------------------------------      
                        TblConversion=if TypeConversion is null  or Record.Field(current, STR_NOM_COLONNE_TRAITEMENT) is null  then TblText
                                      else if TypeConversion = "MINUSCULE"
                                           then Table.TransformColumns(TblText,{{Record.Field(current, STR_NOM_COLONNE_TRAITEMENT), Text.Lower, type text}})
                                           else if TypeConversion = "MAJUSCULE"
                                                then Table.TransformColumns(TblText,{{Record.Field(current, STR_NOM_COLONNE_TRAITEMENT), Text.Upper, type text}})
                                                else if TypeConversion = "NONPROPRE"
                                                     then Table.TransformColumns(TblText,{{Record.Field(current, STR_NOM_COLONNE_TRAITEMENT), Text.Proper, type text}})
                                                     else TblText
                    in
                        TblConversion // nouvelle table à l'issue des opérations de traitements
            )
        in
            LST_ACCUMULATE,  // fin de la boucle

    TRAITEMENTS_REMPLACEMENTS = () as any =>
        let
            STR_COL_ANC_VALEUR=LST_COLUMNS_CRITERES{1},              // Nom de la colonne comportant les anciennes valeurs
            STR_COL_NOUV_VALEUR=LST_COLUMNS_CRITERES{2},             // Nom de la colonne comportant les nouvelles valeurs

            // boucle de traitement sur les critères de remplacement
            //--------------------------------------------------------
            LST_ACCUMULATE=List.Accumulate (
                TBL_CRITERES_TO_RECORDS,  // Liste des enregistrements de remplacement à traiter
                TBL_NETTOYAGE,            // Table de données à l'issue du nettoyage
                (state,current) =>
                let
                    Colonne=Record.Field(current,STR_NOM_COLONNE),  // nom de la colonne à traiter
                    IsExists=if Colonne is null then false else Table.HasColumns(TBL_NETTOYAGE,Colonne), // on va vérifier si elle existe pour éviter des plantages - si inconnue on passe à la suivante
                    TblNew =  if IsExists then
                                 let
                                    AncValeur=Record.Field(current,  STR_COL_ANC_VALEUR),
                                    NouvValeur=Record.Field(current, STR_COL_NOUV_VALEUR),
                                    NouvValeur2=if NouvValeur is null then "" else NouvValeur,    // pour éviter un plantage si aucune valeur est renseignée et remise à blanc
                                    // remplacement des données dans la colonne en cours
                                    //--------------------------------------------------
                                    TblReplace=if AncValeur is null then state
                                            else
                                                Table.TransformColumns(state,{{Colonne, each Text.Replace(_,AncValeur,NouvValeur2), type text}})  // on procède au remplacement des valeurs dans la colonne
                                in
                                    TblReplace
                                else state
                in
                    TblNew  // nouvelle table à l'issue dees remplacements
            )
        in
            LST_ACCUMULATE,

    //******************************************************************************
    //                      PRINCIPALE SECTION
    //******************************************************************************

    //******************************************************************************
    // Identification des paramètres
    //******************************************************************************
    STR_DOSSIER=fnGetParameter("TB_PARAMS", "DOSSIER"),
    STR_FICHIER=fnGetParameter("TB_PARAMS", "FICHIER"),
    STR_TYPE=fnGetParameter("TB_PARAMS", "TYPE"),
    STR_ITEM=fnGetParameter("TB_PARAMS", "ITEM"),
    STR_KIND=fnGetParameter("TB_PARAMS", "KIND"),
    STR_SEPARATEUR=fnGetParameter("TB_PARAMS", "SEPARATEUR"),
    STR_PROMOTE=Text.Upper(fnGetParameter("TB_PARAMS", "PROMOTE")),
  //  STR_DONNES=fnGetParameter("TB_PARAMS", "TABLE_DONNES_IMPORT"),  
    STR_CRITERES=fnGetParameter("TB_PARAMS", "TABLE_CRITERES_IMPORT"),
    STR_TRAITEMENTS=fnGetParameter("TB_PARAMS", "TABLE_TRAITEMENTS_IMPORT"),

    //******************************************************************************
    // Chargement du fichier .csv
    //******************************************************************************
    TBL_DATA_SOURCE = GET_DATA_SOURCE(),
    //Csv.Document(File.Contents(STR_DOSSIER & "\" & STR_FICHIER ),[Delimiter=STR_SEPARATEUR, Encoding=65001, QuoteStyle=QuoteStyle.Csv]),
    TBL_DATA = if STR_PROMOTE is null or STR_PROMOTE = "OUI" then Table.PromoteHeaders(TBL_DATA_SOURCE, [PromoteAllScalars=true]) else TBL_DATA_SOURCE,

    //******************************************************************************
    // Table des critères de remplacement - table des traitements
    //******************************************************************************
    TBL_CRITERES = Excel.CurrentWorkbook(){[Name=STR_CRITERES]}[Content],
    TBL_TRAITEMENTS = Excel.CurrentWorkbook(){[Name=STR_TRAITEMENTS]}[Content],

    //******************************************************************************
    //           On identifie les colonnes des tableaux
    //******************************************************************************
    LST_COLUMNS_CRITERES=Table.ColumnNames(TBL_CRITERES),
    LST_COLUMNS_TRAITEMENTS=Table.ColumnNames(TBL_TRAITEMENTS),

    //*******************************************************************************
    // Respecter l'ordre des colonnes peu importe le nom des colonnses
    // Colonnes critères
    //*******************************************************************************
    STR_NOM_COLONNE=LST_COLUMNS_CRITERES{0},             // Nom de la colonne comportant le nom des colonnes à traiter

    //*******************************************************************************
    // Peu importe le nom des colonnes dans le tableau des traitement cet ordre doit être respecté
    // NETTOYAGE    SUPPR_ESPACE    TEXTE    CONVERSION
    //*******************************************************************************
    STR_NOM_COLONNE_TRAITEMENT=LST_COLUMNS_TRAITEMENTS{0},             // Nom de la colonne à traiter

    //*******************************************************************************
    // Nombre de critères de remplacements - nombre de traitement
    //*******************************************************************************
    // INT_NB_CRITERES=Table.RowCount(TBL_CRITERES),
    // INT_NB_TRAITEMENTS=Table.RowCount(TBL_TRAITEMENTS),

    //*******************************************************************************
    // Transformation des critères et des traitements en liste de records
    //*******************************************************************************
    TBL_CRITERES_TO_RECORDS=Table.ToRecords(TBL_CRITERES),
    TBL_TRAITEMENTS_TO_RECORDS=Table.ToRecords(TBL_TRAITEMENTS),

    //*******************************************************************************
    // Pour vérifier si des traitements sont à effectuer
    //*******************************************************************************
    IsTraitementNettoyage=Record.Field(TBL_TRAITEMENTS_TO_RECORDS{0},STR_NOM_COLONNE_TRAITEMENT),
    IsCritere=Record.Field(TBL_CRITERES_TO_RECORDS{0},STR_NOM_COLONNE),

    //*******************************************************************************
    // Traitements de nettoyage et de remplacement des données selon les critères fournis
    //*******************************************************************************
    TBL_NETTOYAGE=if IsTraitementNettoyage is null then TBL_DATA else TRAITEMENT_NETTOYAGE(),
    TBL_FINALE=if IsCritere is null then TBL_NETTOYAGE else TRAITEMENTS_REMPLACEMENTS()
   
in
    TBL_FINALE

Remarque : même si on trouve que cet utilitaire apporte peu d'intérêt il peut être très pédagogique dans l'apprentissage du langage M de PowerQuery.

IMPORTATION D'UN FICHIER EXCEL
1761163420911.png


1761163464686.png

Ceci est déterminé via le tableau
1761163497299.png


Via la requête
PowerQuery:
let
    STR_DOSSIER=fnGetParameter("TB_PARAMS", "DOSSIER"),
    STR_FICHIER=fnGetParameter("TB_PARAMS", "FICHIER"),
    STR_TYPE=fnGetParameter("TB_PARAMS", "TYPE"),
    Source = if STR_TYPE ="EXCEL"  then
                let    
                    WB_EXCEL=Excel.Workbook(File.Contents(STR_DOSSIER & "\" & STR_FICHIER), null, true),
                    SUPPR_COLONNES = Table.RemoveColumns(WB_EXCEL,{"Data", "Item", "Kind", "Hidden"})
                in
                    SUPPR_COLONNES
             else
                #table(
                            { "Name" }, // defines column names
                        {
                            { "" }
               
                        }
                )
in
    Source

Il suffit de rafraîchir le tableau par le boutonj Actualiser qui va renvoyer automatiquement le liste des ITEM.
Selon le type de source de données il faudra choisir
1761163643210.png


Installation
Pour vos tests :
1- créer un dossier
2- dans ce dossier déposer les deux fichiers Excel
3- déposer le fichier Excel Ventes_2022_2
4- déposer et dézipper diplomes-professionnels.zip
5- effectuer le paramétrage nécessaire correspondant au dossier où vous avez déposé les fichiers
 

Pièces jointes

- Navigue sans publicité
- Accède à Cléa, notre assistante IA experte Excel... et pas que...
- Profite de fonctionnalités exclusives
Ton soutien permet à Excel Downloads de rester 100% gratuit et de continuer à rassembler les passionnés d'Excel.
Je deviens Supporter XLD

Discussions similaires

Retour