繁体   English   中英

如何将 Excel VBA function “AverageIf”与变体数组一起使用?

[英]How can you use the Excel VBA function “AverageIf” with a variant array?

我有一个具有多种值的变体数组。

例如,假设它们如下:1、2、3、0、4、5、0、0、0、0

我想取该数组的平均值,但是我想忽略零。

我的问题是“WorksheetFunction.AverageIf()”function 只能使用范围。

我发现无数帮助将范围转换为变体数组,但没有将变体数组转换为范围。

因为它已经是一个数组,所以只需循环数组并对值求和并除以数组中高于0的项目数会更快:

Sub lkjlkj()
    Dim arr As Variant
    arr = Array(1, 2, 3, 0, 4, 5, 0, 0, 0, 0)
    
    Dim sm As Double
    sm = 0#
    
    Dim cnt As Long
    cnt = 0
    
    Dim i As Long
    For i = LBound(arr) To UBound(arr)
        If arr(i) > 0 Then
            sm = sm + arr(i)
            cnt = cnt + 1
        End If
    Next i
    
    Dim avg As Double
    avg = sm / cnt
    
    Debug.Print avg
End Sub

一个简单的替代方案

通过边界计数和负过滤,您可以计算非零项并将数组总和除以该除数:

Sub TestAverage()
    Dim a: a = Array(1, 2, 3, 0, 4, 5, 0, 0, 0, 0)
    dim avg as Double: avg = Application.Sum(a) / (UBound(Filter(a, 0, False)) + 1)
    Debug.Print avg
End Sub

警告//编辑Filter得到任何部分发现,所以搜索0也会找到1020 基于对Application.Match() - c.f. @VBasic2008 的解决方案- 应用于给定数组作为第一个参数和Array(0)作为第二个参数获得防水结果。 提示: Application.Count()省略错误值,因此您避免了进一步的循环。

Function AvgWithoutZeros(arr1D As Variant) As Double
With Application
    Dim n: n = .Count(arr1D) - .Count(.Match(arr1D, Array(0), 0))  ' number of non-zero items
    AvgWithoutZeros = .Sum(arr1D) / n
End With
End Function

示例调用

Sub TestAverageOfArrayValues()
    Dim a: a = Array(1, 2, 3, 0, 4, 5, 0, 0, 0, 0)
    Debug.Print AvgWithoutZeros(a)
End Sub

只是为了演示一些基于给定范围的数组转换(例如 A 列):

Sub HowToConvertRangeTo1DimArray()
    With Sheet1                ' Code(Name) of your worksheet
        Dim lastRow As Long:  lastRow = .Range("A" & .Rows.Count).End(xlUp).row
        Dim rng     As Range: Set rng = .Range("A2:D" & lastRow) ' start e.g. in row 2
    End With
    
    Dim arr2Dim: arr2Dim = rng.Value                        ' assign data to 2-dim array
    Dim arr1Dim: arr1Dim = Application.Transpose(arr2Dim)   ' make array "flat"
    Debug.Print AvgWithoutZeros(arr1Dim)
End Sub

有例外的平均值

这个使用Application.SumApplication.Match的组合:

Option Explicit

Sub getAvgWithExceptions()
    
    Dim Data As Variant: Data = Array(1, 2, 3, 0, 4, 5, 0, 0, 0, 0)
    Dim Exceptions As Variant: Exceptions = Array(0)
    
    Debug.Print getAverage(Data, Exceptions)

End Sub

Function getAverage(Data As Variant, Exceptions As Variant) As Double
    Dim DataSum As Double: DataSum = Application.Sum(Data)
    Dim DataCount As Long: DataCount = count1D(Data, Exceptions)
    getAverage = DataSum / DataCount
End Function

Function count1D(Data As Variant, Exceptions As Variant) As Long
    Dim i As Long
    For i = LBound(Data) To UBound(Data)
        If IsError(Application.Match(Data(i), Exceptions, 0)) Then
            count1D = count1D + 1
        End If
    Next i
End Function

范围在电子表格中定义为 function 我最初尝试使用需要在电子表格中使用值。 没有人能想出使用“AverageIf”function 的方法,因为他们必须更改电子表格本身,将值强制放入可能已经填充的区域。

更好的解决方案是简单地构建一个带有 if 语句的平均 function。 我的特殊问题是只取非零的平均值。

这是该代码:

Public Function AvgIf(rng As Range)
'Declaring Variables
Dim array1() As Variant
Dim i As Integer
Dim ii As Integer
Dim Xdim As Integer
Dim Ydim As Integer
Dim temp1 As Integer
Dim temp2 As Integer

'In this example, the array is user-defined by the input range
array1 = rng.Value

'Find Array Size
Xdim = UBound(array1, 1)
Ydim = UBound(array1, 2)

'Cycling through every cell of the array
For i = 1 To (Xdim)
For ii = 1 To (Ydim)

'Insert If Statement Here (You can change it to be whatever you want)
If array1(i, ii) > 0 Then
temp1 = temp1 + array1(i, ii)
temp2 = temp2 + 1
End If

Next ii
Next i

'Cheating by doing the last calculation in the output
AvgIf = temp1 / temp2

End Function

这是您理想情况下应该使用的,而不是将数据强制放入电子表格中。

或者,如果您的问题与我的类似(数组只是范围的副本),您可以按照以下信息进行操作:

由于我的范围已转换为数组,因此我只是使用原始范围来解决问题。 (代码见下文)

Public Function TempAvg(rng as Range)

Dim i as integer
Dim t1 as Double
Dim t2 as Double

For i = 1 to 20

If rng(i) > 0 Then t1 = t1 + rng(i)
If rng(1) > 0 Then t2 = t2 + 1

Next i

TempAvg = t1 / t2

End Function

这解决了我的问题。 我向所有发布优雅解决方案的人道歉,因为我似乎无法让他们在我的项目的 scope 中工作。 我确定这是我搞砸了,而不是他们的代码。 请阅读其他答案以获得更好的解决方案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM