I have 4 arrays of data where I need a some product but with few conditions.
I'm unable to solve that and I'm not good at creating VBA functions as well.
Can anyone please help?
Apologies for the lack of clarity.
I'll try to give more details here. Please refer the below workbook.
https://drive.google.com/file/d/1XVEe4Sjw6ZeAh-7jyeLDs7Tp5RRQD20i/view?usp=sharing
Investment value is Row 2 * Row 3.
This value is carried across all the months after amortization given in row 4. 5th row is converting the yearly value into monthly value (1/12).
So, in the first month 50 is invested and the value at the beginning of the month after amort of 100%, So 50 is available for month 1. This is further converted into monthly values with the help of row 5. So, the result for month 1 will be 100 * 50% * 100% * 8.33% = 4.1667 [Cell I9]
For the month 2, the value available is,
Value carried from month 1 after amort (100 * 50% * 99%) +
New amount in month 2 (102 * 50% * 100%)
The above value is converted into the monthly value again with the help of row 5.
Result for month 2 => Cell I10 = (100 * 50% * 99% * 8.33%) + (102 * 50% * 100% * 8.33%) = 8.375
Similarly, for month 3 the value will be,
Month 1's investment (100*50%*98%*8.33%) +
Month 2's investment (102*50%*99%*8.33%) +
Month 3's investment (104*50%*100%*8.33%)
I need the above calculation to happen in single cell for all the months. I tried sumproduct with offset. But I couldn't.
REVISED (based upon comment 'all values are dynamic)...
Plug this into cell b6 per screenshot, drag to right:
=SUM($B2:B2*$B3:B3*$B4:B4*$B5:B5)
This will evaluate the sums you have indicated below the 24 month table [at top your linked spreadsheet] i.e. which correspond to respective months 1,2,... etc.
PREVIOUS SOLN:
HIGH LEVEL
Let cell A1 contain the month (=π, π π β). Plug this into excel to get the sum of the π terms for k = 1,...,π:
=A1*(98-A1+(3/2)*(1+A1)+(1/50)*((1+A1)*((2*A1+1)/6-A1/2-1/2)+A1))/24
DERIVATION
Your sequence has π terms; let π‘(π) be the πth such term:
π‘(π) = (100+2(πβ1))(1β(πβπ)/100)/24
where 1 < 2 < ,..., β€ π β€ ,.., π. Let π(π) be the sum over π = 1, ... , π. It immediately follows that:
π(π)= (1/24) β(100+2(πβ1))(1β(πβπ)/100); π π β; π = 1,2,..,π
Elementary simplification yields the following:
π(π) = (1/24) π { 98 - π + 1.5 (1 + π) + 0.02 {(1+π)((2π+1)/6 - π/2 - 1/2) +r } }
(ππΈπ· β»)
CHECKS
π (A1)
Result
Status
1
4.17
β
2
8.38
β
3
12.62
β
4
16.91
β
5
21.24
β
..
..
n/a
24
109.81
β
Related
Suppose I index the days of the week starting with 1 as Monday and 7 as Sunday. I have four arrays x, y, z and r which store variables for each day of the week. For example, x[1] is the amount of revenue earned on Monday, y[7] is the amount of revenue carried over from Sunday and z[6] is the amount of revenue saved from Saturday.
The total revenue on Monday is x[1] + y[7] + z[6] = r[1]. Similarly, the total revenue on Tuesday is x[2] + y[1] + z[6] = r[2].
I am trying to write a for loop something like this:
for i in 1:7
x[i] + y[i-1] + z[i-2] = d[i]
end
Where when i = 1 and i = 2, the indexing does not become less than or equal to 0 (my indexing starts at 1 and if the result is 0 I get an out of bounds error).
I tried using the modulo function to assist with this, but I realize I am getting 0 in some cases, no matter what values I try. For example, adding 7 and then applying modulo 7 ensures that z[i-2] is z[6] when i = 1, but gives y[i-1] = y[0] when i = 1:
for i in 1:7
x[(i+7)%7] + y[(i-1+7)%7] + z[(i-2+7)%7] = d[(i+7)%7]
end
Is there an efficient solution for this?
Add 6 instead of 7 inside the modulo and add one outside.
( i + 6 ) % 7 + 1
I'm creating a stored procedure in SQL Server for a cricket application. How can I find the total number of balls, given there are 6 balls in an over.
Suppose there are 4 overs. We can easily calculate 4 * 6. But what if there were 4.5 overs? I also want to sum the two different cricket matches over of a particular bowler over.
For example:
match1 overs 4.5
match2 overs 6.3
addition should be 11.2
With a calculator we get 10.8
Here is what I tried
COALESCE(Sum(Overs),0) * 6 + (COALESCE(Sum(Overs),0) - COALESCE(Sum(Overs),0))* 10 as Totalballs,
Based on your last comment, we can first FLOOR the over to find what the first multiple will be.
Then we subtract the over from that, convert to INT, and add.
declare #over decimal(4,1) = 4.5
select
SixeTimesThis = floor(#over)
,Remainder = (#over - floor(#over))
,RemainderAsInt = cast(replace((#over - floor(#over)),'.','') as int)
,FinalResult = floor(#over) * 6 +cast(replace((#over - floor(#over)),'.','') as int)
You can use modulus % to get the extra balls.
Example snippet:
select *, coalesce(floor(Overs)*6 + floor((Overs%1)*10), 0) as Balls
from (values
(1.0),
(4.0),
(4.5),
(null)
) as v(Overs);
Test on db<>fiddle here
Result:
Overs Balls
----- -----
1.0 6
4.0 24
4.5 29
NULL 0
I'm looking to improve my code efficiency by turning my code into arrays and loops. The data i'm working with starts off like this:
ID Mapping Asset Fixed Performing Payment 2017 Payment2018 Payment2019 Payment2020
1 Loan1 1 1 1 90 30 30 30
2 Loan1 1 1 0 80 20 40 20
3 Loan1 1 0 1 60 40 10 10
4 Loan1 1 0 0 120 60 30 30
5 Loan2 ... ... ... ... ... ... ...
So For each ID (essentially the data sorted by Mapping, Asset, Fixed and then Performing) I'm looking to build a profile for the Payment Scheme.
The Payment Vector for the first ID looks like this:
PaymentVector1 PaymentVector2 PaymentVector3 PaymentVector4
1 0.33 0.33 0.33
It is represented by the formula
PaymentVector(I)=Payment(I)/Payment(1)
The above is fine to create in an array, example code can be given if you wish.
Next, under the assumption that every payment made is replaced i.e. when 30 is paid in 2018, it must be replaced, and so on.
I'm looking to make a profile that shows the outflows (and for illustration, but not required in code, in brackets inflows) for the movement of the payments as such - For ID=1:
Payment2017 Payment2018 Payment2019 Payment2020
17 (+90) -30 -30 -30
18 N/A (+30) -10 -10
19 N/A N/A (+40) -13.3
20 N/A N/A N/A (+53.3)
so if you're looking forwards, the rows can be thought of what year it is and the columns representing what years are coming up.
Hence, in year 2019, looking at what is to be paid in 2017 and 2018 is N/A because those payments are in the past / cannot be paid now.
As for in year 2018, looking at what has to be paid in 2019, you have to pay one-third of the money you have now, so -10.
I've been working to turn this dataset row by row into the array but there surely has to be a quicker way using an array:
The Code I've used so far looks like:
Data Want;
Set Have;
Array Vintage(2017:2020) Vintage2017-Vintage2020;
Array PaymentSchedule(2017:2020) PaymentSchedule2017-PaymentSchedule2020;
Array PaymentVector(2017:2020) PaymentVector2017-PaymentVector2020;
Array PaymentVolume(2017:2020) PaymentVolume2017-PaymentVolume2020;
do i=1 to 4;
PaymentVector(i)=PaymentSchedule(i)/PaymentSchedule(1);
end;
I'll add code tomorrow... but the code doesn't work regardless.
data have;
input
ID Mapping $ Asset Fixed Performing Payment2017 Payment2018 Payment2019 Payment2020; datalines;
1 Loan1 1 1 1 90 30 30 30
2 Loan1 1 1 0 80 20 40 20
3 Loan1 1 0 1 60 40 10 10
4 Loan1 1 0 0 120 60 30 30
data want(keep=id payment: fraction:);
set have;
array p payment:;
array fraction(4); * track constant fraction determined at start of profile;
array out(4); * track outlay for ith iteration;
* compute constant (over iterations) fraction for row;
do i = dim(p) to 1 by -1;
fraction(i) = p(i) / p(1);
end;
* reset to missing to allow for sum statement, which is <variable> + <expression>;
call missing(of out(*));
out(1) = p(1);
do iter = 1 to 4;
p(iter) = out(iter);
do i = iter+1 to dim(p);
p(i) = -fraction(i) * p(iter);
out(i) + (-p(i)); * <--- compute next iteration outlay with ye olde sum statement ;
end;
output;
p(iter) = .;
end;
format fract: best4. payment: 7.2;
run;
You've indexed your arrays with 2017:2020 but then try and use them using the 1 to 4 index. That won't work, you need to be consistent.
Array PaymentSchedule(2017:2020) PaymentSchedule2017-PaymentSchedule2020;
Array PaymentVector(2017:2020) PaymentVector2017-PaymentVector2020;
do i=2017 to 2020;
PaymentVector(i)=PaymentSchedule(i)/PaymentSchedule(2017);
end;
I am versed in MATLAB but find myself working in VBA these days as MATLAB is less accessible to me and I struggle with trying to do stuff in VBA (like vectorization) that I could easily handle in MATLAB.
Lets say I have a data table in excel of the following form:
record startDate endDate count
1 100 103 10
2 98 102 5
3 101 104 4
I would like to do all my processing in memory (avoiding loops) and then output results file that looks like this:
1 2 3 Sum
98 0 5 0 5
99 0 5 0 5
100 10 5 0 15
101 10 5 4 19
102 10 5 4 19
103 10 0 4 14
104 0 0 4 4
Basically, I start with earliest date and loop through the latest date and then check to see if each date is included in the date window for each record and if it is I apply the record count to that day and then sum them up.
I created the included output using a simple worksheet function, but I would like to be able to replicate the process in VBA specifically avoiding looping at least reducing to 1 loop instead of embedded loops.
If I were in MATLAB I would find the logical array that meets a condition, for example:
numDays = 7;
numRecords = 3;
startDate = [100; 98; 101];
endDate = [103; 102; 104];
dateVector = [98; 99; 100; 101; 102; 103; 104];
count = [10; 5; 4];
dateLogic = logical(numDays,numRecords);
for d = 1:numDays
dateLogic(d,:) = dateVector(d) >= startDate(:,1) & dateVector(d) <= endDate(:,1)
end
countMatrix = dateLogix * count';
Sum = sum(countMatrix,2);
This would give me a logical matrix of zeros and ones that I can cross multiply with count vector to get my counts and ultimately my Sum vector. I believe I could even use a bsxfun to remove the loop on days.
Please excuse any potential syntax errors as I do not have access to MATLAB right now.
Anyway, how can I do something similar in VBA. Is there an equivalent colon notation to reference the entire range of columns or rows in an array. I will be applying to large data set so efficiency is of the essence. The more I can do in memory before pasting the better.
Thanks in advance.
Here's one possibility, try with sampe data in A1:A4 of a new workbook.
Sub NewTable()
Set Table = Sheet1.[a2:d4]
With Application
Record = .Transpose(.Index(Table, , 1))
FirstDate = .Transpose(.Index(Table, , 2))
LastDate = .Transpose(.Index(Table, , 3))
Count = .Transpose(.Index(Table, , 4))
Dates = .Evaluate("row(" & .Min(FirstDate) & ":" & .Max(LastDate) & ")")
Values = .PV(, Count, .PV(, .GeStep(Dates, FirstDate), .GeStep(LastDate, Dates)))
Sum = .MMult(Values, .Power(.Transpose(Record), 0))
End With
Sheet1.[F1].Offset(, 1).Resize(, UBound(Values, 2)) = Record
Sheet1.[F2].Resize(UBound(Dates)) = Dates
Sheet1.[G2].Resize(UBound(Values), UBound(Values, 2)) = Values
Sheet1.[G2].Offset(, UBound(Values, 2)).Resize(UBound(Dates)) = Sum
End Sub
I've been looking for a while onto websearch, however, possibly or probably I am missing the right terminology.
I have arbitrary sized arrays of scalars ...
array = [n_0, n_1, n_2, ..., n_m]
I also have a function f->x->y, with 0<=x<=1, and y an interpolated value from array. Examples:
array = [1,2,9]
f(0) = 1
f(0.5) = 2
f(1) = 9
f(0.75) = 5.5
My problem is that I want to compute the average value for some interval r = [a..b], where a E [0..1] and b E [0..1], i.e. I want to generalize my interpolation function f->x->y to compute the average along r.
My mind boggles me slightly w.r.t. finding the right weighting. Imagine I want to compute f([0.2,0.8]):
array --> 1 | 2 | 9
[0..1] --> 0.00 0.25 0.50 0.75 1.00
[0.2,0.8] --> ^___________________^
The latter being the range of values I want to compute the average of.
Would it be mathematically correct to compute the average like this?: *
1 * (1-0.8) <- 0.2 'translated' to [0..0.25]
+ 2 * 1
avg = + 9 * 0.2 <- 0.8 'translated' to [0.75..1]
----------
1.4 <-- the sum of weights
This looks correct.
In your example, your interval's length is 0.6. In that interval, your number 2 is taking up (0.75-0.25)/0.6 = 0.5/0.6 = 10/12 of space. Your number 1 takes up (0.25-0.2)/0.6 = 0.05 = 1/12 of space, likewise your number 9.
This sums up to 10/12 + 1/12 + 1/12 = 1.
For better intuition, think about it like this: The problem is to determine how much space each array-element covers along an interval. The rest is just filling the machinery described in http://en.wikipedia.org/wiki/Weighted_average#Mathematical_definition .