I want to create a table about leave and need a cummulative total.
The Annual Leave Column2 DAX is
Annual Leave Column2 =
CALCULATE (
SUM (Sheet1[Debit/Credit]),
ALL ( Sheet1 ),
FILTER(Sheet1, SUM(Sheet1[Debit/Credit])>20), Sheet1[Date] <= EARLIER ( Sheet1[Date] )
)
and for the column 3 is
column 3 = IF( Sheet1[Annual Leave Column2]>20, 20, Sheet1[Annual Leave Column2] )
But the result when it already 20 and there is a -1 in next date it will still count 20 and stuck in 20.
And the result that I need is:
I just think, Can we stop the calculation if the value already 20? and continue the calculation if met -1. Or there is another way how to do it?
It's looks like if I using IF it's just make the visualization into 20 but not set the data into 20, that's why it's stuck in 20 because all the sum is more than 20.
Your best bet is for your source system to either not allow annual credits that exceed the annual cap, or to provide you with the capped annual leave amount directly (rather than trying to calculate it in Power BI).
Even if the source system doesn't store the capped annual leave amount, it may be easier to calculate it in a query using SQL than using Power BI. (I'd recommend a separate question for this.)
Why Do I Say This?
In Excel, a running (or cumulative) total is calculated row-by-row based on the value from the previous row. This makes it easy to "override" the running total and have that override apply to each subsequent row. E.g. you can cap the running total at 20, and the cell underneath acts as if the running total is 20. The cells underneath the cap have no idea that the running total is not really 20.
In DAX, the running total is calculated independently on each row (meaning each row looks at all the rows prior to the current rows date and calculates what the actual running total is). This makes it impossible to override the running total (e.g. by capping it at 20) and have that adjusted running total feed into the next row. The next row always knows what the real running total is.
There's no way to tell DAX to look at the previously calculated running total and add to it because a column cannot reference itself (as user5226582 mentioned, it's a circular dependency). DAX, unlike Excel, runs calculations column by column rather than cell by cell, so it can't use the output of a column as an input for the same column.
Dirty & Incomplete Workaround
A dirty workaround would depend on how many times Annual Credits can get disregarded. Each time all or part of an annual credit is disregarded, it adjusts the running total for all subsequent cells.
For example, on 1-May-17, the true running total is 20.5, but you throw away the 0.5. This means all future rows are based on a running total of 20 on 1-May-17, not 20.5.
You could certainly create a calculated column that identifies the first time the running total is capped (1-May-2017). You would then calculate an Adjusted Running Total that uses the previously calculated running total prior to 1-May-17, but after 1-May-17 ignores the prior running total and instead sums the [Debit/Credit] column from 1-May-17 only plus 20. (Adding 20 because we know the running total is at 20 on 1-May-17 and that won't be reflected in the sum of the [Debit/Credit] column.)
Running Total Is Capped = IF([Annual Leave Column2] > 20, 1, 0)
Running Count of Capped =
CALCULATE (
SUM ( Sheet1[Running Total Is Capped] ),
ALL ( Sheet1 ),
FILTER ( Sheet1, Sheet1[Date] <= EARLIER ( Sheet1[Date] ) )
)
Adjusted Running Total =
IF (
[Running Count of Capped] = 0,
[Annual Leave Column2],
20
+ CALCULATE (
SUM ( Sheet1[Debit/Credit] ),
ALL ( Sheet1 ),
FILTER (
Sheet1,
Sheet1[Date] <= EARLIER ( Sheet1[Date] )
&& Sheet1[Running Count of Capped] > 1
)
)
)
This solution doesn't hold up though because it only works for the first time the cap is hit. Each time you hit the cap, you'll need to adjust the running total in the same way, with a new set of calculated columns that adjusts the adjusted running total. If you can hit the cap 20 times, or 50 times, you'll need the above set of calculated columns repeated 20 or 50 times too.
You can't adjust for the cap across all rows simultaneously, because the first adjustment affects when the next adjustment happens. In your example data, the true running total on 5-Aug-17 is 21, meaning we'd want to reduce it to 20. However, because we've gone over the cap 3 times before, we've already shaved 3.5 days from the running total as a result, and so the adjusted running total is 17.5 and therefore doesn't need capping.
Apart from the sheer number of calculated columns you'd need, the model would also not hold up well to increased volume of data. The EARLIER function is iterative, meaning it runs its calculation once for every row. The more rows, the longer it takes. Using the EARLIER function over & over again as this quick & dirty workaround does would be a performance killer. I strongly recommend finding another solution, ideally before the data reaches Power BI.
Sidenote: If you're going to use the EARLIER function, I'd recommend indexing each row so they're guaranteed to have a unique number rather than relying on the date field as an index. Using the date field as an index could cause unexpected results if you have multiple credits/debits on the same date.
Related
I am trying to create a measure which will calculate the Total Project Revenue
while I have 2 different projects. For each project there is a different calculation:
for Hourly project the calculation should be: Income * BillHours
for Retainer project the calculation should be: Income*TotalWorkinghours
I wrote the below DAX:
enter code here : Total project revenue = IF(max(DimProjects[ProjectType])="Hours",
max(FactWorkingHours[Income])[BillHours],max(FactWorkingHours[Income])*
[Total Working Hours])
the rows are calculated correctly but the total in the table is wrong
what should I fix in DAX so the total of all raw will correct as well.
The total Revenue should be 126,403.33
Thank you in advance
you can find here the table with the results
It's hard to say exactly what your measure is doing because, as written here, that is not a valid measure. I pasted it into the DAX Formatter, which I would recommend for formatting and pasting here into code blocks, and the measure was invalid. It would also be helpful to post the other measures this measure references, eg. [Bill Hours] and [Income Hours].
That being said, I think I can kind of tell what's going on. Your total is probably wrong because the filter context at the total level is being based of the condition where:
MAX ( DimProjects[ProjectType] ) = "Retainer" (or some other value not in your shared snippet)
That is because when you consider the MAX of a string, the higher alphabetical order is considered. Therefore, "Retainer" > "Hours". So at the total level, your table is outputting—more than likely, I can't be certain without more information—the false condition of your measure:
MAX ( FactWorkingHours[Income] ) * [Total Working Hours])
There is a better way to handle your intended outcome. IF statements, in the way you are attempting to use it, are rarely used in a calculated measure. You may be better off trying a calculated column without using the MAX functions. Again, I can't give an exact code recommendation without more context. Hope that sends you in the right direction!
I have a database that has some values as "Date", "StopedTime", "PlannedProductionQtt" and "PlannedProductionTime". These values are sorted by equipment, as the little example below.
What I need to do is divide PlannedProductionQtt by PlannedProductionTime and then multiply by StoppedTime. After this, I want to make a graph that shows it day by day.
At first I thought it was easy, made a new measure PlannedProductionQtt/PlannedProductionTime = SUM(PlannedProductionQtt)/SUM(PlannedProductionTime) (assume it worked without the table name).
And then I did another measure Impact = SUM(StoppedTime)*PlannedProductionQtt/PlannedProductionTime.
When I plotted a clustered column chart with this measure in values and a the day for the axis, at first I thought I had nailed it, but no. The BI summed all of PlannedProductionQtt and divided by the sum of all PlannedProductionTime for the day, and multiplied by the sum of the StoppedTime of that day.
Unfortunately, this gives me wrong results. So, what I need is a measure (or some measures) that would make it equipment by equipment and the sum it by day.
I don't want to make new tables or columns for theses calculations because I actually have 32 items of equipment, 3+ years of data, more than 1 classification of StoppedTime and the databases for PlannedProduction use more than one line per day per equipment.
To make it clear I added one column as Impact to show the difference.
So, if I sum the column Impact per day, I would have for day 1,2 and 3 the results 110725, 61273 and 220833.
However, if I sum first all the PlannedProductionQtt for day 1, divide it by the sum of PlannedProductionTime of day 1 and multiply it by the sum of StoppedTime of day 1 (which is how PowerBi is calculating) I will have 146497.
I inserted the difference in the table below to make the differences clear:
As Jon suggested in a comment, here is what solved my needs:
measure_name = SUMX( source_table , DIVIDE ( source_table[PlannedProductionQtt] , source_table[PlannedProductionTime] , 0 ) ) * SUM( source_table[StoppedTime] )
You have two different types of data you want to divide there, time and int, so you would probably need to unify that. Easiest way to do it would be from the Transform data panel, selecting the column and changing its
format
The division is done fairly easily, can you try creating a new measure as follows
measure_name = CALCULATE(
DIVIDE(<source_table>[PlannedProductionQtt],
<source_table>[PlannedProductionTime],
0)
* <source_table>[StoppedTime]
)
Then it's only a matter of using it as values in a graph and the 'Date' column in x axis.
I am stuck trying to build a measure to determine the best or max 7 day average over a period longer than 7 days.
I have multiple values for each day, the measure needs to sum the values by day then calculate a rolling 7 day average then determine which of those results is the MAX value.
Could you help point me in the right direction please?
You need to use define a column in your measure and run an iterator (MAXX) over it in order to find the maximum value. Without additional details about fields and data model it is hard to be more specific.
However, see below an example:
VAR _tbl = CALCULATETABLE(ADDCOLUMNS(
SUMMARIZE('Fact', 'Dimension 1'[Attribute 1], 'Dimension 2'[Attribute2]),
"#average", AVERAGE('Fact'[Attribute 2])
), ALLSELECTED('Dimension 1'), ALLSELECTED('Dimension 2))
RETURN
MAXX(_tbl, [#rolling_average])
In practice, first we define a table with the measures pre-calculated,
then, we run an iterator on that table in order to retrieve the maximum value.
I'm fairly new to Power BI and struggling with an issue around totals in a table.
I am trying to calculate Mean Average Percentage Error (MAPE) using the following calculation:
[ABS(Actuals - Forecast)/Actuals]
Below is my dataset:
The total in the 'MAPEX' Column is actually the sum of the totals in 'AbsErr' / 'Actuals' columns: (1457.27 / 2786.27 = 0.52).
What I actually need to show is the sum of the values in 'MAPEX' which totals 5.88.
The 'MAPEX' column is a Measure with the following definition:
MAPEX = DIVIDE([AbsErr], sum(CUBE_PeriodicData[Actuals]),0)
I do not need to show the correct total in the 'Total' row in the table, it can be placed elsewhere in the report as a card, I would just like to know if there is a function in DAX that I am unaware of which will total the values in the column vertically?
Seymour's answer looks to be good, but I'm here to add a little that granularity matters in this scenario.
Assuming you have a star schema like this, it is pretty straightforward you can define measures Total Forecast, Total Actual, Absolute Error, and Absolute Percentage Error with below formulas.
Total Forecast = SUM ( Forecast[Forecast] )
Total Actual = SUM ( Actual[Actual] )
Absolute Error = ABS ( [Total Forecast] - [Total Actual] )
Absolute Percentage Error = DIVIDE ( [Absolute Error], [Total Actual] )
Here is what you will get so far.
Here, you are asking how to calculate the sum of Absolute Percentage Errors.
By definition, Absolute Percentage Error shows the value of Absolute Error divided by Total Actual regardless of the drill-down level. Therefore at the grand total, it shows 0.52 which is Absolute Error (1,457.27) divided by Total Actual (2,786.27). If you want it to calculate differently in the grand total level, you need to explicitly implement this logic.
Your requirement would be stated more explicitly like below:
Calculate the values of Absolute Percentage Error in the granularity of each ItemName, Year, and Month.
And add them up.
The function you will need to implement this logic is SUMX. Also, you may explicitly use SUMMARIZE to make sure you are calculating Absolute Percentage Error in the specific granularity.
MAPEX = SUMX (
SUMMARIZE (
Forecast,
'Product'[ItemName],
'Calendar'[Year],
'Calendar'[Month]
),
[Absolute Percentage Error]
)
I have been emphasizing about the granularity so far. This is because if you are not conscious of the granularity, the result may look strange in some cases.
In the above image, MAPEX looks to be the same as Absolute Percentage Error except for the grand total. However, if you drill-down by Quarter instead of Month, you will notice it is not the same at all.
Absolute Percentage Error is showing the quotient of Absolute Error and Total Actual at quarterly level, whereas MAPEX is still summing up monthly values of Absolute Percentage Error, even though Month is not being displayed in the table.
So, my final word is, whenever you invent a new measure like MAPEX, you always need to ask yourself if it makes sense or not for every possible granularities.
One way to solve this would be to use a custom column titled MAPEX instead of a measure that does your calculation. If there is a particular reason you need to use DAX please feel free to let me know and I may be able to figure something out.
Column = ABS(([Actuals]-[Forecast])/[Actuals])
EDIT: Just in case, the way you create a new column is with this button in the view tab.
Alternatively, you can create the custom column from within the query editor which appears to be working for me.
Go with this
VAR _mytable = SELECTCOLUMNS(FactTable, "MAPE", ABS(Actuals - Forecast)/Actuals))
Return
Sumx(_mytable, [MAPE])
I'm setting up a report in PowerBI that will give insight into the amount of work that is planned per department. I know the amount of products to be manufactured for specific projects and the time this takes per department in minutes. I've created a measure to calculate the total amount of time planned per department for a specific period, but it is giving an unexpected total that I don't understand.
The datamodel consists of four tables: a table that contains unique product ids,
a table that contains information on running projects (including the amount of products to be manufactured by a specific date), a table that contains the manufacturing routing which shows how much time is required to manufacture a specific product per department, a calendar table that contains all dates for the next 10 years
Relationships between the tables currently all have a cross filter in both directions. The image below contains the model and also the example data I've used:
Model
What we’re trying to do is create an overview of the amount of work planned per department in hours. So for this I’ve created a measure:
Total time in hours = (SUM(Projects[Amount]) * SUM(Routing[Time (in minutes)]) / 60
When I used this measure for a specific product, everything seems to be fine. However, when looking at the total time per departement I get a higher value. I'm not sure where this comes from. The table in the image shows the numbers I see in PowerBI. The total for Total time in hours (227) is much higher then the sum of the total time for the individual products:
Total time
Can anyone help me figure out how PowerBi calculates this total of 227?
There is no link between 'Projects' and 'Routing'[Department]. So at your grand total level, SUM ( 'Projects'[Amount] ) => (5 + 5 + 5 + 5 + 4 + 4) => 28 and SUM ( 'Routing'[Time (in minutes)] => (186 + 301) => 487. Thus, your total is (28 * 487) / 60 => 13,636 / 60 ~=> 227.
Ultimately, the behavior is "correct" in that the DAX you've written is evaluating conforming to spec, but you'll likely need to take a different approach to the calculation.
One possible approach is:
New Total time in hours =
SUMX ( // SUMX iterates a table, and performs a calculation per row, collecting these
// subtotals in a sum.
VALUES ( 'Products'[Product ID] ), // VALUES gives us a table made up of unique values
// in context from the named column (or table).
[Total time in hours] // your already existing measure
)