在Excel中计算移动平均线

时间:2011-03-12 15:36:24

标签: excel vba worksheet-function array-formulas

我想计算一个列的最后一个,比如20个数的移动平均值。问题是列的某些单元格可能是空的,应该忽略它们。例如:

 A
175
154

188
145
155

167
201

最后三个的移动平均值为(155 + 167 + 201)/ 3。我试图用平均值,偏移量,索引实现这个,但我根本不知道如何。我对宏有点熟悉,所以这样的解决方案可以正常工作:=MovingAverage(A1;3)

感谢您提供任何提示或解决方案!

4 个答案:

答案 0 :(得分:7)

{=SUM(($A$1:A9)*(ROW($A$1:A9)>LARGE((ROW($A$1:A9))*(NOT(ISBLANK($A$1:A9))),3+1)))/3}

使用control + shift + enter输入,使其成为数组公式。这将找到最新的三个值。如果您想要更多或更少,请将公式中的两个“3”实例更改为您想要的任何内容。

LARGE((ROW($A$1:A9))*(NOT(ISBLANK($A$1:A9))),3+1)

此部分返回具有值的所有单元格的第4个最高行数,或者示例中为5,因为行6,8和9是具有值的第1到第3个最高行。

(ROW($A$1:A9)>LARGE((ROW($A$1:A9))*(NOT(ISBLANK($A$1:A9))),3+1))

此部分根据行号是否大于第4个,返回9个TRUE或FALSE。

($A$1:A9)*(ROW($A$1:A9)>LARGE((ROW($A$1:A9))*(NOT(ISBLANK($A$1:A9))),3+1))

这将A1:A9中的值乘以9 TRUE或FALSE。 TRUEs转换为1,FALSEs转换为零。这留下了像这样的SUM函数

=SUM({0;0;0;0;0;155;0;167;201})/3

因为155以上的所有值都不满足行号标准,所以get乘以零。

答案 1 :(得分:3)

如果要使用UDF,只有在参数包含您要处理的所有数据范围时,才会在更改数据时正确重新计算。

以下是移动平均UDF,它处理整个列并包含一些错误处理。
您可以通过在单元格中输入公式=MovingAverage(A:A,3)来调用它。

Function MovingAverage(theRange As Range, LastN As Long) As Variant
    Dim vArr As Variant

    Dim j As Long
    Dim nFound As Long
    Dim dSum As Double

    On Error GoTo Fail
    MovingAverage = CVErr(xlErrNA)
    '
    ' handle entire column reference
    '
    vArr = Intersect(Application.Caller.Parent.UsedRange, theRange).Value2

    If IsArray(vArr) And LastN > 0 Then
        For j = UBound(vArr) To 1 Step -1
            ' skip empty/uncalculated
            If Not IsEmpty(vArr(j, 1)) Then
                ' look for valid numbers
                If IsNumeric(vArr(j, 1)) Then
                    If Len(Trim(CStr(vArr(j, 1)))) > 0 Then
                        nFound = nFound + 1
                        If nFound <= LastN Then
                            dSum = dSum + CDbl(vArr(j, 1))
                        Else
                            Exit For
                        End If
                    End If
                End If
            End If
        Next j

        If nFound >= LastN Then MovingAverage = dSum / LastN

    End If
    Exit Function
Fail:
    MovingAverage = CVErr(xlErrNA)
End Function

答案 2 :(得分:1)

快速解决方案: 假设您的号码在A2:A10的单元格上,请在B10中输入以下公式:

=IF(COUNT(A8:A10)=3,AVERAGE(A8:A10),IF(COUNT(A7:A10)=3,AVERAGE(A7:A10),"too many blanks"))

向上拖动公式,得到移动平均值

如果有两个连续空白的可能性你可以嵌套另一个,如果超过这个并且这个解决方案变得太复杂了

答案 3 :(得分:1)

我在VBA写了一个简短的脚本。希望它能做你想要的。你在这里:

Function MovingAverage(ByVal r As String, ByVal i As Integer) As Double
Dim rng As Range, counter As Long, j As Integer, tmp As Double
    Set rng = Range(r)
    counter = 360
    j = 0
    tmp = 0
    While j < i + 1 And counter > 0
        If Len(rng.Offset(j, 0)) > 0 Then
            tmp = tmp + rng.Offset(j, 0).Value
        End If
        j = j + 1
        counter = counter - 1
    Wend
    MovingAverage = CDbl(tmp / i)
End Function

1)我已将限制设置为360个单元格。这意味着该脚本不会查找超过360个单元格。如果您想更改它,请更改计数器的初始值。

2)脚本返回的不是舍入平均值。将最后一行更改为       MovingAverage = Round(CDbl(tmp / i),2)

3)使用就像您想要的那样,只需在单元格中键入 = MovingAverage(“a1”; 3)

欢迎任何评论。