POWERQUERY :: Expression.Evaluate vs Record.Field :: Construction dynamique d'un nom de colonne à l'appel d'une fonction

oguruma

XLDnaute Occasionnel
Bonjour,
à travers ce post une comparaison entre Record.Field et Expression.Evaluate quand il est nécessaire de passer un nom de colonne de manière dynamique quand celui-ci identifié par [NOM_DE_COLONNE].
En effet dans certaines fonctions qu'elles soient personnelles ou PowerQuery certaines colonnes sont passées sous cette syntaxe [NOM_DE_COLONNE]. Or il est parfois nécessaire que le nom de cette colonne soit dynamique.

J'utilise souvent cette technique dans une majeure partie des fonctions que j'ai développé.

La syntaxe [NOM_DE_VARIABLE] ne fonctionne pas car NOM_DE_VARIABLE est considéré comme un nom de colonne.

L'astuce est de passer par une fonction Expression.Evaluate pour construire la chaine de commande avec un each (solution que je préfère, plus complexe mais elle offre plus de diversité) ou de passer par Record.Field(NOM_DU_RECORD, "NOM_DE_LA_COLONNE") et dans ce cas on peut passer par une variable pour obtenir cette syntaxe
Record.Field(NOM_DU_RECORD, VARIABLE_NOM_DE_COLONNE).

En réel exemple - code initial faisant appel à une fonction personnelle dans laquelle on passe en paramètre un nom de colonne

PowerQuery:
let
    //******************************************************************************************************************
    // Le champ à traiter est passé en dur dans la fonction
    //******************************************************************************************************************
    TBL_CallFunction = Table.AddColumn(TB_EMAILS, "EMAILS_2", each fnDeleteTextBetweenDelimiters([EMAIL], "<", ">"))
in
    TBL_CallFunction

Version avec Expression.Evaluate

PowerQuery:
let
    //******************************************************************************************************************
    // Construction de l'expression de la fonction dynamique via Evaluate
    //******************************************************************************************************************
    STR_FIELD="EMAIL",

    //******************************************************************************************************************
    // On construit la chaine à évaluer
    // Cette méthode bien que contraignante en syntaxe apporte plus de souplesse dans sa construction
    //******************************************************************************************************************   
    STR_Each="each fnDeleteTextBetweenDelimiters([" & STR_FIELD & "],""<"","">"")",

    //******************************************************************************************************************
    // Evaluation dans le contexte PowerQuery
    // Obligation de déclarer via un RECORD les composants du contexte PowerQuery afin qu'ils soient reconnus
    // c'est l'une des constraintes qui imposent la bonne maîtrise de cette fonction
    // avec parfois des messages d'erreur peu évident à comprendre quand on débute
    // Toutes les varibales et fonctions utilisées doivent fournies dans le contexte powerquery via un RECORD
    //******************************************************************************************************************
    EVAL_Each=Expression.Evaluate(STR_Each, [STR_FIELD=STR_FIELD, fnDeleteTextBetweenDelimiters=fnDeleteTextBetweenDelimiters]),

    //******************************************************************************************************************
    // Application du contexte évalué pour appeler la fonction
    //******************************************************************************************************************
    TBL_CallFunction = Table.AddColumn(TB_EMAILS, "EMAIL_2", EVAL_Each)
   
in
    TBL_CallFunction

Version avec Record.Field

Code:
let

    STR_FIELD="EMAIL",
   
    //************************************************************************************************************************
    // Evaluation direct en passant par le RECORD en cours de traitement
    // soit via each '_' et le '_' symbolise le Record
    // soit via une fonction qui remplace le each _ par (RECORD)=> [RECORD : nom du paramètre qui remplace le '_' du each
    // RECORD : nom au choix mais plus parlant que X
    //************************************************************************************************************************

    TBL_CallFunction = Table.AddColumn(TB_EMAILS, "EMAIL_2", (RECORD) => fnDeleteTextBetweenDelimiters(Record.Field(RECORD,STR_FIELD), "<", ">"))
in
    TBL_CallFunction
 

Pièces jointes

  • Each_VS_Record.Field_V0.001.xlsx
    19.5 KB · Affichages: 2

Discussions similaires

Statistiques des forums

Discussions
313 865
Messages
2 103 078
Membres
108 521
dernier inscrit
manouba