【问题标题】:Excel VBA function weighted average code -- how can I improve this?Excel VBA 函数加权平均代码——我该如何改进?
【发布时间】:2022-09-23 19:12:56
【问题描述】:

我需要编写一个函数,该函数采用一系列值 (X) 及其相关的不确定性 (E) 并输出加权平均值。但是,我无法让函数循环遍历数组而不产生值错误(#VALUE!)。如果只输入一个单元格作为 X 的输入,我还希望它只返回 X 的值。这是我目前所处的位置:

\' Calculates the weighted average of arrays of values, X, and their errors, E
Option Explicit
Function WAV(X As Variant, E As Variant) As Double
    \' Update values upon changing spreadsheet
    Application.Volatile
    
    \' Test if we have an array or not
    If IsArray(X) And IsArray(E) Then
        Dim W As Double
        Dim WX As Double
        
        W = 0
        WX = 0
        WAV = 20
        
        For myrow = LBound(X,1) To UBound(X,1)
            For mycol = LBound(X, 2) To UBound(X, 2)
            \'Test if X and E are both numbers and E > 0
                If (Application.WorksheetFunction.IsNumber(X(myrow, mycol)) = True) And (Application.WorksheetFunction.IsNumber(E(myrow, mycol)) = True) Then
                    If E(myrow, mycol) > 0 Then
                        W = W + 1 / (E(myrow, mycol) ^ 2)
                        WX = WX + X(myrow, mycol) / (E(myrow, mycol) ^ 2)
                    End If
                End If
            Next mycol
        Next
        
        If W > 0 Then
            WAV = WX / W
        End If
    Else
        WAV = X
    End If
End Function

我已经为此挣扎了几个小时,但无济于事。我也是 VBA 的初学者,所以我怀疑我在某个地方犯了一个愚蠢的错误。任何帮助,将不胜感激。

  • 通常可以使用SUMPRODUCT 创建加权平均值。您使用 VBA 的任何原因?
  • 你怎么称呼它?
  • @BigBen - 部分出于兴趣,但也使公式更容易
  • @ScottCraner - 我在 Excel 工作表中的一个单元格中调用它,其中两个参数可以是单个单元格或单元格范围(但应该具有相同的大小!)
  • 那么为什么不直接使用WorksheetFunction.Sumproduct() 而不是循环呢?

标签: excel vba function


【解决方案1】:

感谢 BigBen 和 ScottCraner 帮助回答这个问题。这是一个结合了他们两个建议的工作解决方案:

Option Explicit
Function WAV(X As Variant, E As Variant) As Double
    ' Update values upon changing spreadsheet
    Application.Volatile
    
    ' Test if we have an array or not
    If IsArray(X) And IsArray(E) Then
        ' Change all the ranges into arrays
        Dim XArr() As Variant
        Dim EArr() As Variant
        Dim WArr() As Variant
        
        ' Assign the array values
        XArr = X.Value
        EArr = E.Value
        
        ' Resize the weighting array
        ReDim WArr(LBound(EArr, 1) To UBound(EArr, 1), LBound(EArr, 2) To UBound(EArr, 2))
        
        ' Calculate square inverses of errors
        For myrow = LBound(EArr, 1) To UBound(EArr, 1)
            For mycol = LBound(EArr, 2) To UBound(EArr, 2)
                WArr(myrow, mycol) = 1 / (EArr(myrow, mycol) ^ 2)
            Next mycol
        Next myrow
        
        ' Now calculate the weighted average using sumproduct function
        Dim W As Double
        Dim WX As Double
        
        WX = WorksheetFunction.SumProduct(XArr, WArr)
        W = WorksheetFunction.SumProduct(WArr)
        
        ' Return weighted average
        WAV = WX / W
        
    Else
        ' Return the weighted average
        WAV = X
    End If
End Function

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-08
    相关资源
    最近更新 更多