POWERQUERY :: Nettoyage de données - Supprimer des caractères entre deux délimiteurs - Fonction automatisée

oguruma

XLDnaute Occasionnel
Bonjour,
Il arrive régulièrement quand on reçoit un fichier de l'extérieur que l'on soit amené à effectuer du nettoyage de données. Un cas fréquent, supprimer des caractères entre deux séparateurs.
Exemples (eEmails bidons)
1722599573957.png

1722599593085.png

1722599618862.png


L'idée serait supprimer y compris les délimiteurs les caractères entre (, ) - <, > - ::, ::

1722599858913.png


ou ici la colonne d'origine n'est pas conservée à l'issue du nettoyage

1722599878624.png


Pour cela une petite fonction fnDeleteTextBetweenDelimiters

PowerQuery:
let
    Source = (pSTR_String as text, pSTR_LeftDelim as text, pSTR_RightDelim as text) =>  
    let
        STR_LST_NULL={""},
        //***********************************************************************************************
        // On commence par celui de droite et si trouvé on remplace par chaine vide
        //***********************************************************************************************
        LST_Right = List.RemoveMatchingItems(Text.Split(pSTR_String, pSTR_RightDelim), STR_LST_NULL ),

        //***********************************************************************************************
        // Il faut maintenant extraire la partie gauche du délimiteur
        // On balaye le reste de la chaine pour trouve celui de gauche
        //***********************************************************************************************
        LST_Left = List.Transform(
                LST_Right, 
                        // --- Ici autre manière d'exprimer un each en passant par une fonction
                        (x)=>
                            let 
                                //************************************************************************
                                // Calcule sa position pour en déduire le reste de la chaine à fusioinner
                                //************************************************************************
                                INT_Position=Text.PositionOf(x, pSTR_LeftDelim ),
                                //************************************************************************
                                // Par sécurité pour ne pas planter s'il n'est pas trouvé
                                // et on écarte la partie inutile
                                //************************************************************************
                                STR_Value=if INT_Position= -1 then x else Text.Start(x , INT_Position)
                            in
                                STR_Value
                ),
        //**************************************************************************************************
        // Puis assemble les deux chaines pour former celle d'origine sans le contenu entre les séparateurs
        // Les éléments de la liste sont concaténés
        //**************************************************************************************************
        LST_Final = Text.Combine(LST_Left)
    in
        LST_Final
in
    Source

Comment l'utiliser

PowerQuery:
let
    Source = Excel.CurrentWorkbook(){[Name="TB_EMAILS_1"]}[Content],
    TBL_CallFunction = Table.AddColumn(Source, "EMAIL_2", each fnDeleteTextBetweenDelimiters([EMAIL], "<", ">"))
in
    TBL_CallFunction

1722600186485.png


Cas où ne souhaite pas garder la colonne source

Méthode 1

PowerQuery:
let
    Source = TB_EMAILS_1,
    STR_ColumnToClean="EMAIL",
    STR_AddColumn="EMAIL_2",
    STR_StartDelim="<",
    STR_EndDelim=">",
    B_ToDeleteColumn=true,
    STR_EVAL_Each="each fnDeleteTextBetweenDelimitersNoKeep([" & STR_ColumnToClean & "], STR_StartDelim, STR_EndDelim)",
    EVAL_Each=Expression.Evaluate(STR_EVAL_Each ,
        [
            fnDeleteTextBetweenDelimitersNoKeep=fnDeleteTextBetweenDelimiters,
            STR_ColumnToClean=STR_ColumnToClean,
            STR_StartDelim=STR_StartDelim,
            STR_EndDelim=STR_EndDelim
        ]),
    TBL_CallFunction = Table.AddColumn(Source, STR_AddColumn, EVAL_Each),
    TBL_FINAL=if B_ToDeleteColumn
              then 
                    let
                        TBL_DelColumn1 = Table.RemoveColumns(TBL_CallFunction,{STR_ColumnToClean}),
                        TBL_RenameColumn2 = Table.RenameColumns(TBL_DelColumn1,{{STR_AddColumn, STR_ColumnToClean}})
                    in
                        TBL_RenameColumn2
              else
                    TBL_CallFunction
in
    TBL_FINAL

Méthode 2
PowerQuery:
let
    Source = TB_EMAILS_1,
    STR_ColumnToClean="EMAIL",
    STR_StartDelim="<",
    STR_EndDelim=">",
    TBL_Transform = Table.TransformColumns(Source,{{STR_ColumnToClean, (fld) => fnDeleteTextBetweenDelimiters(fld, STR_StartDelim, STR_EndDelim), type text}}),
    TBL_ClearSpaces = Table.TransformColumns(TBL_Transform,{{STR_ColumnToClean, Text.Trim, type text}})
in
    TBL_ClearSpaces

PowerQuery:
let fnTBLDeleteTextBetweenDelimiters = (
        pSTR_Source as any,
        pSTR_ColumnToClean as text,
        pSTR_AddColumn as text,
        pSTR_StartDelim as text,
        pSTR_EndDelim as text,
        optional pB_ToDeleteColumn as logical
    ) =>
    let
        Source = if pSTR_Source is table
                then pSTR_Source
                else Excel.CurrentWorkbook(){[Name=pSTR_Source]}[Content],
        STR_ColumnToClean=pSTR_ColumnToClean,
        STR_AddColumn=pSTR_AddColumn,
        STR_StartDelim=pSTR_StartDelim,
        STR_EndDelim=pSTR_EndDelim,
        B_ToDeleteColumn=if pB_ToDeleteColumn is null then false else pB_ToDeleteColumn,
        STR_EVAL_Each="each fnDeleteTextBetweenDelimiters([" & STR_ColumnToClean & "], STR_StartDelim, STR_EndDelim)",
        EVAL_Each=Expression.Evaluate(STR_EVAL_Each ,
            [
                fnDeleteTextBetweenDelimiters=fnDeleteTextBetweenDelimiters,
                STR_ColumnToClean=STR_ColumnToClean,
                STR_StartDelim=STR_StartDelim,
                STR_EndDelim=STR_EndDelim
            ]),
        TBL_CallFunction = Table.AddColumn(Source, STR_AddColumn, EVAL_Each),
        TBL_FINAL=if B_ToDeleteColumn
                then 
                        let
                            TBL_DelColumn1 = Table.RemoveColumns(TBL_CallFunction,{STR_ColumnToClean}),
                            TBL_RenameColumn2 = Table.RenameColumns(TBL_DelColumn1,{{STR_AddColumn, STR_ColumnToClean}})
                        in
                            TBL_RenameColumn2
                else
                        TBL_CallFunction
    in
        TBL_FINAL
in 
    fnTBLDeleteTextBetweenDelimiters

Version 2
PowerQuery:
let fnTBLDeleteTextBetweenDelimitersV2=
    (
        pSTR_Source as any,
        pSTR_ColumnToClean as text,
        pSTR_StartDelim as text,
        pSTR_EndDelim as text
    )=>

    let
        Source = if pSTR_Source is table
                then pSTR_Source
                else Excel.CurrentWorkbook(){[Name=pSTR_Source]}[Content],
        STR_ColumnToClean=pSTR_ColumnToClean,       
        STR_StartDelim=pSTR_StartDelim,
        STR_EndDelim=pSTR_EndDelim,
        TBL_Transform = Table.TransformColumns(Source,{{STR_ColumnToClean, (fld) => fnDeleteTextBetweenDelimiters(fld, STR_StartDelim, STR_EndDelim), type text}}),
        TBL_ClearSpaces = Table.TransformColumns(TBL_Transform,{{STR_ColumnToClean, Text.Trim, type text}})
    in
        TBL_ClearSpaces
       
in
    fnTBLDeleteTextBetweenDelimitersV2

Le fichier joint sera plus explicite avec les nombreux exemples qu'il comporte
 

Pièces jointes

  • DeleteTextBetweenDelimitersKeep_V0.026.xlsx
    36.6 KB · Affichages: 8

Discussions similaires

Statistiques des forums

Discussions
313 866
Messages
2 103 082
Membres
108 521
dernier inscrit
manouba