jueves, 9 de febrero de 2023

Power Query: Tablas a partir de texto

Una situación no muy habitual es tener que procesar un texto como si fuera una tabla (u otro objeto) dentro de Power Query... Y esto es lo que voy a exponer en el artículo de hoy.
Veremos cómo a partir de los elementos de texto de una lista, realizaremos ciertas transformaciones, hasta conseguir anexar las tablas existentes correspondientes a cada literal.

Veamos en la imagen siguiente el punto de partida (y el resultado final obtenido).
Tenemos tres tablas ('TblES', 'TblDE' y 'TblIT'), pero podrían ser indeterminadas... Y necesitamos anexarlas en una única tabla final.
Como dificultad añadida tenemos encabezados diferentes.
Power Query: Tablas a partir de texto


Como siempre cargaremos nuestros origenes (las tres tablas, mas una cuarta con la traducción de los nombres de columnas) y crearemos en el Editor de Power Query una consulta en blanco con el siguiente código M:
let
    lstNombres={"TblES","TblDE","TblIT"},
    lstNuevosNombres={"Date","Units","Amount"},

    //generamos una tabla de null, que será la 'semilla' de List.Accumulate
    tblINI=#table(lstNuevosNombres,{List.Repeat({null}, List.Count(lstNuevosNombres))}),

    //recorremos los nombres de las tablas
    anexado=List.Accumulate(
            lstNombres,     //elementos a recorrer
            tblINI,         // semilla o inicio de la secuencia
            (state,current)=> let
                //paso clave para trasnformar texto como Tabla
                tabla="#""" & Expression.Identifier(current) & """",

                tbl=[MiTabla= Expression.Evaluate(tabla,#shared)],
                TablaMedia=tbl[MiTabla],    //Obtengo una Tabla a partir de un elemento texto

                //Tranformaciones una vez convertido el texto a tabla_____________
                //selecciono campos según TblLANG
                lang=Text.End(current,2),
                tsl=Table.SelectRows(TblLANG, each List.Contains(lstNuevosNombres,[UK])),
                lstCampos=Table.Column(tsl, lang),
                //preparo lista 'zippeada' para renombrar columnas
                zip=List.Zip({lstCampos,lstNuevosNombres}),
                TblRenombroCOLS=Table.RenameColumns(TablaMedia,zip),
                //y acabo seleccionando solo las columnas requeridas
                TablaCOLS=Table.SelectColumns(TblRenombroCOLS,lstNuevosNombres),
                //incorporo una nueva col con el país..
                TablaFinal=Table.AddColumn(TablaCOLS, "Country", each lang)
            in 
                Table.Combine({state,TablaFinal})
    )
in
    anexado


Me interesa que nos detengamos en el 'paso clave':
...
    //paso clave para trasnformar texto como Tabla
	tabla="#""" & Expression.Identifier(current) & """",

	tbl=[MiTabla= Expression.Evaluate(tabla,#shared)],
	TablaMedia=tbl[MiTabla],    //Obtengo una Tabla a partir de un elemento texto
                ...

Empezamos a construir un literal de cómo entendería o nombraría el motor M a una de nuestras tablas:
Empleamos la función ya conocida Expression.Identifier, además, y esto es importante, concatemos el texto con el caracter almohadilla!!.
En el paso siguiente, creamos un registro asignándole como valor el objeto obtenido al aplicar Expression.Evaluate, que transforma el texto en el objeto que representa, una tabla en el ejemplo.

MUY importante la identificación de los 'contextos'.
Acabamos recuperando el objeto cargado en el registro, siendo ya una tabla al 100%.

El bucle aplicado con List.Accumulate se encarga de ir anexando una tabla trsa otra...

Obviamente este no es el mejor método para anexar tablas... pero bajo ciertas condiciones, el método puede ser interesante.
Abierto a escuchar comentarios y sugerencias de mejora. ;-)

No hay comentarios:

Publicar un comentario

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