oguruma
XLDnaute Occasionnel
Une petite fonction pour calculer des % dans des colonnes par rapport au total de la colonne.
Là aussi cette fonction passe par des Buffers. Attention à la volumétrie. La barre des 5000 lignes est passée sans aucun problème.
Elle est fondée sur le même principe que la fonction permettant de totaliser une colonne en utilisant Expression.Evaluate. La notion de contexte est très importante dans cette fonction. Voir aussi #shared. En fait dès que l'on variabilise une fonction par le biais d'une chaine dynamique son contexte d'exécution n'est plus connu dans la base des instructions PowerQuery tout comme les colonnes qui composent ces chaines dynamiques. Il faut donc de nouveau préciser soit pas #shared ou soit par exemple [List.Buffer=List.Buffer, SourceData=SourceData]
Sinon vous aurez un message vous informant que la fonction, ou que la colonne, ou que la colonne ne sont pas connu dans le contexte.
let fnPct =
(
pSrcData as any,
pFieldValue as text,
pPctField as text,
optional pFieldValue2 as text,
optional pPctField2 as text
) as table =>
let
SrcData=pSrcData,
FieldValue=pFieldValue,
PctField=pPctField,
FieldValue2=pFieldValue2,
PctField2=pPctField2,
SourceData = if SrcData is text then Excel.CurrentWorkbook(){[Name=SrcData]}[Content] else SrcData,
//************************************************************
// On bufferise les valeurs à cumuler pour accélérer
//************************************************************
ToStringBuffer_1="List.Buffer(SourceData[" & FieldValue & "])",
TmpBuffer_1=Expression.Evaluate(ToStringBuffer_1, [List.Buffer=List.Buffer,SourceData=SourceData]),
ToStringBuffer_2="List.Buffer(SourceData[" & FieldValue2 & "])",
TmpBuffer_2=if FieldValue2 is null
then null
else Expression.Evaluate(ToStringBuffer_2, [List.Buffer=List.Buffer,SourceData=SourceData]),
//************************************************************
// On calcule les totaux des colonnes
//************************************************************
SumTmpBuffer_1=List.Sum(TmpBuffer_1),
SumTmpBuffer_2= if FieldValue2 is null
then null
else List.Sum(TmpBuffer_2),
TmpTablePct_1 = Expression.Evaluate("Table.AddColumn(SourceData, PctField, each [" & FieldValue & "]/SumTmpBuffer_1)",
[SourceData=SourceData, Table.AddColumn=Table.AddColumn, PctField=PctField, FieldValue=FieldValue,SumTmpBuffer_1=SumTmpBuffer_1 ]),
TmpTablePct_2 = if FieldValue2 is null
then null
else Expression.Evaluate("Table.AddColumn(TmpTablePct_1, PctField2, each [" & FieldValue2 & "]/SumTmpBuffer_2)",
[SourceData=SourceData, TmpTablePct_1=TmpTablePct_1, Table.AddColumn=Table.AddColumn, PctField2=PctField2, FieldValue2=FieldValue2,SumTmpBuffer_2=SumTmpBuffer_2 ]),
Result= if TmpTablePct_2 is null then TmpTablePct_1 else TmpTablePct_2
in
Result
in
fnPct
Là aussi cette fonction passe par des Buffers. Attention à la volumétrie. La barre des 5000 lignes est passée sans aucun problème.
Elle est fondée sur le même principe que la fonction permettant de totaliser une colonne en utilisant Expression.Evaluate. La notion de contexte est très importante dans cette fonction. Voir aussi #shared. En fait dès que l'on variabilise une fonction par le biais d'une chaine dynamique son contexte d'exécution n'est plus connu dans la base des instructions PowerQuery tout comme les colonnes qui composent ces chaines dynamiques. Il faut donc de nouveau préciser soit pas #shared ou soit par exemple [List.Buffer=List.Buffer, SourceData=SourceData]
Sinon vous aurez un message vous informant que la fonction, ou que la colonne, ou que la colonne ne sont pas connu dans le contexte.
let fnPct =
(
pSrcData as any,
pFieldValue as text,
pPctField as text,
optional pFieldValue2 as text,
optional pPctField2 as text
) as table =>
let
SrcData=pSrcData,
FieldValue=pFieldValue,
PctField=pPctField,
FieldValue2=pFieldValue2,
PctField2=pPctField2,
SourceData = if SrcData is text then Excel.CurrentWorkbook(){[Name=SrcData]}[Content] else SrcData,
//************************************************************
// On bufferise les valeurs à cumuler pour accélérer
//************************************************************
ToStringBuffer_1="List.Buffer(SourceData[" & FieldValue & "])",
TmpBuffer_1=Expression.Evaluate(ToStringBuffer_1, [List.Buffer=List.Buffer,SourceData=SourceData]),
ToStringBuffer_2="List.Buffer(SourceData[" & FieldValue2 & "])",
TmpBuffer_2=if FieldValue2 is null
then null
else Expression.Evaluate(ToStringBuffer_2, [List.Buffer=List.Buffer,SourceData=SourceData]),
//************************************************************
// On calcule les totaux des colonnes
//************************************************************
SumTmpBuffer_1=List.Sum(TmpBuffer_1),
SumTmpBuffer_2= if FieldValue2 is null
then null
else List.Sum(TmpBuffer_2),
TmpTablePct_1 = Expression.Evaluate("Table.AddColumn(SourceData, PctField, each [" & FieldValue & "]/SumTmpBuffer_1)",
[SourceData=SourceData, Table.AddColumn=Table.AddColumn, PctField=PctField, FieldValue=FieldValue,SumTmpBuffer_1=SumTmpBuffer_1 ]),
TmpTablePct_2 = if FieldValue2 is null
then null
else Expression.Evaluate("Table.AddColumn(TmpTablePct_1, PctField2, each [" & FieldValue2 & "]/SumTmpBuffer_2)",
[SourceData=SourceData, TmpTablePct_1=TmpTablePct_1, Table.AddColumn=Table.AddColumn, PctField2=PctField2, FieldValue2=FieldValue2,SumTmpBuffer_2=SumTmpBuffer_2 ]),
Result= if TmpTablePct_2 is null then TmpTablePct_1 else TmpTablePct_2
in
Result
in
fnPct