Reputation: 21
I am having some trouble figuring out how to return an array within a UDF from another UDF. The one here is a simple exponential moving average UDF and I am trying to return the array into another UDF but I am getting #value error. I feel there is a simple solution that I am not seeing. All help is greatly appreciated, thanks.
Function ema(arg1 As Variant, ByVal lngth As Long) As Variant
x = arg1
dim avg As Double
avg = 1
Dim arrema As Variant
arrema = Array()
ReDim arrema(1 To UBound(x, 1), 1 To 1)
For j = 1 To (UBound(x, 1) - lngth)
For i = (1 + j - 1) To (lngth + j - 1)
avg = (WorksheetFunction.Index(x, i, 1) + 1) * avg
Next i
arrema(j, 1) = avg ^ (1 / lngth)
avg = 1
Next j
'ema = avg ^ (1 / lngth)
ema = arrema
End Function
Function test(arg2 As Variant, xlength As Long)
Dim arra As Variant
'Call ema(arg2, xlength)
Dim arr As Variant
arr = Array()
ReDim arr(1 To UBound(arg2, 1), 1 To 1)
arra = ema(arg2, xlength)
For i = 1 To UBound(arg2, 1) - xlength
arr(i, 1) = arra(i, 1)
Next i
test = arr
End Function
Upvotes: 2
Views: 300
Reputation: 53126
If you are calling test
from a formula with a range as the arg1
parameter, then your problem is you are treating a Range
as if it were an Array
by calling UBound(arg2,1)
Change that to UBound(arg2.Value,1)
and it will work.
Further explanation:
By declaring the arg#
parameters as Variant
allows the UDFs to be called with either Range
's or Array
's. It may be better to be specific by using either As Range
or As Variant()
.
In Function ema
this issue is avoided by the line x = arg1
: If arg1
is a Range
then this copies the default property of the Range which is the Value
property to x
, making x
an array. If arg1
is an Array
then it just copies that array into x
.
Net result is Function ema
can handle either Ranges or Arrays. There is another issue there though: WorksheetFunction.Index(x, i, 1)
will fail with one dimensional Arrays. Change it to WorksheetFunction.Index(x, i)
or better still Application.Index(x, i)
to avoid this issue too.
Upvotes: 1