I have an integer array of values and want to find a simple way of calculating its cumulative sum (S = Data(1) + Data(2) + ... + Data(x)
).
I already created this function:
Function CumulativeSum(Data() As Integer, k As Integer) As Integer
For entry = 1 To k
CumulativeSum = CumulativeSum + Data(entry)
Next entry
End Function
and it's working fine. However, I wonder if there's a better way of doing it (mainly without the use of any extra function and essentially using only excel functions like Application.Sum
). I made a small search on the web but didn't find anything on this basis.
I know I'm not asking to correct any code and I'm just asking for an alternative which is not the real purpose of this forum. However, I also suspect that the answer could be simple, so... If anyone care to help me I'll appreciate very, very much! If you find an answer to a similar question, please share the link with me and I'll remove this one.
I'm very sorry for probably my lack of explicitly on my demand: I simply want to find a simple way of calculating the cumulative sum using simple functions on the macro routine itself, WITHOUT using the CumulativeSum
function I created or any other function created by the user.
If you want to achieve a cumulative array array like Array(a,a+b,a+b+c) from Array(a,b,c), then this is the function to achieve it, if you want to pass start and end parameters:
Public Sub TestMe()
Dim outputArray As Variant
Dim inputArray As Variant
Dim counter As Long
inputArray = Array(1, 2, 4, 8, 16, 32, 64)
outputArray = generateCumulativeArray(inputArray, 1, 4)
For counter = LBound(outputArray) To UBound(outputArray)
Debug.Print outputArray(counter)
Next counter
outputArray = generateCumulativeArray(inputArray, toValue:=4)
For counter = LBound(outputArray) To UBound(outputArray)
Debug.Print outputArray(counter)
Next counter
End Sub
Public Function generateCumulativeArray(dataInput As Variant, _
Optional fromValue As Long = 0, _
Optional toValue As Long = 0) As Variant
Dim i As Long
Dim dataReturn As Variant
ReDim dataReturn(0)
dataReturn(0) = dataInput(fromValue)
For i = 1 To toValue - fromValue
ReDim Preserve dataReturn(i)
dataReturn(i) = dataReturn(i - 1) + dataInput(fromValue + i)
Next i
generateCumulativeArray = dataReturn
End Function
Concerning just summing an array, this is the way to do it:
You can use the WorksheetFunction.
and you can pass the array as an argument. Thus, you get all the functions, e.g. Average
, Min
, Max
etc:
Option Explicit
Public Sub TestMe()
Dim k As Variant
k = Array(2, 10, 200)
Debug.Print WorksheetFunction.Sum(k)
Debug.Print WorksheetFunction.Average(k)
End Sub
If you want the sum from a given start to a given end, the easiest way is probably to make a new array and to sum it completely. In Python this is called slicing, in VBA this could be done a bit manually:
Public Sub TestMe()
Dim varArr As Variant
Dim colSample As New Collection
varArr = Array(1, 2, 4, 8, 16, 32, 64)
colSample.Add (1)
colSample.Add (2)
colSample.Add (4)
colSample.Add (8)
Debug.Print WorksheetFunction.Sum(generateArray(varArr, 2, 4))
Debug.Print WorksheetFunction.Sum(generateArray(colSample, 2, 4))
End Sub
Public Function generateArray(data As Variant, _
fromValue As Long, _
toValue As Long) As Variant
Dim i As Long
Dim dataInternal As Variant
Dim size As Long
size = toValue - fromValue
ReDim dataInternal(size)
For i = LBound(dataInternal) To UBound(dataInternal)
dataInternal(i) = data(i + fromValue)
Next i
generateArray = dataInternal
End Function
The idea is that the generateArray
function returns a new array. Thus, its complete sum is what you need. It works also with collections, not only with arrays. Be careful, when using collections, they start with index 1, while arrays (usually) start with 0. If you want to use the same indexing for Arrays and Collections, then change the generateArray function to this one:
Public Function generateArray(data As Variant, _
fromValue As Long, _
toValue As Long) As Variant
Dim i As Long
Dim dataInternal As Variant
Dim size As Long
size = toValue - fromValue
ReDim dataInternal(size)
If IsArray(data) Then
For i = LBound(dataInternal) To UBound(dataInternal)
dataInternal(i) = data(i + fromValue)
Next i
Else
For i = LBound(dataInternal) To UBound(dataInternal)
dataInternal(i) = data(i + fromValue + 1)
Next i
End If
generateArray = dataInternal
End Function
Or write Option Base 1
on top and the array will start from 1 (not advised!).
Try this:
Sub test()
Dim arr As Variant
arr = Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
Dim mySum As Long, k As Long
Dim wsf As WorksheetFunction
Set wsf = Application.WorksheetFunction
k = 6
'operative line below
mySum = wsf.Sum(wsf.Index(arr, 1, Evaluate("ROW(1:" & k & ")")))
MsgBox mySum
End Sub
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With