Selector de dates dinàmic a Power BI

Al món de l’anàlisi de dades amb Power BI, la selecció eficient de dates és crucial per a una visualització i manipulació de dades efectiva. No obstant això, Power BI no té un selector de dates integrat que compleixi les expectatives d’usabilitat de la majoria dels usuaris. Aquest tutorial proporciona una guia pas a pas per crear un selector de dates personalitzat al Power BI, superant les limitacions del selector per defecte.

1.- Taula d’Última Actualització: Per començar, generem una taula a l’editor de Power Query que captura l’última data i hora d’actualització de l’informe. És essencial considerar el fus horari local per assegurar la precisió en publicar a Power BI Service. A continuació, es presenta el codi de Power Query necessari per a aquesta tasca:

let

date = DateTime.Date(DateTimeZone.SwitchZone(DateTimeZone.UtcNow(),+1,0)),
time = DateTime.Time(DateTimeZone.SwitchZone(DateTimeZone.UtcNow(),+1,0)),
//+1 hora para obtener hora de invierno de España respecto a hora UTC.


firstSundayOfNovember = Date.StartOfWeek(#date(Date.Year(date), 11, 7), Day.Sunday),
SecondSundayOfMarch = Date.StartOfWeek(#date(Date.Year(date), 3, 14), Day.Sunday),


isSummerTime =  (date = SecondSundayOfMarch and time >= #time(1,0,0))
          or
    (date > SecondSundayOfMarch and date < firstSundayOfNovember) 
    or 
    (date = firstSundayOfNovember and time >= #time(1,0,0)),


timeZone = (Number.From(isSummerTime))*1, 
//sumamos una hora para el horario de verano en el huso horario de España


ltime = 
            DateTime.From(date) 
            + #duration(0,Time.Hour(time),Time.Minute(time),Time.Second(time))  
            + #duration(0, timeZone, 0, 0),
    #"Convertida en tabla" = #table(1, {{ltime}}),
    #"Columnas con nombre cambiado" = Table.RenameColumns(#"Convertida en tabla",{{"Column1", "UltimaActualización"}}),
    #"Tipo cambiado" = Table.TransformColumnTypes(#"Columnas con nombre cambiado",{{"UltimaActualización", type datetime}})
in
    #"Tipo cambiado"

2.- Creació d’un Calendari Independent: El pas següent és crear un calendari en Power Query que s’utilitzarà en les mesures de l’informe2. Aquest calendari ha de romandre sense vincular altres taules al model. El codi M per a la creació del calendari és el següent:

let
    Source = #date(2018, 1, 1), 
    FechaFinal = #date(Date.Year(DateTime.LocalNow()),12,31),
    ListaInicioFinal = {Number.From(Source)..Number.From(FechaFinal)},
    #"Converted to Table" = Table.FromList(ListaInicioFinal, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
    #"Changed Type" = Table.TransformColumnTypes(#"Converted to Table",{{"Column1", type date}}),
    #"Renamed Columns" = Table.RenameColumns(#"Changed Type",{{"Column1", "Fecha"}}),
    #"Added Custom Column" = Table.AddColumn(#"Renamed Columns", "Custom", each Text.Combine({Date.ToText([Fecha], "yyyy"), Date.ToText([Fecha], "MM"), Date.ToText([Fecha], "dd")}), type text),
    #"Inserted Year" = Table.AddColumn(#"Added Custom Column", "Year", each Date.Year([Fecha]), Int64.Type),
    #"Inserted Quarter" = Table.AddColumn(#"Inserted Year", "Quarter", each Date.QuarterOfYear([Fecha]), Int64.Type),
    #"Inserted Month" = Table.AddColumn(#"Inserted Quarter", "Month", each Date.Month([Fecha]), Int64.Type),
    #"Inserted Day" = Table.AddColumn(#"Inserted Month", "Day", each Date.Day([Fecha]), Int64.Type),
    #"Inserted Merged Column" = Table.AddColumn(#"Inserted Day", "Merged", each Text.Combine({"T", Text.From([Quarter], "es-MX")}), type text),
    #"Inserted Month Name" = Table.AddColumn(#"Inserted Merged Column", "Month Name", each Date.MonthName([Fecha]), type text),
    #"Inserted First Characters" = Table.AddColumn(#"Inserted Month Name", "First Characters", each Text.Start([Month Name], 3), type text),
    #"Inserted Day of Week" = Table.AddColumn(#"Inserted First Characters", "Day of Week", each Date.DayOfWeek([Fecha]), Int64.Type),
    #"Inserted Week of Year" = Table.AddColumn(#"Inserted Day of Week", "Week of Year", each Date.WeekOfYear([Fecha]), Int64.Type),
    #"Inserted Week of Month" = Table.AddColumn(#"Inserted Week of Year", "Week of Month", each Date.WeekOfMonth([Fecha]), Int64.Type),
    #"Inserted End of Week" = Table.AddColumn(#"Inserted Week of Month", "End of Week", each Date.EndOfWeek([Fecha],Day.Monday), type date),
    #"Inserted Day of Year" = Table.AddColumn(#"Inserted End of Week", "Day of Year", each Date.DayOfYear([Fecha]), Int64.Type),
    #"Inserted Day Name" = Table.AddColumn(#"Inserted Day of Year", "Day Name", each Date.DayOfWeekName([Fecha]), type text),
    #"Inserted First Characters1" = Table.AddColumn(#"Inserted Day Name", "First Characters.1", each Text.Start([Day Name], 3), type text),
    #"Inserted Merged Column1" = Table.AddColumn(#"Inserted First Characters1", "Merged.1", each Text.Combine({Text.From([Year], "es-MX"), [Merged]}, "/"), type text),
    #"Inserted First Characters2" = Table.AddColumn(#"Inserted Merged Column1", "First Characters.2", each Text.Start([Custom], 6), type text),
    #"Split Column by Position" = Table.SplitColumn(#"Inserted First Characters2", "First Characters.2", Splitter.SplitTextByPositions({0, 4}, false), {"First Characters.2.1", "First Characters.2.2"}),
    #"Merged Columns" = Table.CombineColumns(#"Split Column by Position",{"First Characters.2.1", "First Characters.2.2"},Combiner.CombineTextByDelimiter("/", QuoteStyle.None),"Merged.3"),
    #"Inserted Merged Column2" = Table.AddColumn(#"Merged Columns", "Merged.2", each Text.Combine({Text.From([Year], "es-MX"), "/", [First Characters]}), type text),
    #"Replaced Value" = Table.ReplaceValue(#"Inserted Merged Column2",0,7,Replacer.ReplaceValue,{"Day of Week"}),
    #"Renamed Columns1" = Table.RenameColumns(#"Replaced Value",{{"Custom", "FechaSK"}, {"Year", "#Año"}, {"Quarter", "#Trimestre"}, {"Month", "#Mes"}, {"Day", "#Día"}, {"Merged", "Trimestre"}, {"Month Name", "Mes"}, {"First Characters", "MesCorto"}, {"Day of Week", "#DíaSemana"}, {"Week of Year", "#SemanaAño"}, {"Week of Month", "#SemanaMes"}, {"End of Week", "CierreSemana"}, {"Day of Year", "#DíaAño"}, {"Day Name", "Día"}, {"First Characters.1", "DíaCorto"}, {"Merged.1", "AñoTrimestre"}, {"Merged.3", "Año#Mes"}, {"Merged.2", "AñoMesCorto"}}),
    #"Tipo cambiado" = Table.TransformColumnTypes(#"Renamed Columns1",{{"Fecha", type date}}),
    #"Columna duplicada" = Table.AddColumn(#"Tipo cambiado", "Fecha - Copia", each [Fecha], type date),
    #"Columnas quitadas" = Table.RemoveColumns(#"Columna duplicada",{"Fecha"}),
    #"Columnas con nombre cambiado" = Table.RenameColumns(#"Columnas quitadas",{{"Fecha - Copia", "Fecha"}})
in
    #"Columnas con nombre cambiado"

3.- Definició de Períodes Seleccionables amb DAX: Un cop establertes la taula de calendari i la data d’actualització, passem a DAX per crear diferents períodes seleccionables com ara “Avui”, “Aquesta setmana”, “Aquest mes”, entre d’altres. Utilitzem una nova taula a la vista de taules de Power BI i creem la següent estructura amb DAX:

Periodos = UNION(
            ADDCOLUMNS(
            CALENDAR(                                 
                MAX('ÚltimaActualización'[UltimaActualización]) - WEEKDAY(MAX('ÚltimaActualización'[UltimaActualización]), 1) + 2,    
                MAX('ÚltimaActualización'[UltimaActualización])  
            ),
            "Tipo", "Semana Hasta la Fecha",
            "Orden", 2
            ),    
            ADDCOLUMNS(
            CALENDAR(
                MAX('ÚltimaActualización'[UltimaActualización]) - WEEKDAY(MAX('ÚltimaActualización'[UltimaActualización]), 1) - 5,
                MAX('ÚltimaActualización'[UltimaActualización]) - WEEKDAY(MAX('ÚltimaActualización'[UltimaActualización]), 1) + 1
            ),
            "Tipo", "Semana Anterior",
            "Orden", 8
            ),
            ADDCOLUMNS(
            CALENDAR(
                date(year(MAX('ÚltimaActualización'[UltimaActualización])),month(MAX('ÚltimaActualización'[UltimaActualización])), 1),
                MAX('ÚltimaActualización'[UltimaActualización])
            ), 
            "Tipo", "Mes Hasta la Fecha",
            "Orden", 3
            ),
            ADDCOLUMNS(
            CALENDAR(
                date(year(MAX('ÚltimaActualización'[UltimaActualización])),month(MAX('ÚltimaActualización'[UltimaActualización]))-1, 1),
                EOMONTH(date(year(MAX('ÚltimaActualización'[UltimaActualización])),month(MAX('ÚltimaActualización'[UltimaActualización]))-1, 1),0)
            ), 
            "Tipo", "Mes Anterior",
            "Orden", 9
            ),
            ADDCOLUMNS(
            CALENDAR(
                date(year(MAX('ÚltimaActualización'[UltimaActualización])),month(MAX('ÚltimaActualización'[UltimaActualización])), 1),
                EOMONTH(MAX('ÚltimaActualización'[UltimaActualización]),0)
            ), 
            "Type", "Mes Actual",
            "Orden", 6
            ),
            ADDCOLUMNS(
            CALENDAR(
                date(year(MAX('ÚltimaActualización'[UltimaActualización])),1, 1),
                MAX('ÚltimaActualización'[UltimaActualización])
            ), 
            "Tipo", "Año Hasta la Fecha",
            "Orden", 4
            ),
            ADDCOLUMNS(CALENDAR(min(Calendario[Fecha]),max(Calendario[Fecha])),
         "Tipo", "Personalizado","Orden",10),
            ADDCOLUMNS(
            CALENDAR(
                date(year(MAX('ÚltimaActualización'[UltimaActualización]))-1,1, 1),
                date(year(MAX('ÚltimaActualización'[UltimaActualización]))-1,12, 31)
            ), 
            "Tipo", "Año Anterior",
            "Orden", 10
            ),
            ADDCOLUMNS(
            CALENDAR(
                date(year(MAX('ÚltimaActualización'[UltimaActualización])),1, 1),
                date(year(MAX('ÚltimaActualización'[UltimaActualización])),12, 31)
            ), 
            "Tipo", "Año Actual",
            "Orden", 7
        ),
        ADDCOLUMNS(
            CALENDAR(                                 
                MAX('ÚltimaActualización'[UltimaActualización]) - WEEKDAY(MAX('ÚltimaActualización'[UltimaActualización]), 1) + 2,    
        MAX('ÚltimaActualización'[UltimaActualización]) + (7 - WEEKDAY(MAX('ÚltimaActualización'[UltimaActualización]), 2))  
            ),
            "Tipo", "Semana Actual",
            "Orden", 5
        ),

        ADDCOLUMNS(
            CALENDAR(                                 
                MAX('ÚltimaActualización'[UltimaActualización]),
                MAX('ÚltimaActualización'[UltimaActualización])
            ),
            "Tipo", "Hoy",
            "Orden", 1
        )
)
Desplegable con los períodos seleccionables por el usuario

4.- Mesures per a l’Anàlisi de Períodes: És crucial emmagatzemar en una mesura el període seleccionat per l’usuari. Això ens permet identificar quan el període és personalitzat i, per tant, filtrar segons la selecció realitzada al calendari. Les mesures rellevants són:

Periodo Seleccionado = SELECTEDVALUE('Periodos'[Tipo])
 MinDate = if(ISFILTERED(Calendario[Fecha]) && [Periodo  Seleccionado] = "Personalizado", min(Calendario[Fecha]),min(Periodos[Date]))
MaxDate = if(ISFILTERED(Calendario[Fecha]) && [Periodo Seleccionado] = "Personalizado", max(Calendario[Fecha]), MAX(Periodos[Date]))
Periodo Analizado = [MinDate] & "-" & [MaxDate]

6.- Integració d’un Slider per a Selecció de Dates: Per tal que l’usuari pugui seleccionar un rang de dates personalitzat, incorporem un slider que permet seleccionar dates de manera interactiva. Aquest slider es vincula directament a la taula de Calendari que hem creat prèviament. Opcionalment, es poden configurar mitjançant adreces d’interès per mostrar o ocultar aquest calendari.

Selector de fechas personalizadas por el usuario

7.- Implementació de Mesures per a Visualitzacions: Amb les mesures anteriors, podem crear mesures que es faran servir en taules i gràfics. És important especificar sempre el filtre de data dins de la mesura, com es mostra al següent exemple:

Ventas Año Actual = 
CALCULATE(
    sum(FactTable[Importe]),
FILTER (FactTable, FactTable[fecha] <= [MaxDate] && FactTable[fecha] >= [MinDate]))

Seguint aquests passos, podreu implementar un selector de dates personalitzat a Power BI que millori significativament la interacció de l’usuari amb els informes. Aquest enfocament permet una selecció de dates més intuïtiva i adaptada a les necessitats específiques de lanàlisi de dades.

Segueix-nos

Comparteix l’entrada!