Skip to main content
cancel
Showing results for 
Search instead for 
Did you mean: 

Register now to learn Fabric in free live sessions led by the best Microsoft experts. From Apr 16 to May 9, in English and Spanish.

Dangar332

Creating Custom Calendars for Accurate Working Day Calculation in Power BI

Introduction

Have you ever tried to add holidays which lie between today (or any dates) to a specific date or the same kind of scenario?

If yeah Then this article helps you

 

Scenario

Recently, I faced a situation where I needed to add days to the current date (today) which depends on the total number of hours left for a particular employee.

Means employee A has 150 hours left and spent only 6-hour for one working day, then divide the hour by daily spend and find the date (forecast date) where employee A completed their task but did not include holidays and weekends.

Let’s consider employee X. Get 15 fore-cast days on the basis of the hours left. Those 15 days do not include weekends and holidays, which we need to add to the current date (today). Let’s consider Employee X got 3 days of weekend or public holiday out of 15 days, then it also needs to add in fore-cast days, which means now 15 days become 18 days.  If employee X's forecast date falls on a weekend or a holiday, it is also not applicable.

 

We take some data for solving scenario

 

Employee Table

Dangar332_0-1708608278565.png

 

Holiday Table

Dangar332_1-1708608294117.png

 

Logic behind solving this problem is we going to take a separate date table which will help for deriving fore-cast date and add new column of Holidays. After that we add a new column which give us a flag of 0 if Date in weekends or in holidays and 1 for date in working day after that we give rank according to flag with exclude of Flag 0.

 


We make a new date Table which particular Use for Fore-cast Date Using Below DAX Code

Here I am taking only 2024 Date field

 

fore-cast Datetable = 
ADDCOLUMNS(
    CALENDAR(
        TODAY(),
        DATE(2024,12,31)
    ),
    "weekday",
    WEEKDAY([Date],2),
    "Dayname",
    FORMAT([Date],"dddd")
)

 

 

Join holiday Table and fore-cast Date table using Date field

Dangar332_2-1708608351966.png

 

 

Make a new column (Holiday) in Fore-cast Date table which help us to bring only holiday date from holiday table to existing table

holiday = RELATED('Holiday Table'[holiday date])

 

 

Make another new column with some condition using Dax code which give Flag 0 for those date which are weekends and holidays and 1 for Working days.

workingday = 
IF(
    NOT('fore-cast Datetable'[weekday]) in {6,7},
    IF(
        'fore-cast Datetable'[holiday]<>BLANK(),
        0,
        1
    ),
    0
)

 

 

Add column Which Give day no from Today with ignoring Weekends and holidays

Day Number = 
RANKX(
    FILTER(
        ALL('fore-cast Datetable'[Date],'fore-cast Datetable'[workingday]),
        'fore-cast Datetable'[workingday]<>0
    ),
    'fore-cast Datetable'[Date],,ASC
)

 

 

Our main goal is taking Days on behalf of Hours and find those date which is equivalent to left days from today with ignoring weekends and holidays. Day Number column give us that ability

 

 

Fore-cast date table Look like below

Dangar332_3-1708608482930.png

 

 

Now make a new column in employee table

Forecast date column = 
var a =FLOOR((Employee[Hour left]/6),1)
return
MAXX(
    FILTER(
        ALL('fore-cast Datetable'[Date],'fore-cast Datetable'[Day Number]),
        'fore-cast Datetable'[Day Number]=a
    ),
    'fore-cast Datetable'[Date]
)

 

 

We can make measure with little bit changes

fore-cast date using measure = 
var a = FLOOR(SUM(employee[hour left])/6,1)
return
MAXX(
    FILTER(
        ALL('fore-cast Datetable'[Date],'fore-cast Datetable'[Day Number]),
        'fore-cast Datetable'[Day Number]=a
    ),
    'fore-cast Datetable'[Date]
)

 

 

Make a table visual

Dangar332_4-1708608907456.png

 

 

If you don’t want to add new table to your Existing data model

We can also achieve Without fore-cast date table by creating it on fly.

 


Use below Dax code for column

fore-cast date without table refrence = 
var a = FLOOR(('Employee'[Hour left]/6),1)
var b =NETWORKDAYS(TODAY(),TODAY()+a,1)
var c = ADDCOLUMNS(
             CALENDAR(TODAY(),TODAY()+a+b),
             "weekday",
             WEEKDAY([Date],2),
             "dayname",FORMAT([Date],"dddd"),
             "publikholiday",LOOKUPVALUE('Holiday Table'[Holiday Date],[holiday date],[Date]),
             "holidaycondition",
                     var a1 = IF(
                                 not(WEEKDAY([Date],2)) in {6,7},
                                 IF(
                                       LOOKUPVALUE('Holiday Table'[Holiday Date],[holiday date],[Date])<>BLANK(),
                                       0,
                                       1
                                 ),
                                 0
                              )
              RETURN
              a1
        )
var f = ADDCOLUMNS(c,"rank",RANKX(FILTER(c,[holidaycondition]<>0),[Date],,ASC))
var e= MINX(FILTER(f,[rank]=a),[Date])
return
e

 

 

here little bit changes in above code for measure


Use below code for measure

fore-cast date measurewithout table refrence = 
var a = FLOOR(sum(employee[hour left])/6,1)
var b =NETWORKDAYS(TODAY(),TODAY()+a,1)
var c =ADDCOLUMNS(
          CALENDAR(TODAY(),TODAY()+a+b),
              "weekday",WEEKDAY([Date],2),
              "dayname",FORMAT([Date],"dddd"),
              "publikholiday",LOOKUPVALUE('Holiday Table'[Holiday Date],'Holiday Table'[holiday date],[Date]),
              "holidaycondition",
                  var a1 = IF(
                                not(WEEKDAY([Date],2)) in {6,7},
                                IF(
                                    LOOKUPVALUE('Holiday Table'[Holiday Date],'Holiday Table'[holiday date],[Date])<>BLANK(),
                                     0,
                                     1
                                ),
                                0
                            )
                  RETURN
                  a1
                )
var f = ADDCOLUMNS(c,"rank",RANKX(FILTER(c,[holidaycondition]<>0),[Date],,ASC))
var e= MINX(FILTER(f,[rank]=a),[Date])
return
e

 

Dangar332_6-1708610934958.png

 

Comments