Calculating growth rates—such as Year-over-Year (YoY), Month-over-Month (MoM), or Quarter-over-Quarter (QoQ)—is a fundamental requirement in business intelligence dashboards. In Power BI, this is achieved using Data Analysis Expressions (DAX).
This guide explains the mathematical logic behind growth calculations and provides the specific DAX patterns you need to implement them in your reports.
The Growth Rate Formula
Before writing code, it is essential to understand the math. The growth rate represents the percentage change between a current metric and a previous metric.
Finally, perform the division. It is best practice to use the DIVIDE function in DAX, as it automatically handles division by zero errors (returning BLANK instead of "Infinity").
Handling Edge Cases
Division by Zero: If your previous period value is 0, a standard math division throws an error. The DAX DIVIDE function prevents this.
Incomplete Periods: When comparing the current year (which might be incomplete) to a full previous year, the growth rate may look artificially negative. You may need to add logic to filter dates to "Today" or the max available data date.
Date Table: Time intelligence functions require a dedicated Date table marked as such in your Power BI model.
Alternative: Month-over-Month Growth
To calculate MoM instead of YoY, simply change the time intelligence function in the variable calculation:
PREVIOUSMONTH('Date'[Date]) or DATEADD('Date'[Date], -1, MONTH).
Use the calculator above to verify your manual calculations and generate the boilerplate DAX code for your specific measure names.
function calculateGrowth() {
// 1. Get input values
var currentValInput = document.getElementById("current_value").value;
var previousValInput = document.getElementById("previous_value").value;
var measureName = document.getElementById("measure_name").value;
var dateColumn = document.getElementById("date_column").value;
// 2. Validate inputs
if (currentValInput === "" || previousValInput === "") {
alert("Please enter both Current and Previous values.");
return;
}
var current = parseFloat(currentValInput);
var previous = parseFloat(previousValInput);
// 3. Mathematical Calculation
var diff = current – previous;
var growthRate = 0;
var growthString = "";
if (previous === 0) {
if (current > 0) {
growthString = "Infinity (New)";
} else if (current === 0) {
growthString = "0.00%";
} else {
growthString = "-Infinity";
}
} else {
growthRate = (diff / previous) * 100;
growthString = growthRate.toFixed(2) + "%";
}
// 4. Update Visual Results
var resultArea = document.getElementById("results_area");
var absDisplay = document.getElementById("abs_change_display");
var rateDisplay = document.getElementById("growth_rate_display");
var daxOutput = document.getElementById("dax_output");
resultArea.style.display = "block";
absDisplay.innerHTML = diff.toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2});
rateDisplay.innerHTML = growthString;
// Color coding the growth
if (growthRate > 0) {
rateDisplay.style.color = "#27ae60"; // Green
} else if (growthRate < 0) {
rateDisplay.style.color = "#c0392b"; // Red
} else {
rateDisplay.style.color = "#262626"; // Black
}
// 5. Generate DAX Code
// Sanitize inputs for display in code block
var cleanMeasure = measureName.trim();
var cleanDate = dateColumn.trim();
var daxCode =
"Growth Rate % = \n" +
"VAR CurrentValue = " + cleanMeasure + "\n" +
"VAR PreviousValue = CALCULATE(" + cleanMeasure + ", SAMEPERIODLASTYEAR(" + cleanDate + "))\n" +
"RETURN\n" +
" DIVIDE(\n" +
" CurrentValue – PreviousValue,\n" +
" PreviousValue,\n" +
" 0\n" +
" )";
daxOutput.innerText = daxCode;
}