New year, new challenge!
This week I was asked to adapt one of our internal Canvas Apps that was used for an exercise challenge in December to track miles, so that the leaderboard resets to ‘0 miles’ at the beginning of each month. Our team’s goal is to log the miles run or walked within the month, with the aim to contribute at least one mile per day of the month.
One of the features I delivered was a progress bar, but I wanted this progress bar to change based upon the duration of the month. Amongst other dynamic calculations, the width of the progress bar I want should be “total number of days in the month multiplied by 10”, and it looks something like this:
As we are all well aware, the length of months aren’t consistent, and in my app progress should be ‘higher’ in February if I have run 15 miles in 28 days, as opposed to running 15 miles in March which has 31days. In February the width should be 280px and in March it should be 310px.
To my surprise there wasn’t an existing Power Fx function that could achieve this but I was able to do this myself with the following solution. For someone who writes Power Fx regularly, I found this quite difficult to explain whilst writing the one statement, so hopefully the following explanation that breaks down the formula can help you too.
Constructing the Formula
I’m using the last day of the month in multiple places in my Canvas App, so I don’t quite want to create the final value (the multiplication by 10 for the width of the progress bar) just yet. For now, let’s start our formula by declaring a new variable called varDaysInThisMonth in the OnStart Property of the Canvas App.
//Create the variable varDaysInThisMonth with an empty string. Set(varDaysInThisMonth,"")
We then want to identify the last day of the month, but there’s also no direct formula for this either! We can use a little trick to achieve this by finding out the first day of next month, and then take away one day from the value.
Let’s do this by constructing the date for the first day of this month, and then add one month to the value. Please note that we need to make the Year and Month value dynamic here, otherwise we’ll end up with bad data in later months.
//Given that the current date is in January, construct the first day of the month using Date (01/01/2023) and return the value "01/01/2023" by adding one month. Set(varDaysInThisMonth, DateAdd(Date(Year(Today()),Month(Today()),1),1,Months))
We now know the first day of the next month, so now we just need to subtract one day from this value to find out the last day of this month by wrapping a new DateAdd formula around our existing DateAdd formula.
//Given that the output above is "01/01/2023", return the value "31/01/2023" by adding -1 days. Set(varDaysInThisMonth, DateAdd(DateAdd(Date(Year(Today()),Month(Today()),1),1,Months)), -1, Days)
In this situation the last day of the month is returned, which may be enough for some of you trying to achieve a similar calculation. In order to finally turn this in to the total number of days in this month, we just need to wrap our DateAdd calculation in a Day formula, which takes the “31” from “31/01/2023”.
//Given that the output above is "31/01/2023", return the total number of days this month, which equates to "31". Set(varDaysInThisMonth, Day(DateAdd(DateAdd(Date(Year(Today()),Month(Today()),1),1,Months),-1,Days)))
And there we have it! Personally, I found this more difficult than I expected to. I know other similar languages used in Excel and Power BI allow for simpler calculations than this, and I’d be interested in whether you’ve found a quicker way to achieve this!
The last step for me was to simply change the Width Property of the grey rectangle acting as the background of the progress bar alongside the formula for the with of the actual progress shown in the green rectangle by using this constructed variable.
Fact check: In this article Aaron implied that he has run 15 miles in January. This is completely false, Aaron would never run 15 miles within one month!
Leave a Reply