Un ejercicio interesante para proyectar cantidades hacia el futuro, generando las fechas de la nada (o 'casi').
Imagina que tienes un listado de proveedores con unas condiciones pactadas de pago distribuidas a lo largo del año...
Fíjate en la imagen como partimos de una tabla sin fechas, pero con una referencia temporal, que nos permite la distribución de los pagos a lo largo del año: campo 'Meses pago'.
Distribución o proyección que haremos en este caso para dos años {2022,2023}, suponiendo un reparto del 'Importe total' a partes iguales cada año!!.
Ejemplo, para un proveedor debemos repartir 100 eur/año en dos pagos anuales, los meses 2 y 5...
Por tanto las fechas del reparto para el 2022 y 2023 serían:
05/02/2022, 05/05/2022, 05/02/2023, 05/05/2023
e importes de 50 eur por fecha, esto es, 100 eur cada año
Veamos el código en lenguaje M, sabiendo que nuestra tabla se llama 'Tabla1':
El aspecto clave de este código, y lo que nos permite generar la secuencia de fechas, dada por los 'Meses de pago', tantas veces como años hayamos dispuesto, es el uso de la función List.TransformMany:
List.TransformMany(list as list, collectionTransform as function, resultTransform as function) as list
Esta es una de esas funciones 'complicadas' de interpretar, pero tremendamente potentes (como List.Generate o List.Accumulate entre otras).
¿Qué hace y cómo funciona List.TransformMany??
Trabaja a partir de dos series o listas... y recorre o aplica una transformación elemento a elemento de una lista sobre los elementos de la primera... ¿raro de explicar o entender?.
Pongamos un ejemplo simple...
Tenemos un listado de nombres y otro de apellidos... y queremos obtener las combinaciones posibles de los nombres con apellidos.
Por tanto recorreremos cada Apellido, uniéndolo con cada Nombre:
El código toma el primer apellido de la lista: 'Romero' y aplica una acción empleando cada elemento de la segunda lista (los nombres')... por tanto tendríamos: Ismael Romero, Raquel Romero.
Seguidamente iríamos al segundo apellido de la lista y le volvería a aplicar los nombres de la segunda lista: Ismael Sánchez, Raquel Sánchez.
Concluiría el proceso con el tercer apellido, aplicando nuevamente los dos nombres: Ismael García, Raquel García.
Lo vemos en el resultado devuelto del ejemplo anterior:
Para nuestro ejemplo de proyectar fechas, la función List.TransformMany nos va a permitir generar la misma secuencia de fechas (por los Meses de pago) para cada uno de los años dados en nuestra segunda lista {2022,2023}... tal como necesitamos.
Fíjate en la estructura base aplicada:
AddListaFechas = Table.AddColumn(Origen, "FechasPago", each List.Sort(List.TransformMany( Text.Split(Text.From([Meses pago]),"|")??[Meses pago], (año)=> {2022,2023}, (mp,año)=> #date(año, Number.From(mp), 5))))
Sobre todo en la parte 'profunda' donde usamos List.TransformMany:
List.TransformMany(
Text.Split(Text.From([Meses pago]),"|")??[Meses pago],
(año)=> {2022,2023},
(mp,año)=> #date(año, Number.From(mp), 5))
Impresionante función ;-)
Otro aspecto curioso es cómo unimos el resultado de dos listas en una tabla.
Una vez generadas las dos listas, empleamos List.Zip para tener pares de elementos 'unidos'...
Y finalmente, sobre esa lista de listas que nos devuelve List.Zip, aplicamos Table.FromRows para convertirla en una tabla y poder retornar el resultado deseado...
Imagina que tienes un listado de proveedores con unas condiciones pactadas de pago distribuidas a lo largo del año...
Fíjate en la imagen como partimos de una tabla sin fechas, pero con una referencia temporal, que nos permite la distribución de los pagos a lo largo del año: campo 'Meses pago'.
Distribución o proyección que haremos en este caso para dos años {2022,2023}, suponiendo un reparto del 'Importe total' a partes iguales cada año!!.
Ejemplo, para un proveedor debemos repartir 100 eur/año en dos pagos anuales, los meses 2 y 5...
Por tanto las fechas del reparto para el 2022 y 2023 serían:
05/02/2022, 05/05/2022, 05/02/2023, 05/05/2023
e importes de 50 eur por fecha, esto es, 100 eur cada año
Veamos el código en lenguaje M, sabiendo que nuestra tabla se llama 'Tabla1':
let
Origen = Excel.CurrentWorkbook(){[Name="Tabla1"]}[Content],
//Creamos una lista de fechas ordenadas a partir del detalle
//del campo 'Meses pago'
//emplearemos List.TransformMany para ello
AddListaFechas = Table.AddColumn(Origen,
"FechasPago",
each List.Sort(List.TransformMany(
Text.Split(Text.From([Meses pago]),"|")??[Meses pago],
(año)=> {2022,2023},
(mp,año)=> #date(año, Number.From(mp), 5)))),
//Con List.Repeat generamos una Lista de importes,
//uno por cada fecha.
//Para luego unirlo en una tabla junto a las fechas anteriores
AddImportesPagoUltimo =
Table.AddColumn(AddListaFechas,
"ImportePago",
each Table.FromRows(
List.Zip({[FechasPago],
List.Repeat({[Importe total]/[Num pagos]},List.Count({2022,2023})*[Num pagos])}),{"Fecha","Importe"} ) ),
ColumnasQuitadas = Table.RemoveColumns(AddImportesPagoUltimo,{"FechasPago"}),
//Expandimos los datos de las tablas
ExpandeFechas = Table.ExpandTableColumn(ColumnasQuitadas, "ImportePago", {"Fecha", "Importe"}, {"Fecha", "Importe"}),
TiposCambiados = Table.TransformColumnTypes(ExpandeFechas,{{"Importe total", Currency.Type}, {"Fecha", type date}, {"Importe", Currency.Type}})
/*
//Si quisieramos verlo dinamizado...
ColumnaDinamizada = Table.Pivot(
Table.TransformColumnTypes(TiposCambiados, {{"Fecha", type text}}, "es-ES"),
List.Sort(List.Distinct(Table.TransformColumnTypes(TiposCambiados, {{"Fecha", type text}}, "es-ES")[Fecha])),
"Fecha",
"Importe")
*/
in
TiposCambiadosEl aspecto clave de este código, y lo que nos permite generar la secuencia de fechas, dada por los 'Meses de pago', tantas veces como años hayamos dispuesto, es el uso de la función List.TransformMany:
List.TransformMany(list as list, collectionTransform as function, resultTransform as function) as list
Esta es una de esas funciones 'complicadas' de interpretar, pero tremendamente potentes (como List.Generate o List.Accumulate entre otras).
¿Qué hace y cómo funciona List.TransformMany??
Trabaja a partir de dos series o listas... y recorre o aplica una transformación elemento a elemento de una lista sobre los elementos de la primera... ¿raro de explicar o entender?.
Pongamos un ejemplo simple...
Tenemos un listado de nombres y otro de apellidos... y queremos obtener las combinaciones posibles de los nombres con apellidos.
Por tanto recorreremos cada Apellido, uniéndolo con cada Nombre:
let
Origen = List.TransformMany(
{"Romero","Sánchez","García"},
(nombre)=> {"Ismael", "Raquel"},
(apellido, nombre)=> nombre & " " & apellido)
in
OrigenEl código toma el primer apellido de la lista: 'Romero' y aplica una acción empleando cada elemento de la segunda lista (los nombres')... por tanto tendríamos: Ismael Romero, Raquel Romero.
Seguidamente iríamos al segundo apellido de la lista y le volvería a aplicar los nombres de la segunda lista: Ismael Sánchez, Raquel Sánchez.
Concluiría el proceso con el tercer apellido, aplicando nuevamente los dos nombres: Ismael García, Raquel García.
Lo vemos en el resultado devuelto del ejemplo anterior:
Para nuestro ejemplo de proyectar fechas, la función List.TransformMany nos va a permitir generar la misma secuencia de fechas (por los Meses de pago) para cada uno de los años dados en nuestra segunda lista {2022,2023}... tal como necesitamos.
Fíjate en la estructura base aplicada:
AddListaFechas = Table.AddColumn(Origen, "FechasPago", each List.Sort(List.TransformMany( Text.Split(Text.From([Meses pago]),"|")??[Meses pago], (año)=> {2022,2023}, (mp,año)=> #date(año, Number.From(mp), 5))))
Sobre todo en la parte 'profunda' donde usamos List.TransformMany:
List.TransformMany(
Text.Split(Text.From([Meses pago]),"|")??[Meses pago],
(año)=> {2022,2023},
(mp,año)=> #date(año, Number.From(mp), 5))
Impresionante función ;-)
Otro aspecto curioso es cómo unimos el resultado de dos listas en una tabla.
Una vez generadas las dos listas, empleamos List.Zip para tener pares de elementos 'unidos'...
Y finalmente, sobre esa lista de listas que nos devuelve List.Zip, aplicamos Table.FromRows para convertirla en una tabla y poder retornar el resultado deseado...




No hay comentarios:
Publicar un comentario
Nota: solo los miembros de este blog pueden publicar comentarios.