自定义函数返回#Value

时间:2018-04-06 15:52:27

标签: vba

我需要一组数据来创建加权平均值,因此我创建了一个自定义函数。

然而,有一些我无法弄清楚的奇怪行为。 首先,当函数在例程中计算时,它返回#VALUE。我故意,寻找字符串或空单元格,计算工作正常,直到我返回它的最后一行,然后它失败。

此外,点击the active cell > click the address bar > press enter后,它会正确计算。我想我只是按 Alt + Ctrl + f9 快捷方式,或者工作簿已自动重新计算,但事实并非如此。它配置正确。

同样奇怪的是,似乎计算运行3 TIMES功能。

数据看起来像这样。顶行是第8行,底部是25

 N              O       p   Q    R
 6,392        8,732     -   -   88.9%
 5,832       11,426     -   -   91.8%
 3,206        6,174     -   -   86.7%
 20,610      13,803     -   -   72.5%
 2,185        2,794     -   -   86.3%
 4,859        5,129     -   -   82.3%
 753          1,003     -   -   84.6%
 1,565        2,537     -   -   98.0%
 766          1,067     -   -   99.0%
 773            737     -   -   95.4%
 228            455     -   -   93.9%
 19               0     -   -   
 20              35     -   -   77.2%
 0                0     -   -   99.5%
 39             145     -   -   91.0%
 130              0     -   -   91.2%
 724            359     -   -   96.7%
 $48,101                        [=wAvg(R8:R24,-4))]

该功能如下所示:

Public Function wAvg(valueRange As Range, weightOffset As Integer) As Variant

    Dim weightedAverage As Double
    Dim values As Range
    Dim totalWeights As Long
    Dim weightColOffset As Long
    weightColOffset = weightOffset

    weightedAverage = 0
    Set values = valueRange

    Dim value As Range

    totalWeights = ActiveCell.Offset(0, weightColOffset).value

    For Each value In valueRange
        Dim weight As Double
        weight = value.Offset(0, weightColOffset) / totalWeights
        If (CStr(value) <> "") Then
        weightedAverage = weightedAverage + weight * value.value
        End If
    Next value

    wAvg = weightedAverage
End Function

我是回归这种权利还是不匹配的类型?我无法理解。

1 个答案:

答案 0 :(得分:0)

正如@AlexP所说 - SUMPRODUCT可能更好。

对于您的原始代码,这可能会更好 Application.Caller将始终引用您的公式单元格,因此将始终返回$ 48,101值。

Public Function wAvg(ValueRange As Range, WeightOffset As Integer) As Double

    Dim rCell As Range 'Individual cell in ValueRange.
    Dim Weight As Double
    Dim WeightedAverage As Double


    For Each rCell In ValueRange
        Weight = 0
        If rCell <> "" Then
            Weight = rCell.Offset(, WeightOffset) / Application.Caller.Offset(, WeightOffset)
            WeightedAverage = WeightedAverage + Weight * rCell
        End If
    Next rCell

    wAvg = WeightedAverage

End Function  

不需要这种东西:
Set values = valueRangevalueRange已经拥有正确的范围,所以只需使用它即可。 weightedAverage = 0。在代码开头,这将是0。