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

Score big with last-minute savings on the final tickets to FabCon Vienna. Secure your discount

Reply
stribor45
Post Prodigy
Post Prodigy

Build Availability Table

Is it possible to build availability table of this data so you can see when there is a time in a week when there are no activities.

 

ParticipantTrainingTimeTimeDay 1Day 2
Participant 1Driving7:00:00 PM20:00:00MW
Participant 1Swimming8:00:00 AM9:00:00MW
Participant 2Basketball6:00:00 PM20:00:00TuTh
Participant 2Running11:00:00 AM13:00:00FF
Participant 3Basketball6:00:00 PM20:00:00TuTh
Participant 3Running11:00:00 AM13:00:00FF
Participant 4Basketball6:00:00 PM20:00:00TuTh
Participant 5Swimming8:00:00 AM9:00:00MW
Participant 5Walking12:00:00 PM14:00:00WF
Participant 6Driving7:00:00 PM20:00:00MW
Participant 6Basketball6:00:00 PM20:00:00TuTh
Participant 7Driving7:00:00 PM20:00:00MW
Participant 8Driving7:00:00 PM20:00:00MW
Participant 9Walking12:00:00 PM14:00:00WF
1 ACCEPTED SOLUTION

Hi @stribor45 ,

Certainly.  You can add a 30 minutes bucket field in the time table:

TimeTable = 
ADDCOLUMNS(
    GENERATESERIES(0, 1439, 1),
    "Time", TIME(INT([Value] / 60), MOD([Value], 60), 0),
    "Hour", INT([Value] / 60),
    "Minute", MOD([Value], 60),
    "Hour-Minute", FORMAT(TIME(INT([Value] / 60), MOD([Value], 60), 0), "hh:mm"),
    "30-Minute Bucket", 
        FORMAT(
            TIME(INT([Value] / 60), 
            IF(MOD([Value], 60) < 30, 0, 30), 0), 
            "hh:mm"
        )
)

Then write a measure like below:

Participants during Duration 30Min = 
VAR SelectedTime = MAX('TimeTable'[Time]) // Assume Time is in "HH:MM" format
VAR BucketStart = TIME(HOUR(SelectedTime), IF(MINUTE(SelectedTime) < 30, 0, 30), 0)
VAR BucketEnd = IF(MINUTE(SelectedTime) < 30, 
                   BucketStart + TIME(0, 30, 0), 
                   BucketStart + TIME(1, 0, 0))

// Concatenate participants within the time window
VAR ParticipantsList = 
    CONCATENATEX(
        FILTER(
            DISTINCT('Table'),
            'Table'[Start Time] <= BucketEnd &&
            'Table'[End Time] >= BucketStart
        ),
        RIGHT('Table'[Participant], 1),
        ", "
    )

// Return either the list of participants or '〇' if no participants
RETURN
    IF(
        ISBLANK(ParticipantsList),
        "-", // Display "-" when no participants
        ParticipantsList
    )

You can use the measure above alongside a color measure in conditional formatting to achieve a visualization shown at the bottom.

Color = 
IF ([Participants during Duration 30Min]="-","#90EE90","#FF0000")
//the color can be replaced with hexadecimal codes like #6B2328)))

 

DataNinja777_0-1730605220777.png

I have attached an example pbix file for your reference.

Best regards,

 

 

View solution in original post

20 REPLIES 20
shafiz_p
Super User
Super User

Hi @stribor45 As I can understand that you want to manage and visualize the availability of participants' activities throughout the week. You can create a availability table with time slots as rows and days of the week as columns.

 

The process involves creating a disconnected time table and a calendar table, then create measure to check if an activity is occurring at specific times and days.

To create a Calendar table, try this code:

CalendarTable = 
ADDCOLUMNS (
    CALENDAR ( DATE ( 2024, 1, 1 ), DATE ( 2024, 12, 31 ) ),
    "Weekday", WEEKDAY ( [Date], 2 ),
    "DayNameShort", SWITCH (
        WEEKDAY ( [Date], 2 ),
        1, "M",
        2, "Tu",
        3, "W",
        4, "Th",
        5, "F",
        6, "Sa",
        7, "Su"
    )
)

Table look like this:

shafiz_p_0-1730566646122.png

To create a time table, try this code:

TimeTable = 
ADDCOLUMNS (
    GENERATESERIES ( TIME ( 0, 0, 0 ), TIME ( 23, 30, 0 ), TIME ( 0, 60, 0 ) ),
    "TimeText", FORMAT ( [Value], "hh:mm AM/PM" )
)

Table look like this:

shafiz_p_1-1730566948716.png

Finaly the measure, evaluates available or not. Try below code:

IsActivity = 
VAR CurrentTime = SELECTEDVALUE ( TimeTable[Value] )
VAR CurrentDay = SELECTEDVALUE ( 'CalendarTable'[DayNameShort] )
RETURN
IF (
    COUNTROWS (
        FILTER (
            Activities,
            ( Activities[Day 1] = CurrentDay || Activities[Day 2] = CurrentDay ) &&
            CurrentTime >= Activities[Start Time] && CurrentTime <= Activities[End Time]
        )
    ) > 0,
    "Not Available",
    "Available"
)

Final output(s):
Output Version 1:

shafiz_p_2-1730567068464.png

Output Version 2:

shafiz_p_3-1730567157334.png

Output Version 3:

shafiz_p_4-1730567249585.png

 

All tables are disconnected. So, without place measure in value field it will show error. After place measure, it will work correctly.

shafiz_p_5-1730567380123.png

 



Hope this helps!!

If this solved your problem, please accept it as a solution and a kudos!!

 

Best Regards,
Shahariar Hafiz

@shafiz_p  can you share the file please if possible. what does the fact table look like. did you change anything?

Same as you provide data. Just changed First Time column to start time and second time column to End time. See fact table image:

shafiz_p_0-1730603202373.png

 

Hope this helps!!

DataNinja777
Super User
Super User

Hi @stribor45,

In order to solve your problem, I have created a data model like below:

 DataNinja777_0-1730553635840.png

 

Your fact able has a relationship with the weekday table.  On the other hand, the time table, generated from the following dax table function remains a disconnected table from your fact table.

 

TimeTable = 
ADDCOLUMNS(
    GENERATESERIES(0, 1439, 1),
    "Time", TIME(INT([Value] / 60), MOD([Value], 60), 0),
    "Hour", INT([Value] / 60),
    "Minute", MOD([Value], 60),
    "Hour-Minute", FORMAT(TIME(INT([Value] / 60), MOD([Value], 60), 0), "hh:mm")
)

As you mentioned that the two weekday columns represent separate dates rather than a duration, I have unpivoted them to create a single weekday column. This column is now connected to the weekday dimension table, as shown above.

 

The duration of participants' activity during the week can be visualized using the DAX measure below:

Activity Duration = 
VAR SelectedTime = MAX('TimeTable'[Time]) // Assume Time is in a format like "HH:MM"

RETURN
    SUMX(
        'Table',
        IF(
            'Table'[Start Time] <= SelectedTime
                &&  'Table'[End Time] >= SelectedTime,
            // Calculate the duration using max and min datetime in minutes
     1,blank()
        )
    )

 From the above, you can visualize the availability schedule, indicating time slots where everyone can attend—shown by the absence of any highlighting.

DataNinja777_1-1730554334485.png I have attached an example pbix file for your reference.

Best regards,

 

I will look at this as well and let you know. thank you

stribor45
Post Prodigy
Post Prodigy

Would it be easier to count how many participant are starting at same slots

 

On Mondays  8am 2 participants

On Mondays 7pm 4 participants

...

Say if i wanted to cancel a class and set that same class for some other time slots how many participants would be affected. 

danextian
Super User
Super User

Hi @stribor45 

 

Questions:

  • What output do you expect from this sample data?
  • What is the difference between the two time column other  than having different formats  (12 vs 24 hr format?)?
  • No activities for the whole table or by participant?




Dane Belarmino | Microsoft MVP | Proud to be a Super User!

Did I answer your question? Mark my post as a solution!


"Tell me and I’ll forget; show me and I may remember; involve me and I’ll understand."
Need Power BI consultation, get in touch with me on LinkedIn or hire me on UpWork.
Learn with me on YouTube @DAXJutsu or follow my page on Facebook @DAXJutsuPBI.

  1. Not sure at this point.  Maybe a table where row would be time slows and column with be weekdays. 

  2. Beside being misformatted nothing. 6:00:00 PM 20:00:00 should be 6pm to 8pm and so on
  3. For the whole table

How would you know which times are vacant if an activity does not indicate its duration?





Dane Belarmino | Microsoft MVP | Proud to be a Super User!

Did I answer your question? Mark my post as a solution!


"Tell me and I’ll forget; show me and I may remember; involve me and I’ll understand."
Need Power BI consultation, get in touch with me on LinkedIn or hire me on UpWork.
Learn with me on YouTube @DAXJutsu or follow my page on Facebook @DAXJutsuPBI.

I thought you could use second time column? This one would be 3 hours

7:00:00 PM20:00:00

I was under the impression that Time 1 was for Day1 and Time 2 was for Day 2. So the activities occur at the same time regardless fo the day?





Dane Belarmino | Microsoft MVP | Proud to be a Super User!

Did I answer your question? Mark my post as a solution!


"Tell me and I’ll forget; show me and I may remember; involve me and I’ll understand."
Need Power BI consultation, get in touch with me on LinkedIn or hire me on UpWork.
Learn with me on YouTube @DAXJutsu or follow my page on Facebook @DAXJutsuPBI.

Yes so basically this one  will be on mondays and wednesdays from 7-8pm

 

Participant 1 Driving 7:00:00 PM 20:00:00 M W

Can you check on this sample pbix.

So basically I created a table of Day and  Time (1 hr interval) and check whether the combination of Day and Start Time  or Day and End Time exists in the data table.  Anything that doesn't exist is available.





Dane Belarmino | Microsoft MVP | Proud to be a Super User!

Did I answer your question? Mark my post as a solution!


"Tell me and I’ll forget; show me and I may remember; involve me and I’ll understand."
Need Power BI consultation, get in touch with me on LinkedIn or hire me on UpWork.
Learn with me on YouTube @DAXJutsu or follow my page on Facebook @DAXJutsuPBI.

@DataNinja777  would this also work on half an hour starts as well. 

What is start and end times are 8:30 to 9:30 istead of 8:00 to 9:00?

Hi @stribor45 ,

Certainly.  You can add a 30 minutes bucket field in the time table:

TimeTable = 
ADDCOLUMNS(
    GENERATESERIES(0, 1439, 1),
    "Time", TIME(INT([Value] / 60), MOD([Value], 60), 0),
    "Hour", INT([Value] / 60),
    "Minute", MOD([Value], 60),
    "Hour-Minute", FORMAT(TIME(INT([Value] / 60), MOD([Value], 60), 0), "hh:mm"),
    "30-Minute Bucket", 
        FORMAT(
            TIME(INT([Value] / 60), 
            IF(MOD([Value], 60) < 30, 0, 30), 0), 
            "hh:mm"
        )
)

Then write a measure like below:

Participants during Duration 30Min = 
VAR SelectedTime = MAX('TimeTable'[Time]) // Assume Time is in "HH:MM" format
VAR BucketStart = TIME(HOUR(SelectedTime), IF(MINUTE(SelectedTime) < 30, 0, 30), 0)
VAR BucketEnd = IF(MINUTE(SelectedTime) < 30, 
                   BucketStart + TIME(0, 30, 0), 
                   BucketStart + TIME(1, 0, 0))

// Concatenate participants within the time window
VAR ParticipantsList = 
    CONCATENATEX(
        FILTER(
            DISTINCT('Table'),
            'Table'[Start Time] <= BucketEnd &&
            'Table'[End Time] >= BucketStart
        ),
        RIGHT('Table'[Participant], 1),
        ", "
    )

// Return either the list of participants or '〇' if no participants
RETURN
    IF(
        ISBLANK(ParticipantsList),
        "-", // Display "-" when no participants
        ParticipantsList
    )

You can use the measure above alongside a color measure in conditional formatting to achieve a visualization shown at the bottom.

Color = 
IF ([Participants during Duration 30Min]="-","#90EE90","#FF0000")
//the color can be replaced with hexadecimal codes like #6B2328)))

 

DataNinja777_0-1730605220777.png

I have attached an example pbix file for your reference.

Best regards,

 

 

@DataNinja777  would it be possible to adjust this based on additional activity that is attached to training columns? Say for example "driving" training also have "First Aid" activity that is attached to it and may be scheduled always on Wednesdays from 11-12 so every time you counting we leave everything as is only this time we add 1 to Wedesday under column 11

Hi @stribor45 ,

 

To integrate the "First Aid" schedule as part of the existing timetable, it’s best to handle this transformation in Power Query for consistency and efficiency.

  1. Duplicate the Fact Table Query: Start by duplicating the main fact table query.
  2. Filter for "Driving" Training: Apply a filter to include only rows where the training is "Driving."
  3. Rename Training Field: Rename the "Training" field to "Driving (First Aid)" to clearly indicate that these entries include the "First Aid" component.
  4. Adjust Start and End Times: Use the "Replace Values" feature in the Power Query ribbon to set the "Start Time" and "End Time" fields to reflect the "First Aid" schedule (e.g., Wednesdays from 11:00 to 12:00).

The final output will show "Driving (First Aid)" entries with the updated time slots, ensuring a seamless integration of both training and activity in your dataset.

DataNinja777_1-1731138022332.png

 

I have attached an example pbix file for your reference.

 

Best regards,

@DataNinja777   Thank you for sharing this. "driving" with its additional activity called "first aid" is an exampke  but other actiivties may or may not have additional activity scheduled at different day/time then the main activity.  Would this work as well on this solution?

I was trying to study the example you attached but i noticed that for participant #1 

#1 first aid on wednesday 11 to 12
driving on monday and ewednesday from 7-8 pm
swiming on monday and wednesday from 8:30 to 9:30 am

 

but the output starts half an hour earlier on  for first aid and driving

 

stribor45_0-1731202547940.png

 

Hi @stribor45 ,

 

Thank you for checking.  I tweaked the formula a little bit to fix the inaccuracy in output.  

Participants during Duration 30Min = 
VAR SelectedTime = MAX('TimeTable'[Time]) // Assume Time is in "HH:MM" format
VAR BucketStart = TIME(HOUR(SelectedTime), IF(MINUTE(SelectedTime) < 30, 0, 30), 0)
VAR BucketEnd = IF(MINUTE(SelectedTime) < 30, 
                   BucketStart + TIME(0, 30, 0), 
                   BucketStart + TIME(1, 0, 0))

// Concatenate participants within the time window
VAR ParticipantsList = 
    CONCATENATEX(
        FILTER(
            DISTINCT('Table'),
            'Table'[Start Time] <= BucketStart &&
            'Table'[End Time] > BucketStart
        ),
        RIGHT('Table'[Participant], 1),
        ", "
    )

// Return either the list of participants or '-' if no participants
RETURN
    IF(
        ISBLANK(ParticipantsList),
        "-", // Display "-" when no participants
        ParticipantsList
    )

 

Specifically changed part is as shown below where instead of BucketEnd, BucketStart variable was used.  

Using only BucketStart in the filter keeps the formula straightforward and avoids errors caused by unnecessary checks with BucketEnd. This approach reliably captures participants within each 30-minute interval as intended.

DataNinja777_0-1731216894467.png

The output is displayed below, and a sample check has confirmed that it now shows the correct results.

 

DataNinja777_1-1731217286970.png

 

I have attached the revised pbix file for your reference.

 

Best regards,

I will try this and let you know.

Helpful resources

Announcements
August Power BI Update Carousel

Power BI Monthly Update - August 2025

Check out the August 2025 Power BI update to learn about new features.

August 2025 community update carousel

Fabric Community Update - August 2025

Find out what's new and trending in the Fabric community.