Excel formula to split an amount per year depending on expenditure days within a date range - excel

I am in the process of building a formula to split a total cost (in column J) based on start and end expenditure periods that can vary from 2021 to 2031. Based on the days between the expenditure period dates (column M), I managed to work out to split the cost using the formulas below up to 2023 but it is not consistent and at times incorrect.
In cell P5 I have the following formula. For year 2021, I seem to get the correct split result.
=IF($K5>AS5,0,$J5/$M5*(AS5-$K5))
In cell Q5, I have the following formula. For year 2022, I seem to get the correct spit as well
=MIN(IF(SUM($N5:P5)>=$J5,0,IF($L5>=AS5,$J5/$M5*(AS5-AR5),$J5/$M5*($L5-MAX(AR5,$K5)))),K5)
However, I don't get the right result in cell Q6 which has the same formula but different dates
=MIN(IF(SUM($N6:P6)>=$J6,0,IF($L6>=AS6,$J6/$M6*(AS6-AR6),$J6/$M6*($L6-MAX(AR6,$K6)))),K6)
Cell R6 shouldn't return any result because it is out of date range. This is where things get mixed up.
Note that from column AR to BC, it is all year end dates from 2020 to 2031 as shown below.
Is there a better way to tackle this sort of formula as I seem to get dragged into a long and unreliable way of doing this.

Here single function(♣) that will create a series of pro-rata multipliers (of appropriate length) for any given start/end date:
EDIT: see end of soln for extended version per OP comment to original soln...
SINGLE FUNCTION
=J11*(LET(dates,EDATE(DATE(YEAR($K11),1,1),12*(SEQUENCE(1,YEAR($L11)-YEAR($K11)+2,1))),IF(dates<K11,K11,IF(dates<L11,dates,L11)))-LET(dates,EDATE(DATE(YEAR($K11)-1,1,1),12*(SEQUENCE(1,YEAR($L11)-YEAR($K11)+2,1))),IF(dates<K11,K11,IF(dates<L11,dates,L11))))/(L11-K11)
It may appear somewhat unwieldy in length, but it is far more robust (and concise) compared to the combination of steps/series you have created. What's more, it returns the precise answer RE: pro-rata payments and is guarenteed to never over/under-run RE: total payment (by design).
BREAK-DOWN
Comprises 3 distinct parts (some of which are similar in pattern/formation):
1] First part - create a series (array) of years spanning start-end dates:
=LET(dates,EDATE(DATE(YEAR($K5)-1,1,1),12*(SEQUENCE(1,YEAR($L5)-YEAR($K5)+2,1))),IF(dates<K5,K5,IF(dates<L5,dates,L5)))
Thanks to the lovely Spill functionality the new Office 365 variant Excel boasts, you never have to worry about how many years are required -- so long as you have the space to the right of this workbook (would be unusual otherwise - assuming you start in column O and clear any content to the right of this, you'd need an end date beyond the year 2557 (26th century) to run out of columns! ☺
2] Second part is merely a replica of the firs series, albeit shifted to the right 'once' (so starts with the 2nd element in the 1st series):
=LET(dates,EDATE(DATE(YEAR($K5),1,1),12*(SEQUENCE(1,YEAR($L5)-YEAR($K5)+2,1))),IF(dates<K5,K5,IF(dates<L5,dates,L5)))
3] Third part - you have the basic ingredients from parts 1 and 2 to complete the required task easily: simply deduct series 2 from 1 (giving days between successive dates in series 1 - i.e. days for each year between start and end dates), divide by total days (to yield pro-rata multipliers), and then multiply these by the total £amount and voila - you have your series!
=J5*(O6#-O5#)/(M5)
♣ Caveat(s) - assuming you have Office 365 compatible version of Excel (which is quite common nowadays)
*EDIT - EXTENDED VERSION
Given above, the following extends this to align monetary results (1st table, o11:w21) within respective calendar period columns (spanning the entire period in question).
This soln:
Determines header row based upon the number of columns & corresponding calender periods (financial yrs commencing 1/1) as an array function (i.e. dynamic range)
Utilises a modified version of the eq. provided for dates arrage (refer: "First Part", original soln)
Comment - same caveats as before - i.e. Office 365 etc.
Screenshot(s)/here refers:
DATES (HEADER) - Y10 (array)
=LET(y_,MIN(K11:K21),x_,MAX(L11:L21),EDATE(DATE(YEAR(y_)-1,1,1),12*(SEQUENCE(1,YEAR(x_)-YEAR(y_)+2,1))))
Comment - enter once within single cell Y10 - i.e. as an array function with Spill to right
ALIGNED/SHIFTED FINANCIALS - Y11:Y21 (each cell in col is an array)
=IFERROR(IF(Y$10#<EDATE(K11,-12),"",IF(Y$10#>EDATE(L11,12),"",INDEX(O11#,1,MATCH(Y$10#,EDATE(DATE(YEAR($K11)-1,1,1),12*(SEQUENCE(1,YEAR($L11)-YEAR($K11)+2,1))),0)))),"")
Comment - enter this as an array fn. (#SPILL! to the right) in each cell within column Y (can drag this function down Y11:Y21 as required)

Related

In Excel: How to built a graph with time as X, names as Y with multiples series?

I am looking for a way to make a specific graph in Excel and I can't find a solution in Excel or on the web.
I have data about an online training with people completing parts of a course at a certain time:
FullName
Course
TIME
Name-A
Part 1
23/03/2022 10:38
Name-A
Part 2
23/03/2022 12:07
Name-A
Part 3
23/03/2022 16:55
Name-B
Part 1
11/03/2022 15:14
Name-B
Part 2
22/03/2022 12:08
Name-B
Part 3
28/03/2022 16:06
Name-B
Part 4
30/03/2022 14:55
Name-B
Part 5
18/04/2022 08:13
Name-C
Part 1
11/04/2022 15:25
Name-C
Part 2
20/04/2022 13:50
I would like to have a specific graph of this data:
On the vertical axis: one row for each user' name: Name-A, Name-B and Name-C.
On the horizontal axis: continuous time (say, in days) From the minimum time in the table (or less) to the maximum (or more)
Series of plots for the data: Each part of the course (from Part 1 to Part 5 here) would be a series of dots of a specific color, placed on the right row (for a learner's name) above the corresponding time on the horizontal axis.
Do you have any idea on how it could be achieved?
All the best, R.S.
Edit: The table does not appear as in the preview so i try to add a screenshot:
Screenshot of the table
So one way to visualise this as mentioned in the comments is to create a separate series for each person and show passing each part of the course as a vertical step:
It's based very loosely on this but I've set each day in the date range as the x-coordinates and used a lookup to transform the data in H2
=RIGHT(XLOOKUP($G2+TIME(23,59,59),FILTER($C$2:$C$11,$A$2:$A$11=H$1),FILTER($B$2:$B$11,$A$2:$A$11=H$1),0,-1))+(COLUMN()-COLUMN($G$1))*10
pulled down and across to give
Explanation
The data for the graph has dates spanning the times in the raw data for its x-coordinates (column G). I generated it manually but could have used Sequence in Excel 365.
There are three columns of y-values, H to J, generating a separate series for each person. The three lines are initially spaced out by 10 units based on the column number. In the formula above, the raw data is filtered by the person's name so the headers in columns H, I or J match the names in column A in the raw data. Xlookup is used with 'next smallest' match so where the date in column G is greater or equal to the date/time in column C it will return the corresponding course from column B. Because column C actually contains date/times, I have added almost 24 hours when matching the date in column G to make sure that a match is found if the day is the same, regardless of time. In a case like Name-A, where three courses are completed in the same day, this will automatically select the last one (Part 3). Then I take the right-hand character of the course name (which is a digit in the sample data) and add it to the relative column number multiplied by 10. If there is no match, Xlookup returns zero so you just get the initial value for each series (10, 20 or 30), otherwise the result will be an increase by one unit each time a course is passed. If you couldn't assume the last character of the course name was a digit, you would need a lookup to assign a number to each course name.
The data is then plotted on a scatter graph with points joined by straight lines. I had to adjust the x-axis manually to make the range correct and the labelling clearer.
This could be done without Excel 365, probably using Aggregate to get the highest row number with a condition on the name and date.
EDIT
I could have achieved the same result much more easily using Countifs to find how many courses had been passed by a certain person by a certain date:
=COUNTIFS($A$2:$A$11,H$1,$C$2:$C$11,"<="&$G2+TIME(23,59,59))+(COLUMN()-COLUMN($G$1))*10
This wouldn't have needed Excel 365. If you needed to give different courses different weightings, you could do this with a sumproduct and a lookup, also fairly straightforward.

Get sum of cells containing "Vacation" except when related date matches certain day & month

oversimplified i have two columns: Date and Text; I want to check my current amount of vacation days based on the first date in row 2, so i came up with the following formula:
="Available vacation days: "&YEARFRAC(A2;TODAY())*12*(25/12)
I calculate the fraction of the year based on the first date and todays date, multiply it by 12 to get months and multiply it again by the total amount of vacation days in my contract per month. Now i got another formula to collect me all cells in column B containing "Vacation", pretty straight forward:
=COUNTIF(B:B;"Vacation")
Now the interesting part - i got the formula who gives me a boolean if a datetime matches the 24th or 31st of december:
=AND(OR(DAY(A53)=24;DAY(A53)=31);MONTH(A53)=12)
I want to count vacation days happening on a 24th or 31st of december as a half-vacation day (0.5), and otherwise fully (as a 1). Then i want to combine my first statement with this result and subtract the used vacation days. I read about VLOOKUP and XLOOKUP but am unsure if this fits this purpose. I want to avoid having an extra column with my boolean returns and rather have this one cell giving me all the information combined.
Without introducing another column, and using DAY and MONTH
It's nearly impossible, and just unnecessarily so...
Please reconsider this, what will happen if you want to add 4th of July as a holiday?
Your formula =AND(OR(DAY(A53)=24;DAY(A53)=31);MONTH(A53)=12) only works for 1 row at a time. So, we can't ever use it with a list, because you will get the whole list as a result every single time. You can't divide them into smaller lists and join them together, there is no such functionality without VBA.
In the future, do not set arbitrary constraints like "no additional columns", you can hide them if you don't like them. And if you don't need them, remove unnecessary rows like non-vacation rows. They are irrelevant, so why not separate the two.
Just to prove my point, here's the solution you wanted:
Solution
=COUNTIFS(B2:B9;"Vacation") - (COUNT(IFERROR(FILTER(FILTER(FILTER(A2:A9;B2:B9="Vacation");MONTH(FILTER(A2:A9;B2:B9="Vacation"))=12);DAY(FILTER(FILTER(A2:A9;B2:B9="Vacation");MONTH(FILTER(A2:A9;B2:B9="Vacation"))=12))=31);0))+(COUNT(IFERROR(FILTER(FILTER(FILTER(A2:A9;B2:B9="Vacation");MONTH(FILTER(A2:A9;B2:B9="Vacation"))=12);DAY(FILTER(FILTER(A2:A9;B2:B9="Vacation");MONTH(FILTER(A2:A9;B2:B9="Vacation"))=12))=24);0))))*0,5
It works, but it's a pain to read, use and maintain.
A2:A9 refers to the dates column
B2:B9 refers to the text column
So in the future, the last thing you want to do is set arbitrary constraints. Furthermore, why use functions like MONTH and DAY when we can just read the text? That way you could even create a table of holidays to search for instead. That will be no fun task with this setup. (Oh, and if it's because of the year, just strip it away from the text when you want to know only the month and day.
Best of luck!

Excel: Nesting two Nested IF statements inside one IF statement depending on Dropdown Box

I have 2 Nested IF Statements..
=IF($B3=$K$3,DATE(YEAR(D3)+$L$3,MONTH(D3)+$M$3,DAY(D3)),IF($B3=$K$4,DATE(YEAR(D3)+$L$4,MONTH(D3)+$M$4,DAY(D3)),IF($B3=$K$5,DATE(YEAR(D3)+$L$5,MONTH(D3)+$M$5,DAY(D3)),IF($B3=$K$6,DATE(YEAR(D3)+$L$6,MONTH(D3)+$M$6,DAY(D3)),""))))
and
=IF($C3=$O$3,DATE(YEAR(D3)+$P$3,MONTH(D3)+$Q$3,DAY(D3)),IF($C3=$O$4,DATE(YEAR(D3)+$P$4,MONTH(D3)+$Q$4,DAY(D3)),IF($C3=$O$5,DATE(YEAR(D3)+$P$5,MONTH(D3)+$Q$5,DAY(D3)),"")))
which work as required in two separate columns. What I would like is to Nest them again so that depending on the choice made from a Data Validation dropbox (Choice 1 or Choice 2, in the following) it either displays the date calculated from the first Choice, or from the second. This is what I have, but I can't get it to work. I think I need an OR in there, but I don't know where, as there are so many IFs already.
=IF($I$2=”Choice1”,IF($B3=$K$3,DATE(YEAR(D3)+$L$3,MONTH(D3)+$M$3,DAY(D3)),IF($B3=$K$4,DATE(YEAR(D3)+$L$4,MONTH(D3)+$M$4,DAY(D3)),IF($B3=$K$5,DATE(YEAR(D3)+$L$5,MONTH(D3)+$M$5,DAY(D3)),IF($B3=$K$6,DATE(YEAR(D3)+$L$6,MONTH(D3)+$M$6,DAY(D3)))),IF($I$2=”Choice2”,IF($C3=$O$3,DATE(YEAR(D3)+$P$3,MONTH(D3)+$Q$3,DAY(D3)),IF($C3=$O$4,DATE(YEAR(D3)+$P$4,MONTH(D3)+$Q$4,DAY(D3)),IF($C3=$O$5,DATE(YEAR(D3)+$P$5,MONTH(D3)+$Q$5,DAY(D3))),""))))))
If it was just one column of dates I can use this..
=IF($I$2="Choice 1",$E4, IF($I$2="Choice 2",$F4,""))
with a couple of helper columns, but I could have as many as 10, which would require 20 helper columns on a spreadsheet that's already 70 odd columns wide, which I'd rather avoid if possible. I've done this on a test worksheet, rather than mess about with the original for now.
EDIT Additional information as requested. (Edited to generic terms as it's a work item)
I have these columns
and using the following dropdown..
would like the date in "Choice 1 OR 2 Increase" to update depending on the selection of either "Choice 1" or Choice 2" information chosen from either of the two sets of Category dropdowns..
This formula takes the information from the first date dropdown and correctly calculates the new date..
=IF($B3=$K$3,DATE(YEAR(D3)+$L$3,MONTH(D3)+$M$3,DAY(D3)),IF($B3=$K$4,DATE(YEAR(D3)+$L$4,MONTH(D3)+$M$4,DAY(D3)),IF($B3=$K$5,DATE(YEAR(D3)+$L$5,MONTH(D3)+$M$5,DAY(D3)),IF($B3=$K$6,DATE(YEAR(D3)+$L$6,MONTH(D3)+$M$6,DAY(D3)),""))))
with Category 1 - 4, in that order, being the four date sections of this formula.
This formula takes the information from the second date dropdown and correctly calculates the new date..
=IF($C3=$O$3,DATE(YEAR(D3)+$P$3,MONTH(D3)+$Q$3,DAY(D3)),IF($C3=$O$4,DATE(YEAR(D3)+$P$4,MONTH(D3)+$Q$4,DAY(D3)),IF($C3=$O$5,DATE(YEAR(D3)+$P$5,MONTH(D3)+$Q$5,DAY(D3)),"")))
with Category 5-7, in that order being the three date sections of this formula.
Both formulas work correctly when used independently of each other to populate individual columns, and a third column can be used to get the date required (using the dates already provided separately in two "helper" columns) using the following formula..
=IF($I$2="Choice1",$E3, IF($I$2="Choice2",$F3,""))
What I would like is to be able to combine the actions of both of the above formulas somehow, so that by using the Choice 1/Choice 2 dropdown (Pic 2), it calculates the date depending on the choice in that dropdown box, and also the other two dropdown boxes (Pics 3 + 4) and populates the "Choice 1 OR 2 Increase" column (Pic 1)
If I was only using this one example, I'd just use the helper columns but there will be several, and the sheet is around 70 columns wide already. Combining (at least the actions of) these two formulas into one, will save a lot of extra columns.
I hope that's the information you require..
Thanks
Liam
I would set things up differently, and use a different formula.
Since your Categories and Choices do not overlap, I would combine all the categories into a single table.
eg:
Since both Years and Months can have a varying number of days, I'd suggest using EDATE for the additions.
I also used a Named Range for the Choice dropdown,
and a Table for the Category table.
Doing that, you can use this formula (assuming your data table is in A1:Cn)
=EDATE(C2,VLOOKUP(INDEX($A2:$B$5,1,MATCH(Choice,$A$1:$B$1,0)),Category,2,FALSE)*12 + VLOOKUP(INDEX($A2:$B$5,1,MATCH(Choice,$A$1:$B$1,0)),Category,3,FALSE))
The formula
MATCH decides which column of category choice to use
VLOOKUP to return the appropriate years and months
EDATE(Date, years*12 + months)
If you prefer to use your method of adding datevalues, you can apply the same methodology:
=DATE(YEAR(C2)+VLOOKUP(INDEX($A2:$B$5,1,MATCH(Choice,$A$1:$B$1,0)),Category,2,FALSE),MONTH(C2)+VLOOKUP(INDEX($A2:$B$5,1,MATCH(Choice,$A$1:$B$1,0)),Category,3,FALSE),DAY(C2))
Note that the two methods can give different results depending on the day of the month, and whether the end month has the same number of days as the start month.
eg:
31 January 2020 + 1 month --> 29 Feb 2020 vs 02 Mar 2020
31 January 2020 + 3 month --> 30 Apr 2020 vs 01 May 2020

Finding a shorter period of days within a longer period for calculation

I have a set of dates, in total 7 periods spanning 6 months each with corresponding calculation factor.
I will have user input of period for which they'd want the calculation to be done, which can fall within one of the 6 months periods or encompass between two or more such periods wholly or partially.
Illustration:
The preset periods:
User input:
I've obtained decimal value (monthly basis) of the periods input by the user for calculation. For first instance (see user input), the decimal value for the period 01-01-2015 to 29-04-2015 will be 3.97 on monthly basis. The calculation for that period would be like:
n*3.97*113%
For the second instance, the decimal value for the period 30-04-2015 to 30-06-2015 would be 2.03, which would be used to do calculation at 113% and then the result will be added to the calculation done at 119% using the decimal value 5.65 for the period 01-07-2015 to 20-12-2015:
(n*2.03*113%)+(n*5.65*119)
Think I can handle the breaking up of periods since the revision event is bi-annual on particular dates but advice regards to that is welcome. More importantly, I need help tracing the preset calculation factor (say 132%) corresponding to the period input by the user as illustrated above. Is it feasible?
I will use the standard approach for finding the overlap between two dates and will split the task into three parts as in my answer to this recent question.
(1) The first part is finding the overlap between the user's range of dates and one or more revision periods in whole months and will need an array formula. I have chosen to use the Datedif function 1 to get the difference in months between the beginning and end of the overlaps. If there is no overlap, the start date fed in to Datedif will be after the end date, and it will return an error which can be trapped by Iferror. If the user's dates start in A2 and B2, this gives in C2:
=SUM(IFERROR((DATEDIF(IF(K$2:K$8>A2,K$2:K$8,A2),IF(L$2:L$8<B2,L$2:L$8,B2),"m")+1)*M$2:M$8,0))
which has to be entered as an array formula using CtrlShiftEnter
The above result includes the first and last months entered by the user even if they are incomplete months. It's then necessary to subtract any missing days in the first and last months.
(2) Missing days in first month as a fraction of the number of days in that month in D2:
=SUMIFS($M$2:$M$8,$K$2:$K$8,"<="&A2,$L$2:$L$8,">="&A2)*(A2-EOMONTH(A2,-1)-1)/(EOMONTH(A2,0)-EOMONTH(A2,-1))
A noted by OP, this could also have been done using sumproduct, vlookup or index/match.
(3) Missing days in last month as a fraction of days in that month in E2:
=SUMIFS($M$2:$M$8,$K$2:$K$8,"<="&B2,$L$2:$L$8,">="&B2)*(EOMONTH(B2,0)-B2)/(EOMONTH(B2,0)-EOMONTH(B2,-1))
The total is just (1)-(2)-(3) or
=C2-D2-E2
I have put the results of OP's two examples for comparison in H2 and H3: my results agree with them in the first 3 significant figures.
n*3.97*113%
(n*2.03*113%)+(n*5.65*119)
In all cases I have set n=1 and ignored the fact that the rate is a percentage.
This shows how the results would be calculated manually:
1 Pros of using Datedif:
(1) Works across year boundaries unlike just using Month function.
(2) Works conveniently with Iferror to identify non-matching date ranges.
Cons of using Datedif:
(1) It is an undocumented function and may be withdrawn in future.
(2) In this particular case, all date calculations are within the same year so Month would be useable.

Sorting alphanumeric dates in Excel

I have a data set were a column represents the expiry date of a product in the following format: 1M, 2M, 1Y, 2Y, 1W, 2W, 1D, 2D. I would like to sort my data based on these dates in Excel, but I'm doing it in a very inefficient way, by expressing everything in days and then sorting the data according to the Days_column I create. Is there a better way to deal with this kind of data?
I think I have this understood. Here is a picture of the final result:
I found some good information here: https://support.office.com/en-us/article/Add-or-subtract-dates-b83768f5-f695-4311-98b1-757345f7e926#bm6
I put this in D2 and copied it down: =LEFT(C2,LEN(C2)-1). In cell E2 I put =RIGHT(C2,1), and copied it all the way down. In F2 I have =IF(E2="Y",DATE(YEAR(A2)+D2,MONTH(A2),DAY(A2)),IF(E2="M",EDATE(A2,D2),IF(E2="D",A2+D2,IF(E2="W",A2+(D2*7),"x")))).
Notes: Adding months is based on the number of days in the upcoming months, and not always equal to 30. Notice that 1 month added to 1/31/2016 puts you at 2/29/2016. Adding the year works the same way, you don't have to worry about leap years messing you up.
For weeks I used the number of weeks multiplied by 7, and then just added those days to the Buying date.
You could split your expiry into two columns - Expiry_number i.e. the duration or numeric part of the expiry, and Expiry_unit i.e. M, D, Y. You can split this using functions, for example your numeric column:
=LEFT(D3, LEN(D3)-1)
where D3 is the expiry. And then your units column:
=Right(D3, 1)
Then you can sort the the data on two levels - alphabetically on the Expiry_unit (as chance would have it the durations units increase in length alphabetically D, M, Y) and then numerically on Expiry_number.

Resources