Excel adjustment of values - Max 3 iterations - excel

I have following values in MS Excel.
Years: Y1, Y2, Y3, Y4, Y5, Y6 Y7 Y8 Y9 Y10
Income: -10, 2, 5, 6, -4, 8, -3, 6, 5, 2
Let us assume the Income values are entered in cell range C3:L3
Tax rate is 50% of Net Income. Tax will be Nil if yearly Net income is <= 0. Moreover, if the previous year or years income is negative, it may adjusted against current year's income. The adjustment cannot be done for more than 3 consecutive years. For eg. Loss of Y1(-10) can be adjusted until Y3 only. Y4 will not absorb any previous year's losses. Similarly Y6 will adjust -4 from Y5 and the Net income for Y6 will be 4. The tax in Y6 will be 4*50% = 2
Using the above logic, the corresponding tax amounts(done manually) will be:
Tax: 0, 0, 0, 3, 0, 2, 0, 1.5, 2.5, 1
Can you build an excel formula that can compute the above Tax(shown manually above) and limit the adjustments? No helper rows or columns to be used. I guess Offset() may be used.
Thanks in advance

assuming your formulae are in rows C3 to L3 :
I believe this would work C4:
=50%*MAX(0,C3+MIN(0,MIN(SUM(A3:B3),B3)))
And you can then extend it to the 10 cells.

Related

Simple(r) Excel formula to calculate forward stock (inventory) cover

This is a perennial question for retailers, for which there are a number of solutions in existence:
How can you calculate the "forward cover" of a product knowing its current inventory and armed with forward sales estimates.
eg.
current inventory 100 units (cell A1)
weekly forward sales estimates: 25, 30, 10, 40, 90... (in range
A2:AX)
Here the answer would be 3.875 weeks (3 full weeks plus 0.875 of week 4)
I have a UDF to do this already.
I also have some slightly complicated array functions to do this, eg.
=MATCH(TRUE,SUBTOTAL(9,OFFSET(A2:A13,,,ROW(A2:A13)-ROW(A2)+1))>A1,0)-1+(A1-SUM(A2:INDEX(A2:A13,MATCH(TRUE,SUBTOTAL(9,OFFSET(A2:A13,,,ROW(A2:A13)-ROW(A2)+1))>A1,0)-1)))/INDEX(A2:A13,MATCH(TRUE,SUBTOTAL(9,OFFSET(A2:A13,,,ROW(A2:A13)-ROW(A2)+1))>A1,0)-1+1)
I was wondering if there is a neater way with these 'new-fangled' array functions which have been available for the last few years in later versions of Excel?
Here is another possible solution, although it requires the LET() function which is only available to newer version of excel (2021, 365 and later I believe).
The solution would be the following formula:
=LET(
sales,A2:A50,
inventory,A1,
cum_sum,MMULT(SEQUENCE(1,ROWS(sales),1,0),(ROW(sales)<=TRANSPOSE(ROW(sales)))*sales),
week_full,MATCH(TRUE,inventory<cum_sum,0) - 1,
week_frac,(inventory - INDEX(cum_sum,week_full)) / INDEX(sales,week_full + 1),
week_full + week_frac
)
Explanation
Given inventory and the forward looking sales estimates, the formula calculates the running total (i.e. cumulated sum) of the sales estimates as shown in the table here below
Inv and Sales
Cumulated Sum
Inv > Cum_Sum
Week
100
25
25
0
1
30
55
0
2
10
65
0
3
40
105
1
4
90
195
1
5
...
...
1
6
The formula goes on to get the number of full weeks of 'forward cover' by finding the the value for the cumulated sum that exceeds the inventory minus one (here 4 - 1 = 3).
Lastly, for the value of the week fraction covered in the last week, the formula calculates inventory minus sum of sales estimates of all previous weeks divided by sales estimate of final week of cover (i.e. (100 - 65) / 40 = 0.875).
Edit
After simplifying the formula you used with the LET() function, I noticed it's doing exactly the same calculation with the only difference of how the cumulated sum is being calculated. Here's your formula using LET():
=LET(
sales,A2:A50,
inventory,A1,
cum_sum,SUBTOTAL(9,OFFSET(sales,,,SEQUENCE(ROWS(sales)))),
week_full,MATCH(TRUE,cum_sum>inventory,0)-1,
week_frac,(inventory - INDEX(cum_sum,week_full)) / INDEX(sales,week_full+1),
week_full + week_frac
)
=LET(inv,A1,
sales,A2:A6,
cs,SCAN(0,sales,LAMBDA(x,y,x+y)),
m,XMATCH(A1,cs,1)-1,
m+(inv-
IF(m=0,
0,
INDEX(cs,m)))
/INDEX(sales,m+1))
SCAN() is perfect for creating a cumulative sum.
It can be referenced inside XMATCH because of the use of LET.
Here m returns the number of full weeks and the final calculation is the number of full weeks + (inv- cumulative sum up to the full week)/sales of the following week.

IF function for if x > y, but < yz multiple by b

So this is what I’m trying to do. If the percent of an output (let’s call it A1) is <75% multiply by 0. If it’s between 75-100% multiply by 1, if it’s between 100-150% multiply by 2, etc.
Scott Craner's MATCH answer is already good in the comments. But if you are looking for a plain IF function:
=IF(A1 < 0.75, 0,
IF(A1 < 1, B1,
IF(A1 < 1.5, B1 * 2)))
Although, I recommend using IFS for readability since we can opt not to include else values due to the non-conflicting conditions.
=IFS(
A1 < 0.75, 0,
A1 < 1, B1,
A1 < 1.5, B1 * 2
)
Sample Output:
Note:
Sheets read the formula left to right (top to bottom) so if it doesn't match the first condition, it will just proceed to the next one.
Feel free to adjust the ranges if it must be inclusive to the upper limit. (e.g < to <=)
Notice that 1st and 2nd values were not multiplied by 0 and 1, as we all know, the result would be 0 and the number itself respectively thus I opted from multiplying B1 to those numbers.
Sample outputs in the sheet shown are respective to their rows.
use:
=INDEX(IFNA(VLOOKUP(A1, {0.75, 0; 1, B1; 1.5, B1*2}, 2, 0)))

Loop through row multiplying by one row VBA

I have a set of weights in rows BA40:BZ40 and I want each row starting from BA60:BZ60 to sum (BA40*BA60 + BB40*BB60 + ... + BZ40*BZ60). Then paste this in CA60 then move onto row 61. However I still need to reference BA40:BZ40. I don't know if its my simplistic mind getting confused or its not possible. However I have learnt everything is possible. My code at the moment is
Dim cellsum As Long
For i = 60 to 1000
So I want to calculate for each day, the weighted sum of the loss. For example day 1, sum(0.2*(-10)+ 0.2*(-8)+ 0.1*(-6) + 0.5(-4))
Weight: 20%, 20%, 10%, 50%
Day 1: -10, -8, -6, -5
Day 2: -9, -8, -7, -6
Day 3: -5, -5, -4, -4
...
Use SUMPRODUCT() function as following. It will automatically calculate percentage. You do not need to sum as .2, .1
=SUMPRODUCT(BA40:BZ40,BA60:BZ60)
Imagine the follwing table:
Then the weighted sum of day 1 would calculate according to your example like …
=SUM($B$1*B3,$C$1*C3,$D$1*D3,$E$1*E3)
which is the same as …
=SUMPRODUCT($B$1:$E$1,B3:E3)
This formula in G3 then can easily pulled/copied down until G5.
So for your data it should be something like the following in cell CA60 …
=SUMPRODUCT($BA$40:$BZ$40,BA60:BZ60)
and then copy down to the other rows.

np.percentile not equal to quartiles

I'm trying to calculate the quartiles for an array of values in python using numpy.
X = [1, 1, 1, 3, 4, 5, 5, 7, 8, 9, 10, 1000]
I would do the following:
quartiles = np.percentile(X, range(0, 100, 25))
quartiles
# array([1. , 2.5 , 5. , 8.25])
But this is incorrect, as the 1st and 3rd quartiles should be 2 and 8.5, respectively.
This can be shown as the following:
Q1 = np.median(X[:len(X)/2])
Q3 = np.median(X[len(X):])
Q1, Q3
# (2.0, 8.5)
I can't get my heads round what np.percentile is doing to give a different answer. Any light shed on this, I'd be very grateful for.
There is no right or wrong, but simply different ways of calculating percentiles The percentile is a well defined concept in the continuous case, less so for discrete samples: different methods would not make a difference for a very big number of observations (compared to the number of duplicates), but can actually matter for small samples and you need to figure out what makes more sense case by case.
To obtain you desired output, you should specify interpolation = 'midpoint' in the percentile function:
quartiles = np.percentile(X, range(0, 100, 25), interpolation = 'midpoint')
quartiles # array([ 1. , 2. , 5. , 8.5])
I'd suggest you to have a look at the docs http://docs.scipy.org/doc/numpy/reference/generated/numpy.percentile.html

Expanding a condensed list to find the median

Column A has a x number of units and column b has an xx amount set for those number of units (a1 = 3, b1 = 100, a2 = 2, b2 = 150, etc). Is there a way to easily write out all items in column b the number of times specified in column a to easily use the median function? In this example: 100, 100, 100, 150, 150 = 100 median amount.
You could try this:
=MEDIAN(IF(FREQUENCY((SUM(B1:B4)+{0,1})/2,SUMIF(A1:A4,"<="&A1:A4,B1:B4)),A1:A4))
For example the following returns Median = 2.5
Num Amount
3 200
2 150
4 100
1 150
The ranges can be extended to fit the required data range. The Amount column is a positive integer and Num is any numerical value.

Resources