Create a Rolling Calendar Year in Canvas Apps

Earlier this week I had a requirement to create a screen that would help others forecast an activity for the next 12 months. Whilst I was happy working with the data model, ensuring that the year was based on this month and the next eleven was more difficult than I anticipated. I suspect that this is because of my previous work with Dynamics 365 Customer Engagement & model-driven apps, where ‘Next X Months’ is a common and native reporting query, so I haven’t really had to think about it too much.

Here is a step-by-step guide on how you can create your own, and feel free to adapt this to use days or years instead!

Add a Gallery Control to your Screen

As calendars are visual, let’s add a Gallery control to the screen as this will enable us to create user interface effects that you’d typically see within a calendar-style control. At this moment in time, we won’t add a data source.

A screenshot of a Canvas App with a Horizontal Gallery control using the CustomGallerySample list of Items

I would recommend a Horizontal Gallery control for this example so that we can see the next 12 months across the screen with no scrolling necessary.

Create a Collection to Store Months

Now this is where the real work starts! We’re going to need to create a Collection which recognises today’s date and then shows the proceeding 11 months. This may initially look complicated, but it’s just two distinct lines of code and then a copy of the second line with very small amendments for each month.

ClearCollect(MonthsList, {Name: Text(Today(),"mmmm"), Month: Month(Today()), Year: Year(Today())}, 
{Name: Text(DateAdd(Today(),1,Months),"mmmm"), Month: Month(DateAdd(Today(),1, Months)), Year: Year(DateAdd(Today(),1, Months))},

As you can see from the above partial Power Fx code, we need to:

  • Collect a list of months called MonthList.
  • Store the name of the month by converting the month’s value to text using the Text format “mmmm”.
  • Store the date’s month’s value (January = 1, February = 2, etc.) using Month.
  • Store the date’s year value using Year.
  • Create the next item in the Collection by wrapping the code above in the DateAdd Power Fx code, incrementing by one each time.

đź’ˇWhilst it may not seem purposeful at the moment, storing the month’s value will help us if we need to query data when selecting one of the gallery items and mitigate the risk of delegation!

A screenshot of a Canvas App with a new collection called MonthList which collects values for this month and the proceeding 11 months.

Here’s the full code snippet:

ClearCollect(MonthsList, {Name: Text(Today(),"mmmm"), Month: Month(Today()), Year: Year(Today())}, 
{Name: Text(DateAdd(Today(),1,Months),"mmmm"), Month: Month(DateAdd(Today(),1, Months)), Year: Year(DateAdd(Today(),1, Months))},
{Name: Text(DateAdd(Today(),2,Months),"mmmm"), Month: Month(DateAdd(Today(),2, Months)), Year: Year(DateAdd(Today(),2, Months))},
{Name: Text(DateAdd(Today(),3,Months),"mmmm"), Month: Month(DateAdd(Today(),3, Months)), Year: Year(DateAdd(Today(),3, Months))},
{Name: Text(DateAdd(Today(),4,Months),"mmmm"), Month: Month(DateAdd(Today(),4, Months)), Year: Year(DateAdd(Today(),4, Months))},
{Name: Text(DateAdd(Today(),5,Months),"mmmm"), Month: Month(DateAdd(Today(),5, Months)), Year: Year(DateAdd(Today(),5, Months))},
{Name: Text(DateAdd(Today(),6,Months),"mmmm"), Month: Month(DateAdd(Today(),6, Months)), Year: Year(DateAdd(Today(),6, Months))},
{Name: Text(DateAdd(Today(),7,Months),"mmmm"), Month: Month(DateAdd(Today(),7, Months)), Year: Year(DateAdd(Today(),7, Months))},
{Name: Text(DateAdd(Today(),8,Months),"mmmm"), Month: Month(DateAdd(Today(),8, Months)), Year: Year(DateAdd(Today(),8, Months))},
{Name: Text(DateAdd(Today(),9,Months),"mmmm"), Month: Month(DateAdd(Today(),9, Months)), Year: Year(DateAdd(Today(),9, Months))},
{Name: Text(DateAdd(Today(),10,Months),"mmmm"), Month: Month(DateAdd(Today(),10, Months)), Year: Year(DateAdd(Today(),10, Months))},
{Name: Text(DateAdd(Today(),11,Months),"mmmm"), Month: Month(DateAdd(Today(),11, Months)), Year: Year(DateAdd(Today(),11, Months))}
);

Technically speaking, we’re not actually working with Months and Years directly here, we’re adding one month to the current date for every item. Whilst we don’t see it on the screen, if today’s date is the 13th November 2022, then the calculation for the second item in the Collection is actually splitting values from the 13th December 2022, and so on. This doesn’t matter though, as we aren’t manipulating or using Day values anywhere in this example.

Associate the Gallery and the Collection

This is relatively straight forward, the hard work is now done. Head over to your Gallery and replace the Items Property with MonthsList, and then run the OnStart Property from your App control in the Tree View.

A screenshot of the Canvas App showing the dynamic data associated with the controls provided by the Horizontal Gallery.

Depending on how you’ve adapted this example, you may see errors on the screen or your may see unnecessary controls. This is ok. This is the canvas trying to associate everything that you have with the controls provided for the custom data.

Get Styling!

  • Removed the Image control.
  • Replaced Subtitle2’s data with the date’s Year value.
  • Added a thin Rectangle control to separator data.
  • Added the month’s value underneath the separator just to show how you could display more data.
  • Added a ‘fill’ for the selected Gallery Item so that you can visually identify which month has been clicked by the user using the code below within the Fill property of a Rectangle:
If(ThisItem.IsSelected, RGBA(255, 191, 0, 1), RGBA(0,0,0,0))
A screenshot of the Canvas App with the finished rolling calendar view, showing all of the data that we collected earlier in a styled Horizontal Gallery control.

Final Thoughts

And there we have it, a fully dynamic month selector that will change based on the month we are currently in. There are several ways that you could possibly adapt this to either add more dynamic complexity, by creating a second gallery below that is controlled by the selector we’ve just produced – this is actually what I had to do for the client, but I can’t show you that as the data was far too specific!

I’ve also discussed the creation of this collection with a few colleagues this week and I couldn’t find anything more efficient to dynamically calculate the rolling months, so I would be really keen to hear your suggestions in the comments below if you have any.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s