Power BI calculate workdays in month - powerbi

I have a lot to learn of Power BI and I am currently stuck with a column I need to add in my Calendar table.
I have to calculate a workday column that should flag each day of the month with it's workday number (from 1 to the maximum number of working days for that month).
I was able to find a solution online with RANKX (I have a column, NonWorkday that flags with 1 for all days that are either weekends or holidays) but it's not complete:
Workday =
VAR CurrentMonth = Calendar[MonthYear]
VAR MonthTable = FILTER( ALL( Calendar ), Calendar[NonWorkDay] = 0 && Calendar[MonthYear] = CurrentMonth )
RETURN
IF( Calendar[NonWorkDay] = 1, BLANK(), RANKX(MonthTable, CALCULATE(AVERAGE(Calendar[DayofMonth])), ,ASC))
What I'm missing is that, for weekends and holidays I don't want blank, I want it to have the same workday number as the previous workday and if the month starts with a non-working day, that will be 0. An example image below:
It would be great if anyone can help me with a solution or point me in the right direction, either DAX or M query.
Thank you!
LE: Adding MVE code, as per #Marco_CH request:
let
Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("bdJBDoMwDATAv+RciXgTSPIW1P9/oxTbar34wGUQCWvveRbZZEMFyqvI9dTyfp0FGbYMe4b7D+v94otHRNw4IrYbZzxTcWUoNVWJp3ZVRN1VW9RDtUcdqnu8zfRIlZJN1Rl1qS6aly2hEuscQelEJwnamXPLmQKKTg68OR0daHeiswNlFB0eKKToREAbNG41Z05pA9zwbBYiwtqKZ7N6xG5txf8PdGtrgiN+vltb8SzQiji8rUg6IfGq6W3NtKVKsZa3FUmr5CAW7yuSVgmls57Iiv/h9ak589a6NxZZqyijM4X0snHK4Y2Nh0xvbMqc8prg+wM=", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [Date = _t, NonWorkDay = _t, WantedWorkday = _t]),
#"Changed Type" = Table.TransformColumnTypes(Source,{{"Date", type date}, {"NonWorkDay", Int64.Type}, {"WantedWorkday", Int64.Type}})
in
#"Changed Type"
LE2: My final calculation based on the answered provided by #msta42a:
WD =
var day ='Calendar'[Date]
VAR CurrentMonth = Calendar[MonthYear]
return
CALCULATE( COUNTROWS('Calendar'), FILTER('Calendar', Calendar[MonthYear] = CurrentMonth && 'Calendar'[Date] <= day && 'Calendar'[NonWorkDay] <> 1)) +0
Results:

You can calculate this like "running count/total" here my example (in your code you should add a clause for month/year)
Workday =
var day ='Calend'[Date]
return
CALCULATE( COUNTROWS('Calend'), FILTER('Calend', 'Calend'[Date] <= day && 'Calend'[Weekend]="wd" && Calend[Nonworking] <> 0)) +0

Related

How to calculate frequency received data from time column in Power BI?

I have a table with received time like the below:
As you see, the frequency of received data in some rows is different and they are 1000ms, 1001ms, 998ms.
How can I calculate the average frequency of received time in ms?
I suggest using Power Query to
add a column that is the original date_time column offset by 1
Then add another column showing the difference between current row and previous row
This method, at least in M Code, is faster than using an Index column to refer to previous row
Then you can do your mathematical analyses.
let
Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("dc27DcAgDAXAVRA1An9iO2EVxP5rgEQZXn3FjZGjsTUh4cRdqctTwy3P8heD4lv8KgHl3RJX+dCjBIXRo3JkLg==", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [date_time = _t]),
#"Changed Type" = Table.TransformColumnTypes(Source,{{"date_time", type datetime}}),
//add column containing previous rows data
//usually faster than using and INDEX column
prevList = {null} & List.RemoveLastN(#"Changed Type"[date_time]),
tbl1 = Table.FromColumns(
{#"Changed Type"[date_time],prevList},
{"date_time","Prev Row"}
),
#"Added Custom" = Table.AddColumn(tbl1, "Difference", each /*if [Prev Row] = null then 0
else*/ Duration.TotalSeconds([date_time] - [Prev Row])),
#"Changed Type1" = Table.TransformColumnTypes(#"Added Custom",{
{"date_time", type datetime}, {"Prev Row", type datetime}, {"Difference", type number}})
in
#"Changed Type1"
In PowerQuery add an Index column to your data so that you can address singe rows. Then with DAX add a calulated column to the table:
Milliseconds =
VAR NextIndex = 'Table'[Index] + 1
VAR MaxIndex = MAX(Table[Index])
VAR Difference =
IF(
'Table'[Index] = MaxIndex,
BLANK(),
'Table'[date_time] -
CALCULATE(
VALUES('Table'[date_time]),
Filter(
ALL('Table'),
'Table'[Index] = NextIndex
)
)
)
RETURN
CONVERT(ABS(Difference * 3600 * 24 * 1000), INTEGER)
Now you are looking for AVERAGE( Milliseconds ).
Note: Things would have been easier if you provided copyable data instead of a screenshot.

Calculated columns bases on the past 3 months in Power query

First time trying to use M in power query... what I have is this table
I need to create two columns that per each row (combination of CD_Loja x CD_Produto )returns me the sum of QT_VENDA for that combination divided by the # of days in the past 3 months. The other column is pretty much the same but with the sum of  VL_VENDA_LIQ  Instead.
I.e: For the first row I want to sum up all QT_VENDA that matches CD_PRODUTO =1001930 AND CD_LOJA = 151 in the past 3 months (the DATE column has daily data) and divide it by the number of days in those 3 months.
Is there a way to do so ? And how do I go about this ?
Thanks in advance.
In powerquery, M, something along these lines
let Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
#"Changed Type" = Table.Buffer(Table.TransformColumnTypes(Source,{{"DATA", type date}, {"CD_PRODUCTO", type text}, {"CD_LOIA", type text}, {"QT_VENDA", Int64.Type}, {"VL_VENDA_LIQ", Int64.Type}})),
#"Added Custom" = Table.AddColumn(#"Changed Type" ,"QT_VENDA_90",(i)=>List.Average(Table.SelectRows(#"Changed Type" , each [CD_PRODUCTO]=i[CD_PRODUCTO] and [CD_LOIA]=i[CD_LOIA] and [DATA] <= i[DATA] and [DATA] >= Date.AddDays(i[DATA] ,-90)) [QT_VENDA]), type number),
#"Added Custom2" = Table.AddColumn(#"Added Custom" ,"VL_VENDA_LIQ_90",(i)=>List.Average(Table.SelectRows(#"Changed Type" , each [CD_PRODUCTO]=i[CD_PRODUCTO] and [CD_LOIA]=i[CD_LOIA] and [DATA] <= i[DATA] and [DATA] >= Date.AddDays(i[DATA] ,-90)) [VL_VENDA_LIQ]), type number)
in #"Added Custom2"
You can try a Measure like below-
your_expected_value =
var current_row_data = MIN(your_table_name[DATA])
--I Guess the column name should be Date instead
var current_row_data_minus_90_day = MIN(your_table_name[DATA]) - 90
var current_row_cd_produto = MIN(your_table_name[CD_PRODUTO])
var current_row_cd_loja = MIN(your_table_name[CD_LOJA])
RETURN
CALCULATE(
SUM(your_table_name[QT_VENDA]),
FILTER(
ALL(your_table_name),
your_table_name[DATA] >= current_row_data_minus_90_day
&& your_table_name[DATA] <= current_row_data
&& your_table_name[CD_PRODUTO] = current_row_cd_produto
&& your_table_name[CD_LOJA] = current_row_cd_loja
)
)/90
--Here 90 used for static 3 month consideration

Table with all dates between last sales day and defined N periods

How to get Dates for N last full months. I want the last month to be determined by Sales amount.
This is the whole table for the example.
The expected result is a calculated table of Date column from 2020-05-01 to 2020-07-31. Looks like this:
Date
2020-05-01
2020-05-02
2020-05-03
…
2020-07-29
2020-07-30
2020-07-31
What have I tried? First, a measure to get the last date with sales:
MaxDate =
CALCULATE(
EOMONTH( MAX( T[Date] ), 0),
ALL( T ),
T[Amount] > 0
)
And the calculated table:
T_Range =
var a = [MaxDate]
var b = DATESINPERIOD( T[Date] , a, -3, MONTH )
return
b
But it returns only 3 days, not the whole range from 2020-05-01 to 2020-07-31.
The table to reproduce the problem:
let
Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("ZcrLCQAgDATRXnJWSNZ/LWL/bShIQFyY02PmFCg0qp0kiMkKTmBKTJmpROCjyldj6pceGb+YkhgJXNYG", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type text) meta [Serialized.Text = true]) in type table [Date = _t, Amount = _t]),
#"Changed Type" = Table.TransformColumnTypes(Source,{{"Date", type date}, {"Amount", Int64.Type}})
in
#"Changed Type"
Please check if this helps -
Created a new column with 'Max date' measure you provided.
Then crated min date column with below DAX.
Min Date = EDATE([MaxDate],-3)+1
Created new table using below.
T_Range = CALENDAR(MAX(T[Min Date]),MAX(T[Max Date]))

Power Bi DAX: Show data from 6 months past start date

i have been having trouble trying to figure out how to show my data past a date that is 6 months past the start date.
I need to show the values that are after the 6 months past the start date.
Each date is different for each person
i have the formula as a calculated column for the 6 months:
+6m = DATEADD('Employee List'[Emp. Dates].[Date], +6, MONTH)
A measure will not work because i cannot apply it to my table as it comes up with an error.
How do i get it to work?
Should i scrap the +6m column for a new formula?
Basic measure:
Total Sales = SUM(Sales[Total Sales])
As long as you do not provide sample data, it is just guessing what you want. It might be it:
YourMeasure =
CALCULATE (
[Total Sales],
DATEADD (
'Employee List'[Emp. Dates].[Date] -- it is better to use here 'Calendar'[Date]
-6,
MONTH
)
)
update
This will give you a good start.
Sample data:
let
Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WMjIwMtA1MAQiJR0lQ6VYHZiQEaaQMaaQCaaQKaaQGaaQOaaQBaaQJYaQoQGmEKbrDdFdb4jpR0NkP8YCAA==", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type text) meta [Serialized.Text = true]) in type table [Date = _t, Amount = _t]),
#"Changed Type" = Table.TransformColumnTypes(Source,{{"Date", type date}, {"Amount", Int64.Type}})
in
#"Changed Type"
Measure =
var MinDate = CALCULATE( MIN(T[Date]), REMOVEFILTERS(T[Date]) )
var SixMonthAfter = CALCULATE( DATEADD( T[Date], 6 , MONTH ), T[Date] = MinDate )
return
CALCULATE( SUM( T[Amount] ), FILTER( T, T[Date] > SixMonthAfter ) )

PowerBi timeseries duration

In PowerBI, I have a simple table with 3 columns:
let
Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("TYzBCcAwDAN38dugyk5bdxaT/deICzXN77hDyhSKCkHYwafwbJyaYiUc9I4XaH/1MgHeXQO+bcf7ux0XW3x5Lg==", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type text) meta [Serialized.Text = true]) in type table [id = _t, start = _t, end = _t]),
#"Changed Type" = Table.TransformColumnTypes(Source,{{"id", Int64.Type}, {"start", type date}, {"end", type date}})
in
#"Changed Type"
From which I can create the following visual
My challenge is to calculate the total duration in days of the times series based on filter selected above. Any help would be appreciated.
I have tried the following DAX formula but it gives me crazy results as shown above.
YTDDuration =
var start_Date=FIRSTDATE(ALLSELECTED('CALENDAR'[Date]))
var end_Date=LASTDATE(ALLSELECTED('CALENDAR'[Date]))
var current_Start=MAX(Table2[start])
var current_end=MAX(Table2[end])
var bigif=IF(current_end>start_Date&&current_Start<end_Date,DATEDIFF(MAX(start_Date,current_Start),MIN(end_Date,current_end),DAY),0)
RETURN
CALCULATE(SUMX(Table2, bigif),FILTER(ALL(Table2), Table2[start] <= max(Table2[end])))
Expected output would be:
The key here is to account for gaps in dates and consolidate overlapping dates.
You can iterate through your calendar table and count the number of days where that day falls into one of the id time periods.
YTDDuration =
var current_Start = CALCULATE(MIN(Table2[start]), ALL(Table2))
var current_end = MAX(Table2[end])
RETURN
SUMX(
FILTER('CALENDAR', 'CALENDAR'[Date] <= current_end),
MAXX(ALL(Table2), IF([Date] > [start] && [Date] <= [end], 1, 0))
)
This starts at the minimal start date and adds 1 for each day where that Date is between start and end for some row in Table2. If none of the rows contains that Date, the max is over just zeros and returns zero. If one or more matches, you get a max of one and we count that day.
YTD Duration by end: