I am having one table in PowerBI which is having 3 columns: 1.EnrollId 2.Status 3.StatusChangeDate. One EnrollId is having 4 statuses and their particular statusChangeDates. I want to find no. of days between two dates with status condition.
EnrollId Status StatusChangeDate
101 AppStart 15/02/2019
101 Application 27/03/2019
101 Enrollment 03/04/2019
101 Complete 28/04/2019
I want to create formula in DAX like
[StatusChangeDate (where Status="Enrollment") - StatusChangeDate(where status="AppStart)]
or
[StatusChangeDate (where Status="Complete")- StatusChangeDate(where status="Enrollment)]
i.e. 03/04/2019 - 15/02/2019 = 44 Days
28/04/2019 - 03/04/2019 = 25 Days
My advice is go for a Calculated Column, you can try and adjust this to a measure but there is more factors to consider regarding the filter context.
For a calculated column:
DaysLastChange =
VAR _currentStatusChangeDate = [StatusChangeDate]
VAR _currentEnrollId = [EnrollId]
RETURN
DATEDIFF(
CALCULATE(MAX('Table1'[StatusChangeDate]);FILTER('Table1';_currentEnrollId = [EnrollId] && _currentStatusChangeDate > [StatusChangeDate] ));
_currentStatusChangeDate;
DAY
)
If you want measures, try something like this. For each period between two Statuses, you need to create another measure. When more than one [EnrollId] is selected, the measure returns a blank.
Days Enrollment - Complete =
VAR scDateEnrollment =
CALCULATE ( MAX ( 'Table'[StatusChangeDate] ), 'Table'[Status] = "Enrollment" )
VAR scDateComplete =
CALCULATE ( MAX ( 'Table'[StatusChangeDate] ), 'Table'[Status] = "Complete" )
RETURN
IF (
HASONEVALUE ( 'Table'[EnrollId] ),
DATEDIFF ( scDateEnrollment, scDateComplete, DAY )
)
Cardvisuals or a table-visual would look like this. As you can see the table-visual is not affected by the slicer.
EDIT
This is the table i used:
Related
I have WTDdata table that contains ThisYearRevenue and LastYearRevenue summarized by week:
I need to create 4 more columns LastYearOnlineRevenue, LastYearStoreRevenue, ThisYearOnlineRevenue, and ThisYearStoreRevenue from another table (RevenueByDate) that looks like this:
W column in this table means Fiscal Week.
I tried using this aproach:
LastYearOnlineRevenue =
SUMMARIZE(FILTER(ALL(FiscalCalendar),FiscalCalendar[FiscalWeek]),FiscalCalendar[FiscalWeek]),
"LastYearOnlineRevenue",CALCULATE(SUM(RevenueByDate[Revenue]),FiscalCalendar[FiscalYear] =
YEAR(TODAY())-1 && RevenueByDate[Channel] = "Online")
If you can help me with at least one column, I am assuming the logic will be the same for the other 3.
Thank you in advance.
Here is the location for sample data and .pbix file:
https://1drv.ms/u/s!AhhZq1add5YwjYIvuASi76lCL3R1eA?e=C7ObDZ
Try this:
Since there is no way of telling the current year from the WTDdata table, I have assumed that the current year is always 2021, you can also replace that with:
VALUE ( MAX ( RevenueByDate[FiscalYear] ) )
LastYearOnlineRevenue =
VAR CurrentFiscalWeek = WTDdata[FiscalWeek]
VAR CurrentYear = 2021
VAR ImmediatePreviousYear =
CALCULATE (
MAX ( FiscalCalendar[FiscalYear] ),
FiscalCalendar[FiscalYear] < CurrentYear,
REMOVEFILTERS ( WTDdata )
)
VAR Result =
CALCULATE (
SUM ( RevenueByDate[Revenue] ),
FiscalCalendar[FiscalWeek] = CurrentFiscalWeek,
FiscalCalendar[FiscalYear] = ImmediatePreviousYear,
RevenueByDate[Channel] = "Online",
REMOVEFILTERS ( WTDdata )
)
RETURN
Result
I have a case where I'm getting a circular dependency.
I'm trying to calculate what stock will arrive to our warehouse by a certain date, but the eta_date is a calculated date column.
The formula reporting the problem is this :
SIT Arriving Soon =
VAR PastDate = Today() - 40
VAR FutureDate = TODAY() + 14
return
CALCULATE(SUMX(OnOrder,OnOrder[Open ASN qty [units]]]), DATESBETWEEN(OnOrder[ETA Date],PastDate, FutureDate)
)
The issue is that the datesbetween function needs a column to refer to, and my column is the calculated column below, which only refers to other columns within the 'onorder' table:
to understand this formula, here is a small key:
InT is a true/false if a quantity is in transit
Open ASN qty = the qty that is in transit
I then look at different vendors and the shipping mode used to add the number of days transport time.
I then do a calculation to add to the transport time to the 'invoiced by supplier' date, and if the vendor is not one of the defined vendors, then we use the default calculated date "OnOrder[Target VSL3 Date]"
ETA Date =
Var InT = if ( OnOrder[Open ASN qty [units]]] <> 0, 1,0)
Var AAVend = if( OnOrder[Vendor] = "451633" ||
OnOrder[Vendor] = "97051583"||
OnOrder[Vendor] = "452825", "AA", "Non-AA")
Var AATransTime = if( AAVend = "AA", IF(OnOrder[Ship Mode] = "Blitz", 5, IF(OnOrder[Ship Mode] = "Air", 14, 42)), 500)
var TransTime = IF(AATransTime > 0, AATransTime, 99999)
RETURN
if ( InT = 1, DATEADD(OnOrder[Ship Date].[Date], TransTime,DAY), OnOrder[Target VSL3 Date]. [Date])
Can anyone help me to get this issue sorted, or advise a way on how I could calculate this?
Thanks very much!
Ditch the DATESBETWEEN and just filter on the date column:
SIT Arriving Soon =
VAR PastDate = Today() - 40
VAR FutureDate = TODAY() + 14
return
CALCULATE(SUM(OnOrder[Open ASN qty [units]]]), OnOrder[ETA Date] >= PastDate && OnOrder[ETA Date] <=FutureDate)
)
thanks for the reply. I tried the formula, and I still get the circular reference error. It talks about the field 'ADC invoice number'. Here is the code to that :
ADC Invoice No =
CALCULATE ( FIRSTNONBLANK ( 'ADC Movements'[ADC Invoice Number], 1 ), FILTER ( ALL ( 'ADC Movements' ), 'ADC Movements'[PoFull] = OnOrder[PoFull] ) )
I don't see how this conflicts at all.
I have a table visual with branch, client and revenue information. The revenue is coming from a measure which is affected by the week selector slicer.
I need to show Rank for selected week and rank increment/decrement from selected week's rank vs previous week from selected week. In snapshot, Rank # and Rank are the requirements.
I tried to create rank with AllSelected function but it is always affected by week slicer and I cannot get previous week rank to compare and put Rank increment/decrement.
DAX I tried for Rank
This Week GP =
var _Total =
CALCULATE(
SUM(V_TopClients[revenue]),
DATESBETWEEN('Date'[date],[current_week_start_date], [current_week_end_date])
)
return _Total
Previous Week GP =
var _Total =
CALCULATE(
SUM(V_TopClients[revenue]),
DATESBETWEEN('Date'[date],[previous_week_start_date], [previous_week_end_date])
)
return _Total
Rank This Week =
RANKX(
ALLSELECTED(V_TopClients),
CALCULATE(SUM(V_TopClients[Revenue])
)
)
--Update: added dax for measures
Here I am able to get the rank for this week i.e. the week selected on slicer.
But unable to get rank for previous week.
I have v_TopClients that has weekly revenue information linking to dimCalendar, Date tables.
Here is another and probably the best option for you-
Step-1:
Create a new custom table based on your table "TopClient". The code is as below-
group_by_result_new =
VAR group_wise_revenue =
GROUPBY (
TopClients,
TopClients[CalendarWeekKey],
TopClients[clientID],
"gp_this_week", SUMX(CURRENTGROUP(), TopClients[GrossProfit])
)
RETURN
SELECTCOLUMNS (
group_wise_revenue,
"CalendarWeekKey", TopClients[CalendarWeekKey],
"clientID", TopClients[clientID],
"gp_this_week", [gp_this_week]
)
Step-2:
Create relation between table "DimCalendar" and "group_by_result_new" using the column "CalendarWeekKey"
Step-3:
Create a new column (remember it a column) as below-
gp_prev_week =
VAR client_id = group_by_result_new[clientID]
VAR calendar_key_this_week = group_by_result_new[CalendarWeekKey]
VAR end_date_this_week =
LOOKUPVALUE(
DimCalendar[WeekEndingDate],
DimCalendar[CalendarWeekKey], CONVERT(calendar_key_this_week,INTEGER)
)
VAR end_date_prev_week = CONVERT(end_date_this_week,DATETIME) - 7
VAR calendar_key_prev_week =
LOOKUPVALUE(
DimCalendar[CalendarWeekKey],
DimCalendar[WeekEndingDate] , end_date_prev_week
)
VAR gp_prev_week =
LOOKUPVALUE(
group_by_result_new[gp_this_week],
group_by_result_new[CalendarWeekKey],calendar_key_prev_week,
group_by_result_new[clientID], CONVERT(client_id,INTEGER)
)
RETURN gp_prev_week
Step-4:
Create a new column (remember it a column) for RANK this week as below-
rank_this_week =
RANKX (
FILTER (
group_by_result_new,
group_by_result_new[CalendarWeekKey] = EARLIER (group_by_result_new[CalendarWeekKey])
),
group_by_result_new[gp_this_week],
,
DESC
// ,
// DENSE
)
Step-5:
Create a new column (remember it a column) for RANK prev week as below-
rank_prev_week =
RANKX (
FILTER (
group_by_result_new,
group_by_result_new[CalendarWeekKey] = EARLIER (group_by_result_new[CalendarWeekKey])
),
group_by_result_new[gp_prev_week],
,
DESC
// ,
// DENSE
)
And that's all! This should also work same as my previous solution.
Cheers!!
In DAX, there are builtin function PREVIOUSMONTH, PREVIOUSQUARTER and PREVIOUSYEAR available. But as you are searching for weekly data comparison, you required your own date periods to calculate. I just can give you some idea as below-
First, crate 4 measure based on your slicer week/date selection.
Example:
current_week_end_date = SELECTEDVALUE(Dates[Date])
current_week_start_date = SELECTEDVALUE(Dates[Date]) - 7
previous_week_end_date = SELECTEDVALUE(Dates[Date]) - 8
previous_week_start_date = SELECTEDVALUE(Dates[Date]) - 15
Now, you need 2 separate measure to calculate this week and previous week total revenue. Example Measures are given below-
1.
this_week_revenue =
CALCULATE(
SUM(table[revenue]),
DATESBETWEEN(
'Dates'[Date],
[current_week_start_date],
[current_week_end_date]
)
)
2.
previous_week_revenue =
CALCULATE(
SUM(table[revenue]),
DATESBETWEEN(
'Dates'[Date],
[previous_week_start_date],
[previous_week_end_date]
)
)
Now you have both weekly value in your hand and you can compare measure "this_week_revenue " with measure "previous_week_revenue" to generate the directions indicators.
Hope this will help!
Below image is just for reference:
I am trying to do the cumulative count for the users first time access the web page.
Table looks like,
UserID , Initial Access Date
100, 2019-05-10
200, 2019-05-20
100, 2019-05-21
100, 2019-05-25
200, 2019-05-30
300, 2019-06-01
Current Expression:
Cumulative Total =
CALCULATE (
DISTINCTCOUNT ( [USERID] ),
FILTER (
ALLSELECTED ( TABLE ),
[INITIAL ACCESS DATE] <= MAX ( [INITIAL ACCESS DATE] )
)
)
This only returns cumulative total count, How would I get the running total based on this count of Users.
Expected Results:
1 - Upload your Fact table in Power Bi
2 - Create a Date Table
Date = CALENDARAUTO()
Then
Year = Year('Date'[Date])
Month = MONTH('Date'[Date])
YEAR_MONTH = VALUE('Date'[Year])*100+VALUE('Date'[Month])
3 - Set relationships
4 - You can compute a set of two measures :
First
InitialAccess =
VAR InitialAccessInCurrentPeriod =
DISTINCTCOUNT(Fact_T[UserID ])
RETURN
InitialAccessInCurrentPeriod
Then :
InitialAccessCumulated =
VAR MaxDateInPeriod = MAX('Date'[Date]) // Retrieve the last date in current filter context
VAR StartingDate = MINX(ALLSELECTED('Date');[Year]) // Retrieve the lowest year selected on slicer
RETURN
CALCULATE(
[InitialAccess]; // Compute the number of initial access
FILTER( // In a nex filter context where all the dates
ALL('Date'); // Equal or superior to the lowest date selected
'Date'[Year]>=StartingDate
&&
'Date'[Date]<= MaxDateInPeriod // Until the last date visible in the current row context
)
)
You can see the final result here :
I have added to row to your fact table to have several years
Here is the Fact table used :
UserID Initial Access Date
50 12/12/2018
100 10/05/2019
200 20/05/2019
100 21/05/2019
100 25/05/2019
200 30/05/2019
300 01/06/2019
400 04/02/2020
Finally I got it working without creating extra columns or measures,
Cumulative Total =
CALCULATE (
SUMX (
Table,
IF ( DISTINCTCOUNT ( Table[UserID] ) > 0, 1, 0 )
),
FILTER (
ALLSELECTED ( Table ),
Table[InitialAccessDate]
<= MAX ( Table[InitialAccessDate] )
)
)
Cheers!!
I need to calculate the ongoing revenue for installation + maintenance for projects and calculate the monthly revenue for controlling purposes in DAX in Power BI.
The problem is the following.
The projects are stored in a table CONTRACTS like this:
And I have a separate date table INST_DATE_TABLE:
The tables are connected via the [INSTALLATION_DATE] field.
For every month the revenue is the total of the [INSTALLATION_REVENUE] if the installation was carried out that month plus from the first month on the monthly maintenance revenue which is given as the [MAINTENANCE_COST_PER_UNIT] * [MAINTENANCE_UNIT] / 12.
And the maintenance revenue should be only calculated if the current date is beyond the installation date!
Some contracts are not yet signed, so they dont't have an installation date set (NULL)
So the INSTALLATION REVENUE DAX is like this:
.INSTALLATION_REVENUE =
CALCULATE (
SUMX(CONTRACTS;
CONTRACTS[INSTALLATION_REVENUE]
);
CONTRACTS[INSTALLATION_DATE] > 0
)
And the MONTHLY REGULAR REVENUE is like this:
.REGULAR_REVENUE =
CALCULATE (
SUMX(CONTRACTS;
CONTRACTS[MAINTENANCE_COST_PER_UNIT]*CONTRACTS[MAINTENANCE_UNIT]
) / 12;
CONTRACTS[INSTALLATION_DATE] > 0
)
For all dates I can calculate the cash flow of the latter like this:
.REGULAR_REVENUE_ONGOING =
CALCULATE (
[.REGULAR_REVENUE];
ALL(INST_DATE_TABLE[INSTALLATION_DATE])
)
which gives me a nice series of monthly revenues for all periods. But I only would like to see this for the periods that are beyond the installation date!
So lets say filtered on contract 1 I have now the following cash flow:
But for periods before 2019.04.01 I would like to see zeros!
How can I do that?
I just can't filter on dates referring to the installation date of the project!
After I have the expected result for one contract it would be easy to sum it up for all contracts like this
.TOTAL_REVENUE =
[.INSTALLATION_REVENUE] + [.REGULAR_REVENUE_EXPECTED]
UPDATE:
I created a cumulative total to display the ongoing revenue as such:
.REGULAR_REVENUE_ONGOING =
CALCULATE (
[.REGULAR_REVENUE];
FILTER(
ALL(INST_DATE_TABLE[INSTALLATION_DATE]);
INST_DATE_TABLE[INSTALLATION_DATE
<=MAX(INST_DATE_TABLE[INSTALLATION_DATE])
)
)
this displays the correct series, but now I have another problem. When I try to cumulate this already cumulative data series it does not add up as a cumulative data series!
Any help would be appreciated
.REVENUE_TOTAL_CUMULATIVE =
CALCULATE(
[.REVENUE_TOTAL];
FILTER(
INST_DATE_TABLE;
INST_DATE_TABLE[INSTALLATION_DATE] <= MAX(INST_DATE_TABLE[INSTALLATION_DATE])
)
)
Assuming there are no end dates to your ongoing revenue, then try:
.REGULAR_REVENUE_ONGOING =
VAR DateMin =
CALCULATE(
MIN ( CONTRACTS[INSTALLATION_DATE] ),
ALL ( INST_DATE_TABLE )
)
VAR DateMax =
MAX ( INST_DATE_TABLE[INSTALLATION_DATE] )
RETURN
SUMX (
FILTER (
ALL ( INST_DATE_TABLE ),
INST_DATE_TABLE[INSTALLATION_DATE] >= DateMin && INST_DATE_TABLE[INSTALLATION_DATE] <= DateMax
),
[.REGULAR_REVENUE]
)
And for a cumulative total revenue:
.REVENUE_TOTAL_CUMULATIVE =
VAR DateCurrent = MAX ( INST_DATE_TABLE[INSTALLATION_DATE] )
VAR CumulativeInstallationRevenue =
CALCULATE (
[.INSTALLATION_REVENUE],
FILTER (
ALL ( INST_DATE_TABLE ),
INST_DATE_TABLE[INSTALLATION_DATE] <= DateCurrent
)
)
VAR CumulativeOngoingRevenue =
SUMX (
FILTER (
ALL ( INST_DATE_TABLE ),
INST_DATE_TABLE[INSTALLATION_DATE] <= DateCurrent
),
[.REGULAR_REVENUE_ONGOING]
)
RETURN
CumulativeInstallationRevenue + CumulativeOngoingRevenue
See https://pwrbi.com/so_55808659/ for worked example PBIX file