¡Jueves de post! Hoy os traigo la sesión que realicé el fin de semana en el Global Power Platform Bootcamp 2023. Qué no sé si sabéis pero fue un fin de semana espectacular para la comunidad de Power Platform. Tuve el honor de poder colaborar con las comunidades de Colombia, Nicaragua, Paraguay, Lima y Euskadi. Como sabéis, desde comienzos de año, soy co-organizador del grupo de Power Platform Euskadi, me gustaría agradecer a todo el equipo el que me hayan ayudado para poder estar en todas y cada una de las comunidades anteriores. 

Gracias: Inés Pascual, Cristina Tarabini-Castellani, Nagore Landa, David Uyarra y Carlos Cantero


Ahora, vamos con la sesión:

 

¿Qué es un dataflows?



Un dataflow es una colección de tabla/s que se crean y
administran en las áreas de trabajo del servicio Power BI, es decir, en la
nube. Además pueden ser reutilizados en otros conjuntos de datos ahorrando al
usuario tiempo en el desarrollo de los modelos.

De otra forma, los dataflows son la herramienta de ETL en la nube, es decir,
nuestro Power Query Online que nos permite realizar todas nuestras
transformaciones para su posterior uso. 

 

 
 
 

Ventajas de uso



Crear una lógica de transformación reutilizable que puedan
compartir muchos conjuntos de datos e informes en Power BI à Por ejemplo, nuestra
querida dimensión tiempo.





Crear una única fuente de la verdad al obligar a los analistas a conectarse a
los flujos de datos, en lugar de conectarse a los sistemas subyacentes y que
cada uno haga su proceso de ETL à
O lo que es lo mismo, creación de un almacén de datos





Impedir que los analistas tengan acceso directo al origen de datos subyacente. à Tener separado el
origen de datos del conjunto de datos.



Nos permite un control sencillo del Query Folding (el
plegado de consultas) à
Es decir, es la capacidad de una consulta de Power Query para generar una única
instrucción de consulta para recuperar y transformar los datos de origen.



….. Muchísimas más …..



 



Paso 1: Creamos el dataflow

 


 



Paso 2: Creamos una consulta en blanco para calcular
la fecha fin del año actual. Para ello:

 



let





//Extraigo el año del sistema





Año = Date.Year(DateTime.LocalNow()),





// Convierto en texto y concateno el año al texto 31/12/





Fecha = Text.From("31/12/") & Text.From(Año),





// Convierto en fecha el texto del paso anterior





FechaFin = Date.FromText(Fecha)





in





FechaFin




 



Paso 3: Creamos la fecha inicio. Podemos hacerlo de
la misma manera que la fecha fin o creamos un parámetro. A mí me gusta hacerlo
de esta manera, por el siguiente motivo. La fecha inicio la trato como fija en
el dataflow, y en función la necesidad del modelo, traigo más o menos
información, en cambio la fecha fin, tiene que ser dinámica, sino cada año
habría que modificar el dataflow.

 

 
 
 

Paso 4: Ahora lo que hacemos es generar una consulta
en blanco con el número de días existentes entre la fecha inicio y fecha fin.
¿Cómo lo calculamos? Pues muy sencillo, con la función Duration.Days que nos
extrae el número de días entre dos fechas.



¡OJO! Falta sumar uno ya que la diferencia entre las
dos fechas no incluye a una de ellas y necesitamos los días totales



 



let



 // Calculamos el intervalo de dias



 DiasIntervalo = Duration.Days( FechaFin -
FechaInicio) +
1 ,



 

Paso 5: Creamos una lista con todos los valores que
existen desde la fecha de inicio a la fecha de fin. Para ello usamos la función
List.Dates:



 






La función: #durations (0,0,0,0)



 






 // listamos las fechas del intervalo



 Fecha = List.Dates(FechaInicio,DiasIntervalo,
#duration(
1,0,0,0)),



 



Paso 6: La lista que acabamos de crear, debemos
transformarla en una tabla. Para ello podemos hacerlo de dos maneras distintas.



 



1.  
Con la interfaz de usuario



2.  
Con código M.



 



//  Convertimos en tabla la lista



   #"Convertido en tabla" =
Table.FromList(Fecha, Splitter.SplitByNothing(),
null, null,
ExtraValues.Error),



 



Paso 7: Renombramos la columna a Fecha



 



// Cambiamos el nombre de la columna 1



   #"Columnas con nombre
cambiado" = Table.RenameColumns(#"Convertido en tabla", {{
"Column1", "Fecha"}}),



 



Paso 8: Transformamos el tipo de dato de la columna
ya que Power Query nos lo ha categorizado como Cualquiera y nosotros queremos
que sea tipo fecha.



 



// Cambiamos el tipo de la columna



 #"Tipo de columna
cambiado" = Table.TransformColumnTypes(#"Columnas con nombre
cambiado", {{
"Fecha", type date}}),



 



Paso 9: Extraemos el año



Aquí, vamos a modificar el código M que nos ha
generado Power Query, ya que nos ha categorizado la columna año como número
decimal, y el año, en mi pueblo es un número entero de toda la vida. Así además
ayudamos al motor para la compresión. Para ello:



 



// Extraemos el año



  #"Año insertado" =
Table.AddColumn(#"Tipo de columna cambiado",
"Año", each
Date.Year([Fecha]), Int64.Type),



 



Paso 10: Una vez ya tenemos el año, generamos la
columna del mes. Hacemos como con la columna de año y modificamos el tipo de
dato.



 



// Extraemos el mes



 #"Mes insertado" =
Table.AddColumn(#"Año insertado",
"Mes", each
Date.Month([Fecha]), Int64.Type),



  

Paso 11: Extraemos el nombre del mes



 

// Insertamos el nombre del mes



 #"Nombre del mes
insertado" = Table.AddColumn(#"Mes insertado",
"Nombre
del mes"
, each
Date.MonthName([Fecha]),
type nullable text),



 



Paso 12: En el caso que queramos colocar el nombre
del mes en otra cultura, por ejemplo, inglés, basta con añadirle al código M lo
siguiente:

 



// Insertamos el nombre del mes en ingles 

  #"Nombre del mes insertado
1" = Table.AddColumn(#"Nombre del mes insertado",
"Nombre
del mes ingles"
, each
Date.MonthName([Fecha],
"en-US"), type
nullable
text),



 



Paso 13: Extraemos el número del día.



 



// Insertamos el número del día



   #"Día insertado" =
Table.AddColumn(#"Nombre del mes insertado 1",
"Día", each
Date.Day([Fecha]), Int64.Type),



 



Paso 14: Extremos el nombre del día desde la columna
Fecha:



 



// Insertamos el nombre del día



   #"Nombre del día
insertado" = Table.AddColumn(#"Día insertado",
"Nombre
del día"
, each
Date.DayOfWeekName([Fecha]),
type nullable text),



 



Paso 15: Extraemos el nombre del día en inglés



 



// Insertamos el nombre del día en inglés



   #"Nombre del día insertado
1" = Table.AddColumn(#"Nombre del día insertado",
"Nombre
del día ingles"
, each
Date.DayOfWeekName([Fecha],
"en-US"), type
nullable
text),



 



Paso 16: Ahora, una buena práctica, es convertir la
fecha en un ID único de número entero, de manera que la compresión sea mejor
que con columnas de tipo Fecha o Fecha y Hora. Para ello al año debemos
multiplicarlo por 10.000, el mes por 100 y sumar el año, mes y día.



 



// Convertimos la fecha en un número
entero multiplicando y sumando el año * 10000, el mes * 100 y el día * 1



   #"Personalizado agregado"
= Table.TransformColumnTypes(Table.AddColumn(#"Nombre del día insertado
1",
"IdFecha", each
[Año]*
10000+[Mes]*100+[Día]),
{{
"IdFecha", Int64.Type}}),



 



Paso 17: Ahora, vamos a obtener el número entero que
corresponde al campo fecha, de manera que nos sirva a futuro para calcular
desviaciones de manera sencilla, por ejemplo, saber si la fecha es una fecha
pasada o futura. Como sabemos, las columnas de fecha, para Power Query, son
números enteros y la hora son números decimales.



 



// Obtenemos el número entero de la fecha
y lo nombramos como IdFechaEntero



   #"Personalizado agregado
1" = Table.TransformColumnTypes(Table.AddColumn(#"Personalizado
agregado",
"IdFechaEntero", each
Number.From([Fecha])), {{
"IdFechaEntero",
Int64.Type}}),



 



Paso 18: Ahora, calculamos el día actual, es decir,
el día de hoy para ello. ¡Atención! Depende de la franja horaria en la que nos
encontremos, hay un desvío con el número obtenido. Si estamos con la hora por
debajo de las 12:00 del mediodía, Power Query lo redondea hacia abajo pero si
hemos sobrepasado las 12:00 del mediodía Power Query lo redondea hacia arriba (
y esto no nos interesa ). ¿Cómo lo solucionamos? Basta con modificar el código
M para que redondee hacia debajo de manera que si pasamos las 12:00 del
mediodía no nos distorsione.



 



 



// Calculamos el día actual, redondeando
hacia abajo de manera que evitemos la desviación con la hora



   #"Personalizado agregado
2" = Table.TransformColumnTypes(Table.AddColumn(#"Personalizado
agregado 1",
"Hoy", each
Number.RoundDown(Number.From(DateTime.LocalNow()))), {{
"Hoy",
Int64.Type}}),



 



Paso 19: Obtenemos el número del día de la semana.
Sumamos 1 ya que sino empieza en 0 el lunes y no en 1 como queremos.



 



// Insertamos el día de la semana y le
sumamos 1 para que empiece el lunes en 1



   #"Día de la semana
insertado" = Table.AddColumn(#"Personalizado agregado 2",
"Día
de la semana"
, each
Date.DayOfWeek([Fecha])+
1, Int64.Type),



 



Paso 20: Calculamos si es laborable o no. Partiendo
de que para este modelo de Lunes a Viernes son Laborables mientras que sábado y
domingo son festivos. Para ello añadimos una columna condicional.



 



// Calculamos si es laborale o festivo
(fin de semana)



   #"Columna condicional
insertada" = Table.AddColumn(#"Día de la semana insertado",
"Laborable", each if
[Día de la semana] <=
5 then "Laborable" else "Festivo", type text),



 



Paso 21: Calculamos el trimestre del año. Power
Query nos lo crea como número, por lo que le cambiamos el formato a Int64.Type



 



// Insertamos el trimestre del año



   #"Trimestre insertado" =
Table.AddColumn(#"Columna condicional insertada",
"Trimestre", each
Date.QuarterOfYear([Fecha]), Int64.Type),



 



Paso 22: Si queremos el trimestre con el T1, T2,
etc.,…  Debemos concatenar a la columna
de Trimestre la letra T. Para ello:



 



// Insertamos el trimestre del año
concatenando la T y convirtiendo en texto



   #"Trimestre insertado 1"
= Table.AddColumn(#"Trimestre insertado",
"Trimestre
TX"
, each "T"
& Text.From(Date.QuarterOfYear([Fecha])),
type text),



 



Paso 23: Si queremos calcular el trimestre del año,
es tan sencillo como modificar el código M del paso anterior:



 



// Insertamos el trimestre del año
concatenando la Q y convirtiendo en texto  



   #"Trimestre insertado 2"
= Table.AddColumn(#"Trimestre insertado 1",
"Trimestre
QX"
, each "Q"
& Text.From(Date.QuarterOfYear([Fecha])),
type text),



 



Paso 24: Calculamos el año actual, de cara a
calcular los posibles desvíos y lo colocamos como Int64.



 



// Calculamos el año actual



   #"Personalizado agregado
3" = Table.TransformColumnTypes(Table.AddColumn(#"Trimestre insertado
2",
"AñoActual", each
Date.Year(DateTime.LocalNow())), {{
"AñoActual",
Int64.Type}}),



 



Paso 25: Hacemos lo mismo para el mes actual.



 



// Calculamos el mes actual



   #"Personalizado agregado
4" = Table.TransformColumnTypes(Table.AddColumn(#"Personalizado
agregado 3",
"MesActual", each
Date.Month(DateTime.LocalNow())), {{
"MesActual",
Int64.Type}}),



 



Paso 26: Realizamos el mismo procedimiento para el
cálculo del día actual.



 



// Calculamos el día actual



   #"Personalizado agregado
5" = Table.TransformColumnTypes(Table.AddColumn(#"Personalizado
agregado 4",
"DiaActual", each
Date.Day(DateTime.LocalNow())), {{
"DiaActual",
Int64.Type}}),



 



Paso 27: Calculamos el desvío del año. Esto nos va a
aportar mucho dinamismo en los filtros. Para ello, a la columna año le restamos
la columna de año actual.



 



// Calculamos el desvío del año



   #"Personalizado agregado
6" = Table.TransformColumnTypes(Table.AddColumn(#"Personalizado
agregado 5",
"DesvioAño", each
[Año] - [AñoActual]), {{
"DesvioAño",
Int64.Type}}),



 



Paso 28: Calculamos el desvío del mes. Esto nos va a
aportar mucho dinamismo en los filtros. Para ello, a la columna mes le restamos
la columna de año actual y SUMAMOS la columna DesvíoAño*12



 



// Calculamos el desvío del mes



   #"Personalizado agregado
7" = Table.TransformColumnTypes(Table.AddColumn(#"Personalizado
agregado 6",
"DesvioMes", each
[Mes]-[MesActual]+([DesvioAño]*
12)), {{"DesvioMes",
Int64.Type}}),



 



 



Paso 29: Calculamos el desvío del día restando a la
columna IdFechaEntero la columna Hoy.



 



// Calculamos el desvío del día



   #"Personalizado agregado
8" = Table.TransformColumnTypes(Table.AddColumn(#"Personalizado
agregado 7",
"DesvioDia", each
[IdFechaEntero] - [Hoy]), {{
"DesvioDia",
Int64.Type}}),



 



Paso 30: Calculamos trimestre actual que nos va a
servir para realizar los cálculos de desvíos



 



// Calculamos el trimestre actual



   #"Personalizado agregado
9" = Table.TransformColumnTypes(Table.AddColumn(#"Personalizado
agregado 8",
"TrimestreActual", each
Date.QuarterOfYear(DateTime.LocalNow())), {{
"TrimestreActual",
Int64.Type}}),



 



 



Paso 31: Calculamos el desvío del trimestre. Esto
nos va a aportar mucho dinamismo en los filtros. Para ello, a la columna trimestre
le restamos la columna de trimestre actual y SUMAMOS la columna DesvíoAño*4



 



// Calculamos el desvío del trimestre



   #"Personalizado agregado
10" = Table.TransformColumnTypes(Table.AddColumn(#"Personalizado
agregado 9",
"DesvioTrimestre", each
[Trimestre]-[TrimestreActual]+([DesvioAño]*
4)),
{{
"DesvioTrimestre",
Int64.Type}}),



 



Paso 32: Insertamos mediante la interfaz de usuario
la semana



 



// Insertamos la semana actual mediante la
interfaz



   #"Semana del año
insertada" = Table.AddColumn(#"Personalizado agregado 10",
"Semana
del año"
, each
Date.WeekOfYear([Fecha]), Int64.Type),



 



Paso 33: Calculamos la semana ISO, mediante una
adaptación de la fórmula conocida como Ron de Bruin.



 



// Insertamos la semana ISO (Adaptación de
la fórmula de Ron de Bruin)



   #"Personalizado agregado
11" = Table.TransformColumnTypes(Table.AddColumn(#"Semana del año
insertada",
"SemanaISO", each if
 Number.RoundDown((Date.DayOfYear([Fecha])-(Date.DayOfWeek([Fecha],
Day.Monday)+
1)+10)/7)=0 



then 



   
Number.RoundDown((Date.DayOfYear(#date(Date.Year([Fecha])
-1,12,31))-(Date.DayOfWeek(#date(Date.Year([Fecha])-1,12,31),
Day.Monday)+
1)+10)/7



else if



   
(Number.RoundDown((Date.DayOfYear([Fecha])-(Date.DayOfWeek([Fecha],
Day.Monday)+
1)+10)/7)=53
and (Date.DayOfWeek(#date(Date.Year([Fecha]),
12,31),
Day.Monday)+
1<4)) 



then 1 



else 



  
Number.RoundDown((Date.DayOfYear([Fecha])-(Date.DayOfWeek([Fecha], Day.Monday)+
1)+10)/7)),
{{
"SemanaISO",
Int64.Type}})



 



in



#"Personalizado agregado 11"



 

 Y con esto llegamos al final de la sesión que presenté en el GPPB 2023. Aquí abajo os dejo el video por si queréis verlo.

 


 



¡Nos vemos en los datos!