Charles wrote...
>I actually found a solution thanks to an earlier post:
>
>Public Function WA(v As Variant, d As Variant) As Double
...
> For i = LBound(d, 1) To UBound(d, 1)
> dsum = dsum + v(i, 1) * d(i, 1)
[quoted text clipped - 5 lines]
> WA = CVErr(xlErrDiv0)
> End If
You don't include a check that v and d have the same number of items or
(more restrictive) are shaped the same. Since you don't check this,
your udf would return #VALUE! due to runtime errors whenever there are
fewer items in v than in d. Also, since you're the one who wants to
handle arrays as well as ranges, not all arrays are 2D, so the
assignment statements above would also throw runtime errors when v
and/or d is 1D. Finally, you can't return #DIV/0! unless the function's
return type is Variant. The CVErr assignment will also throw runtime
errors, thus returning #VALUE! rather than #DIV/0!.
Then there's the semantic issue that your udf accepts negative weights.
The safe way to do this would be something like
Function wa(v As Variant, w As Variant) As Double
Dim aw() As Double, t As Double, x As Variant
Dim sv As Double, sw As Double
Dim nv As Long, nw As Long
'make sure v and w aren't scalars
If Not IsArray(v) Then v = Array(v)
If Not IsArray(w) Then w = Array(w)
nw = 16 'positive initial value - modify as needed
ReDim aw(1 To nw)
nv = 0 'first using nv to count items in w
For Each x In w
nv = nv + 1
If nv >= nw Then
nw = 2 * nw
ReDim Preserve aw(1 To nw)
End If
aw(nv) = x
Next x
nw = nv
ReDim Preserve aw(1 To nw)
nv = 0 'now using nv to count items in v
For Each x In v
nv = nv + 1
t = aw(nv)
If t > 0 Then
sv = sv + x * t
sw = sw + t
End If
Next x
If nv = nw And sw > 0 Then
wa = sv / sw
ElseIf nv <> nw Then
wa = CVErr(xlErrNA)
Else
wa = CVErr(xlErrDiv0)
End If
End Function
When you need to process multiple array arguments, you should check
that they have the same number of items at least. Checking whether
they're the same shape is trickier, but sometimes that's necessary.