Extended Date Table - Add Agile Sprint schedule

@Melissa

I would like to see your latest Extended Dates Table M code extended to incorporate the Agile Sprint scheduling (I have added them as calculated columns but would like to see it embedded within M code to be cleaner):

Sprint Number
Sprint Start Date
Sprint End Date

Parameters to add when invoking include:

Sprint Duration (# of Days)
Sprint Start Day of Week
Sprint Number start (what sprint number do you wish to begin with?)

This will go a LONG way in supporting operational or transactional results/ROI observed as AGILE scrum teams release new or enhanced functionality for business organizations.

Thank you!

ClarkeM

Thanks @ClarkeM for creating the new thread.
I’ll get back to you.

Hi @ClarkeM,

I’ve got an idea but not 100% sure on the desired outcome. Could you share a mock up with your calculated columns or an image? I’m sure it will make perfect sense to me then.

Thanks again!

Hi @ClarkeM,

We noticed that you have not responded to our request last Feb. 17, 2023.

We are waiting for the masked demo pbix file, images of the entire scenario you are dealing with, screenshots of the data model, details of how you want to visualize a result, and any other supporting links and details.

If there won’t be any activity in the next few days, we’ll tag this post as Solved.

A post was split to a new topic: M Code I can add to my date table

Hi @ClarkeM,

I noticed you didn’t provide a PBIX file or mock-up with your calculated columns or an image, requested by Melissa in the post above. Providing one will help users and experts find a solution to your inquiry faster and better.

A perfect initial question includes all of the following:

  • A clear explanation of the problem you are experiencing
  • A mockup of the results you want to achieve
  • Your current work-in-progress PBIX file
  • Your underlying data file (to allow us to go into Power Query if necessary to transform your data and/or data model – often DAX questions really end up being data modeling solutions)

Check out this thread on Tools and Techniques for Providing PBIX Files with Your Forum Questions

I also suggest that you check the forum guideline How To Use The Enterprise DNA Support Forum. Not adhering to it may sometimes cause delay in getting an answer.

Not completing your data may sometimes cause delay in getting an answer.

If there won’t be any activity in the next few days, we’ll tag this post as Solved.

Thank you!

Hi @ClarkeM,

Give this a go. It’s a Custom Function that can be invoked on any Date table. As per your description this will add a Sprint Schedule for the entire table.

image

Parameters and how to use them:

  1. AddToTable, is the table these columns should be added to
  2. CalendarStartDate, is the first date from the calendar
  3. CalendarEndDate, is the last date from the calendar
  4. SprintDurationDays, for example, a duration of 2 weeks? enter 14
  5. SprintStartDayOfWeek, weekday a sprint cycle starts, enter 0 = Sun up to 6 = Sat
    This is optional, when omitted the SprintStartDayOfWeek is Monday
  6. SprintStartNumber, integer to be assigned to the first added sprint cycle
    This is optional when omitted the SprintStartNumber is 1

.
Here’s the function:

(AddToTable as table, CalendarStartDate as date, CalendarEndDate as date, SprintDurationDays as number, optional SprintStartDayOfWeek as number, optional SprintStartNumber as number ) as table =>
let
    // //variables
    // CalendarStartDate = #date( 2023, 1, 1),
    // CalendarEndDate = #date( 2023, 3, 31),
    // SprintDurationDays = 14,
    // SprintStartDayOfWeek = 2, //optional default Monday =1, choose from 0 = Sun to 6 = Sat
    // SprintStartNumber = 1, //optional default 1
    
    //setup
    SprintBaseLen = 7, //fixed to force weeks
    sLen = Number.RoundUp( SprintDurationDays / SprintBaseLen, 0 ) * SprintBaseLen,
    nSkip = List.PositionOf( List.Transform( List.Dates( CalendarStartDate, 7, Duration.From(1)), each Date.DayOfWeek( _, SprintStartDayOfWeek?? 1 ) +1 ), 1, 0 ),
    Reps = Number.RoundDown( (Number.From( CalendarEndDate - CalendarStartDate ) - nSkip) / sLen, 0 ),

    //logic
    Result = Table.TransformColumnTypes( Table.Combine(
        List.Generate(
            ()=> [
                r = 1,
                s = SprintStartNumber?? 1,
                t = Table.FromColumns(
                    { 
                        List.Repeat( {null}, nSkip ) & List.Repeat( {s}, SprintDurationDays ) & List.Repeat( {null}, sLen - SprintDurationDays ),
                        List.Repeat( {null}, nSkip ) & List.Repeat( {Date.AddDays( CalendarStartDate, nSkip)}, SprintDurationDays ) & List.Repeat( {null}, sLen - SprintDurationDays ),
                        List.Repeat( {null}, nSkip ) & List.Repeat( {Date.AddDays( CalendarStartDate, (nSkip + (SprintDurationDays * r)) -1)}, SprintDurationDays ) & List.Repeat( {null}, sLen - SprintDurationDays )
                    },  { "Sprint Number", "Sprint Start Date", "Sprint End Date"}
                )
            ],
            each [r] <= Reps,
            each [
                r = [r] + 1,
                s = [s] + 1,
                t = Table.FromColumns(
                    { 
                        List.Repeat( {s}, SprintDurationDays ) & List.Repeat( {null}, sLen - SprintDurationDays ),
                        List.Repeat( {Date.AddDays( CalendarStartDate, nSkip + (sLen * (r-1)))}, SprintDurationDays ) & List.Repeat( {null}, sLen - SprintDurationDays ),
                        List.Repeat( {Date.AddDays( CalendarStartDate, nSkip + (sLen * (r-1)) + SprintDurationDays -1 )}, SprintDurationDays ) & List.Repeat( {null}, sLen - SprintDurationDays )
                    },  { "Sprint Number", "Sprint Start Date", "Sprint End Date"}
                )
            ],
            each [t]
        )), {{"Sprint Number", Int64.Type}, {"Sprint Start Date", type date}, {"Sprint End Date", type date}}
    ),
    Final = Table.FromColumns(
        Table.ToColumns( AddToTable ) & Table.ToColumns( Result ),
        Table.ColumnNames( AddToTable ) & Table.ColumnNames( Result )
    )
in
    Final

.
With this result

Amend to your needs.
All the best.

3 Likes

Hi @Melissa ,

Thank you very much for the detailed answer. we appreciate the time you have spent on this.

Hello @ClarkeM

Did the response from Melissa help solve your query?

If not, can you let us know where you’re stuck and what additional assistance you need?

If it did, please mark the answer as the SOLUTION.

Thank you

1 Like

Hello @ClarkeM

Just following up if the response above help you solve your inquiry.
If it did, please mark his answer as the SOLUTION.

We’ve noticed that no response was received from you on the post above. In case there won’t be any activity on it in the next few days, we’ll be tagging this post as Solved.

Hi @ClarkeM

Due to inactivity, a response on this post has been tagged as “Solution”.

If you have a follow question or concern related to this topic, please remove the Solution tag first by clicking the three dots beside Reply and then untick the check box.

We request you to kindly take time to answer the Enterprise DNA Forum User Experience Survey,.

We hope you’ll give your insights on how we can further improve the Support forum. Thanks!

Hi @Melissa,

Sorry for the delay. Work has been quite busy.

Here are the calculated columns I have created to establish a sprint schedule in the dates table.

I used 1/23/2019 as the first sprint’s start date. 14 is the length of my company’s sprint cycle.

Sprint Number = FLOOR(DATEDIFF(DATE(2019,1,23),‘Dates’[Date],DAY)/14,1)+1

This just identifies the start date of each sprint for each day in my dates table.

Sprint Start Date = CALCULATE(MIN(‘Dates’[Date]),ALLEXCEPT(‘Dates’,‘Dates’[Sprint Number]))

This identifies the end date.

Sprint End Date = CALCULATE(MAX(‘Dates’[Date]),ALLEXCEPT(‘Dates’,‘Dates’[Sprint Number]))

This is what the data looks like in the dates table:

Thanks,

Clarke

Thanks for clearing that up @ClarkeM

Give this Custom Function a go, it can be invoked on any Date table. As per your description this will add a Sprint Schedule for the entire table beginning on the SprintStartDate.

image

Parameters and how to use them:

  1. CalendarTable, is the table these columns will be added to
  2. CalendarDateCol, is the column that contains the unique date values in the calendar
  3. SprintStartDate, is the first date from initial sprint cycle
  4. SprintDurationDays, requires a weekly pattern; 1 week = 7, 2 weeks =14 and so on
  5. SprintStartNumber, number to be assigned to the first added sprint cycle
    This is optional when omitted the SprintStartNumber is 1

.
Here’s the function.

( CalendarTable as table, CalendarDateCol as list, SprintStartDate as date, SprintDurationDays as number, optional SprintStartNumber as number ) as table =>
let
    // // //variables
    // CalendarTable = Dates,
    // CalendarDateCol = Dates[Date],
    // SprintStartDate = #date( 2023, 3, 1),
    // SprintDurationDays = 14,
    // SprintStartNumber = 108, //optional default 1
    
    //logic
    r = Table.FromRecords(
        List.TransformMany(
            CalendarDateCol,
            each [ 
                n = Number.RoundDown( Number.From( _ - SprintStartDate )/SprintDurationDays, 0 ),
                r = if n < 0 then {null} else {n}
            ][r],
            (x, y)=> [ 
                Sprint Number = y + SprintStartNumber ?? 0, 
                Sprint Start Date = try Date.AddDays( SprintStartDate, y*SprintDurationDays ) otherwise null, 
                Sprint End Date = try Date.AddDays( SprintStartDate, (y*SprintDurationDays) +SprintDurationDays -1 ) otherwise null 
            ]
        ), type table [ Sprint Number = nullable number, Sprint Start Date = nullable date, Sprint End Date = nullable date ]
    ),
    Final = Table.FromColumns(
        Table.ToColumns( CalendarTable ) & Table.ToColumns( r ),
        Table.ColumnNames( CalendarTable ) & Table.ColumnNames( r )
    )
in
    Final

.
With this result when invoked.

Amend to your needs.
All the best.