martes, 7 de septiembre de 2021

Power Query: Función con parámetros opcionales

Siguiendo con la entrada anterior donde expuse un par de formas para modifcar una dato concreto (fila - columna) dentro de una consulta de Power Query... Hoy convertiremos ese proceso es una función M personalizada, pero con parámetros opcionales !!
Revisa el artículo anterior, donde se explica el proceso de modificación de una 'celda concreta' en una consulta.

Partimos de nuestra ya conocida tabla del post comentada, con unos campos:Año, País, Comercial, Producto y Unidades; Tabla que se ha cargado al editor de consultas de Power Query solo como conexión.

Para crear nuestra función M personalizada te recomiendo leas primero este interesante post, donde se explican las metatags de documentación de una función M.

Igualmente es importante que conozcas estas funciones de Expression:
Expression.Evaluate
Expression.Identifier

Con esos conceptos leídos, podemos acceder al editor de consultas de Power Query y añadir una Consulta en blanco donde escribiremos el siguiente código M:
let 
TablaConDatos=
    //Trabajaremos sobre la Tabla de la hoja de cálculo cargada
    let
        Origen = Excel.CurrentWorkbook(){[Name="TblDATOS"]}[Content]
    in
        Origen,

//Creamos una función personalizada que contiene entre 3-7 parámetros
// tres obligatorios + cuatro opcionales
ModificaFila=
    (NumFila as number,

    Campo1 as text,
    ValorNuevo1 as any, 

    optional Campo2 as text, 
    optional ValorNuevo2 as any,

    optional Campo3 as text, 
    optional ValorNuevo3 as any ) as table=>

let
    //definimos los ámbitos/contextos donde podremos trabajar con las funciones Expression.Evaluate y .Identifier
    AmbitoVariables = 
            [ValorNuevo1I=ValorNuevo1, 
            ValorNuevo2I=ValorNuevo2, 
            ValorNuevo3I=ValorNuevo3],
    //incluímos #shared para englobar la totalidad de funciones, secciones, etc...
    AmbitoVariables_Globals = Record.Combine({AmbitoVariables, #shared}),

    //Componemos, de manera dinámica, y según los argumentos rellenados
    //el Record que permite modificar un dato de una fila-columna en concreto

    //en caso que se relleno o no el Campo2
    CampoDOS = if Campo2=null then
                {TablaConDatos{NumFila} & 
                    Expression.Evaluate("[" & Text.From(Campo1) & "=" & Expression.Identifier("ValorNuevo1I") & "]", AmbitoVariables_Globals)}
            else
                {TablaConDatos{NumFila} & 
                    Expression.Evaluate("[" & Text.From(Campo1) & "=" & Expression.Identifier("ValorNuevo1I") & "]", AmbitoVariables_Globals) & 
                    Expression.Evaluate("[" & Text.From(Campo2) & "=" & Expression.Identifier("ValorNuevo2I")  & "]",AmbitoVariables_Globals)},
    
    //en caso que se relleno o no el Campo3
    CampoTRES = if Campo3=null then
                CampoDOS
            else
                {TablaConDatos{NumFila} & 
                    Expression.Evaluate("[" & Text.From(Campo1) & "=" & Expression.Identifier("ValorNuevo1I") & "]", AmbitoVariables_Globals) & 
                    Expression.Evaluate("[" & Text.From(Campo2) & "=" & Expression.Identifier("ValorNuevo2I")  & "]",AmbitoVariables_Globals) &
                    Expression.Evaluate("[" & Text.From(Campo3) & "=" & Expression.Identifier("ValorNuevo3I")  & "]",AmbitoVariables_Globals)},

    // Acción donde primero Eliminamos la fila 2 (recuerda que estamos en base 0 !!)
    //para seguidamente Insertar una nueva fila en el lugar de la anterior
    // con un registro compuesto por los nuevos valores
    // que modifican los previos existentes
    ValorModificado = Table.InsertRows(
        Table.RemoveRows(TablaConDatos,NumFila,1),   //Elimina la fila 2
        NumFila,          //insertamos una nueva fila en la posición 2
        //el valor de la fila compuesto por el siguiente Record
        CampoTRES)
in 
    ValorModificado,
        
//Configuramos Valores Permitidos para algunos campos...
ValoresPermitidos =
    let
        //Lista con los nombres de los campos de la Tabla 'original'
        //que serán los valores permitidos al rellenar: Campo1, Campo2 o Campo3
        optCampos123 = Table.ColumnNames(TablaConDatos),

        //Asignamos características a los tipos de campo
        CamposParamType = type text 
            meta
            [Documentation.FieldCaption = "Selecciona un campo",
            Documentation.AllowedValues = optCampos123],
        ValoresParamType = type any 
            meta
            [Documentation.FieldCaption = "Indica el nuevo valor del registro"],

        //redefinimos los tipos de datos que admiten nuestros parámetros
        NuevosTipos = type function (
            NumFila as number,
            Campo1 as CamposParamType,
            ValorNuevo1 as ValoresParamType,
            optional Campo2 as CamposParamType,
            optional ValorNuevo2 as ValoresParamType,
            optional Campo3 as CamposParamType,
            optional ValorNuevo3 as ValoresParamType)
        as table,
        
        ReemplazamosTiposFuncion = Value.ReplaceType(ModificaFila, NuevosTipos)
    in
        ReemplazamosTiposFuncion

in 
    ValoresPermitidos

El resultado sería:
Power Query: Función con parámetros opcionales

Si invocamos nuestra función bien directamente, bien desde el paso intermedio de alguna consulta, veríamos el resultado del cambio/modificación...
Por ejemplo:
Power Query: Función con parámetros opcionales


Hemos indicado que deseamos modificar de la fila 3 (ojo!!, trabajamos en base cero) el dato de la columna de Año y País por nuevos valores 2021 y España...Dejando los argumentos del tercer campo vacíos, i.e., sin cambios.
Power Query: Función con parámetros opcionales

No hay comentarios:

Publicar un comentario

Nota: solo los miembros de este blog pueden publicar comentarios.