array formula: sum to date - excel

I have a number of invoices:
invoice #
start
end
paid on
amount
paid to date (hardcoded)
1
01/01/2020
30/01/2020
01/02/2020
£10.00
£10.10
2
01/02/2020
20/02/2020
01/03/2020
£7.50
£17.60
3
21/02/2020
30/02/2020
01/03/2020
£2.50
£20.10
4
01/01/2000
30/01/2000
01/03/2000
£0.10
£0.10
Where the invoices
are not necessarily sorted by start and end date
are not necessarily sorted by paid date.
might not have a paid-on value.
I want to add a field called paid to date that would show me the amount I have been paid so far where it would add the amount for:
the current invoice
the invoices that were paid prior to this invoice's paid-on date.
the invoices with the same paid-on date as this invoice but with a start date <= this invoice's start date.
Effectively mirroring the hard-coded column.
This is how I do it with a query (which might not be the simplest/most elegant way of doing it)
=Index(
query(
A1:E10,
"select SUM(E)
where D is not null
and (
D < date '"& TEXT( D2,"yyyy-mm-dd")&"'
OR (
D = date '"& TEXT( D2,"yyyy-mm-dd")&"'
and
B <= date '"& TEXT( B2,"yyyy-mm-dd")&"'
)
)"
),
2, 1
)
which is all well and good. but I want to be able to do it with array-formula, so I can have it auto-generated for me.
I tried using it inside array-formula but the value is only ever generated for the first row. I guess it's misinterpreting the range I am passing as the range of the query function, ie A1:E10. is there an easy way of fixing it?
Do I need to use VLookup?
Here is a sample spreadsheet.

try:
=INDEX(IFNA(VLOOKUP(A2:A, {INDEX(SORT({A2:B, D2:E}, 2, 1, 3, 1),,1),
MMULT(TRANSPOSE((ROW(E2:E)<=TRANSPOSE(ROW(E2:E)))*
INDEX(SORT({A2:B, D2:E}, 2, 1, 3, 1),,4)), SIGN(E2:E))}, 2, 0)))

If you have Excel 365, you can Filter directly.
Note that I am using a table with structured references. Then you don't need to adjust the range references as you add/remove rows from the table.
=SUM(FILTER([amount],([paid on]<[#[paid on]])+(([paid on]=[#[paid on]])*([start]<[#start])),0),[#amount])
This part does the filtering:
...([paid on]<[#[paid on]])+(([paid on]=[#[paid on]])*([start]<[#start]))...
Note: You can use the same algorithm in Sheets:
Note that I am using regular addressing, and also using a semicolon instead of a comma for the argument separators
=sum(iferror(FILTER($E$2:$E$5;($D$2:$D$5<$D2)+(($D$2:$D$5=$D2)*($B$2:$B$5<$B2)));0);E2)

Related

DAX - referencing row header in a formula

I need your help in creating a DAX measure that would help me resolving the following problem:
I have a table that shows case number, creation date and closure date:
case_number creation_date closure_date
CA001 4/15/2020 4/19/2020
CA002 4/17/2020 4/20/2020
CA003 4/19/2020 4/21/2020
CA004 4/19/2020 4/20/2020
I have a pivot with various measures where row headers are consecutive days from a related Calendar table. One of the columns I need is a number of active cases in given day (number of cases that were created before or the same day as the context date, AND closed after the context date). The expected outcome would be like this:
date open_cases
4/13/2020 0
4/14/2020 0
4/15/2020 1
4/16/2020 1
4/17/2020 2
4/18/2020 2
4/19/2020 3
4/20/2020 1
4/21/2020 0
in regular Excel, the formula that calculates the same would be =COUNTIFS(table_cases[creation_date],"<="&[#date],table_cases[closure_date],">"&[#date]), but in my case this will be a part of a bigger pivot table/dashboard and I need to write a measure in DAX that would calculate this.
I would appreciate your help in this matter.
Best regards,
Michal
There are a variety of ways to read the current context. You can use MAX or VALUES or SELECTEDVALUE (if available). These don't all behave exactly the same, so use whichever is appropriate for your situation.
open_cases =
VAR RowDate = MAX ( Calendar[date] )
RETURN
CALCULATE (
COUNT ( table_cases[case_number] ),
table_cases[creation_date] <= RowDate,
table_cases[closure_date] > RowDate
)
Here, MAX is evaluated within the filter context, so it should return the value in the current row (or the maximal date for subtotals and grand totals).

aggregating duplicates in excel

I have a excel file whose sample looks like the img attached. The highlighted numbers are the duplicate ids which I have. Now column E basically counts the number of days by (C-B) However, I want just one id per row. So for id 55555 the start date is 10/25/2017 and end date should be 1/14/2018 which will now make the number of days to be 61+19=80. However, I am unable to think of a formula which can do this. Any help on this will be greatly appreciated
#Karan Kashyap import & drag down the below formula on column E.
=SUMPRODUCT(--($A$2:$A$6=A2),$E$2:$E$6)
Output:
Dates are numbers, nothing more. They represent the number of days since 31-Dec-1899. All you need is MAXIFS minus MINIFS. If your version of Excel doesn't support MAXIFS or MINIFS then here are some pre-Excel 2016, Office 365 alternatives.
'Minimum start date if id = 55555
'option 1 for xl2010 and newer
=AGGREGATE(15, 7, B$2:B$6/(A$2:A$6=A2), 1)
'option 2 for pre-xl2010
=MIN(INDEX(B$2:B$6+(A$2:A$6<>A2)*1E+99, , ))
'Maximum end date if id = 55555
'option 1 for xl2010 and newer
=AGGREGATE(14, 7, C$2:C$6/(A$2:A$6=A2), 1)
'option 2 for pre-xl2010
=MAX(INDEX(C$2:C$6-(A$2:A$6<>A2)*1E+99, , ))
I've used 0 \d\a\y\s_) for a custom number format in column E.

Moving average excluding weekends and holidays

I have a table within PowerPivot currently that tracks a count of customers through our sales pipeline. From (by sales location) first interaction to charged sale. So far, I’ve creates a moving 5-day average that averages each task. Below is the DAX formula I’ve created thus far and an example table.
=
CALCULATE (
SUM ( [Daily Count] ),
DATESINPERIOD ( Table1[Date], LASTDATE ( Table1[Date] ), -7, DAY ),
ALLEXCEPT ( Table1, Table1[Sales Location], Table1[Group] )
)
/ 5
Where I’m struggling is being able to come up with a way to exclude weekends and company observed holidays. Additionally, if a holiday falls on a weekday I would like to remove that from the average and go back an additional day (to smooth the trend).
For example, on 11/26/18 (the Monday after Thanksgiving and Black Friday) I would like to average the five business days previous (11/26/18, 11/21-11/19, and 11/16). In the example above, the moving total and average for the previous 5 days should be Intake = 41 (total) 8.2 (average), Appointment = 30 (total) 6 (average), and Sale = 13 (total) and 2.6 (average).
Based on the formula currently, each of these numbers is inaccurate. Is there an easy way to exclude these days?
Side note: I’ve created an ancillary table with all holidays that is related to the sales data that I have.
Thank you for the help!
For this, I'd recommend using a calendar table related to Table1 on the Date column that also has a column IsWorkday with 1 if that day is a workday and 0 otherwise.
Once you have that set up, you can write a measure like this:
Moving Avg =
VAR Last5Workdays =
SELECTCOLUMNS (
TOPN (
5,
FILTER (
DateTable,
DateTable[Date] <= EARLIER ( Table1[Date] )
&& DateTable[IsWorkday] = 1
),
DateTable[Date], DESC
),
"Workday", DateTable[Date]
)
RETURN
CALCULATE (
SUM ( Table1[Daily Count] ),
Table1[Date] IN Last5Workdays
ALLEXCEPT ( Table1, Table1[Sales Location], Table1[Group] ),
)
/ 5
The TOPN function here returns the top 5 rows of the DateTable where each row must be a workday that is less than or equal to the date in your current Table1 row (the EARLIER function refers to the earlier row context that defines the current row).
I then use SELECTCOLUMNS to turn this table into a list by selecting a single column (which I've named Workday). From there, it's basically your measure with the date filter changed a bit.
#alexisolson Thank you for the response here. I was actually able to figure this out over the weekend but forgot to close out the thread (sorry about that! Appreciate your help either way). But I did something fairly similar to what you mentioned above.
I created a date table (CorpCalendar) that was only inclusive of working days. Then I created an index column within the CorpCalendar table to give each row a unique number in ascending order. From there, I linked the CorpCalendar table to my SalesData table by related dates and used the LOOKUPVALUE function to bring the index value over from the CorpCalendar table to the SalesData table. In a separate column I subtracted 4 from the date index value to get an index adjustment column (for a range of five days from the actual date index and the adjustment...if that makes sense). I then added an additional LOOKUPVALUE helper column to match the adjusted date index column to the appropriate working day.Lastly, I then used the following function to get the 5 day rolling average.
=CALCULATE(sum(Combined[Daily Count]),DATESBETWEEN(Combined[Date - Adjusted],Combined[Date - Adjusted (-5)],Combined[Date - Adjusted]),ALLEXCEPT(Combined,Combined[Group]))/5
This is probably more convoluted than necessary, however, it got me to the answer I was looking for. Let me know if this makes sense and if you have any suggestions for future scenarios like this.
Thanks again!

Get Value of first Pair

I have this file
Date | Time | Table | Checkin Time | Bill Number ..| .. |
7/1/2018 **18:03:48** **6** **18:03:48** **4332**
7/1/2018 18:11:23 **6** **18:03:48** **4332**
7/1/2018 18:23:10 **6** **18:03:48** **4332**
7/1/2018 19:24:11 8 19:24:11 4333
7/1/2018 19:56:17 8 19:24:11 4333
7/1/2018 20:31:11 *6 20:31:11 4332*
I need to calculate Checkin Time which is 1st time of table number and bill number.
For example See one customer checkin at 18:03:48 with table number 6
His Bill number is 4332 .
So for table number 6 and Bill number 4332 chekin time will be 1st time
which is 18:03:48.
So I applied the formula:
=IF(AND(E3=E2,C3=C2,A3=A2),D2,MIN(OFFSET(E3,0,-3,MATCH(0,(E3:E$35470=E3)*(C3:C$35470=C3)*(A3:A$35470=A3),0)-1,1)))
But the value changes at 6th row .
It's giving 20:31:11 as checkin time .
It should be 18:03:48 because the 6th row table number and bill number is same as 1st one.
So How do I make it possible, to calculate the checkin time as per 1st time who have same bill and table number , no matter which row .
Here is the excel file I have uploaded to Google drive.
Here is the screenshot.
Edit:- Formula by #jeeped work, But as the log is of 30 days
The data keeps repeating the other day too.
Can it be done by giving some unique date value ?
If you don't have the newer MINIFS and MAXIFS, use AGGREGATE to achieve the same result.
=AGGREGATE(15, 7, ((A$2:A$7)+(B$2:B$7))/((C$2:C$7=C2)*(E$2:E$7=E2)), 1)
Format the result any way you want; as date and time, time only, etc.
You can make use of an array formula combining INDEX+MATCH to return the earliest time value that matches your conditions first. In cell D2, enter the following:
=INDEX($B$2:$B$7,MATCH(1,($C$2:$C$7=C2)*($E$2:$E$7=E2),0))
When returning, be sure to press CONTROL+SHIFT+ENTER instead of just ENTER to make sure the formula calculates correctly.
#Jeeped's answer is spot on, here is an adjustment for the formula to work over multiple days that have the same table numbers and bill numbers:
=AGGREGATE(15, 7, ((A$2:A$13)+(B$2:B$13))/((C$2:C$13=C2)*(E$2:E$13=E2)*(A$2:A$13=A2)), 1)
All I did was add this extra conditional argument, that checks if the "Date" is the same:
*(A$2:A$13=A2)

Excel 2010 Dax Onhand Quantity Vs. Last Date Qty

Ive spent the last 2 days trying to get this, and I really just need a few pointers. Im using Excel 2010 w/ Power Pivot and calculating inventories. I am trying to get the amount sold between 2 dates. I recorded the quantity on hand if the item was in stock.
Item # Day Date Qty
Black Thursday 11/6/2014 2
Blue Thursday 11/6/2014 3
Green Thursday 11/6/2014 3
Black Friday 11/7/2014 2
Green Friday 11/7/2014 2
Black Monday 11/10/2014 3
Blue Monday 11/10/2014 4
Green Monday 11/10/2014 3
Is there a way to do this in dax? I may have to go back and calculate the differences for each record in excel, but Id like to avoid that if possible.
Somethings that have made this hard for me.
1) I only record the inventory Mon-Fri. I am not sure this will always be the case so i'd like to avoid a dependency on this being only weekdays.
2) When there is none in stock, I dont have a record for that day
Ive tried, CALCULATE with dateadd and it gave me results nearly right, but it ended up filtering out some of the results. Really was odd, but almost right.
Any Help is appreciated.
Bryan, this may not totally answer your question as there are a couple of things that aren't totally clear to me but it should give you a start and I'm happy to expand my answer if you provide further info.
One 'pattern' you can use involves the TOPN function which when used with the parameter n=1 can return the earliest or latest value from a table that it sorts by dates and can be filtered to be earlier/later than dates specified.
For this example I am using a 'disconnected' date table from which the user would select the two dates required in a slicer or report filter:
=
CALCULATE (
SUM ( inventory[Qty] ),
TOPN (
1,
FILTER ( inventory, inventory[Date] <= MAX ( dates[Date] ) ),
inventory[Date],
0
)
)
In this case the TOPN returns a single row table of the latest date earlier than or equal to the latest date provided. The 1st argument in the TOPN specifies the number of rows, the second the table to use, the 3rd the column to sort on and the 4th says to sort descending.
From here it is straightforward to adapt this for a second measure that finds the value for the latest date before or equal to the earliest date selected (i.e. swap MIN for MAX in MAX(dates[Date])).
Hope this helps.
Jacob
*prettified using daxformatter.com

Resources