在Excel中计算移动平均线

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

A 175 154 188 145 155 167 201 

后三位的移动平均数将是(155 + 167 + 201)/ 3。 我试图使用平均值,偏移量,索引来实现这一点,但我根本不知道如何。 我有点熟悉macros,所以这样的解决scheme将正常工作: =MovingAverage(A1;3)

感谢您的任何提示或解决scheme!

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

input这个控制+ shift +input使其成为一个数组公式。 这会find最新的三个值。 如果你想要或多或less,将公式中的两个“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)) 

该部分根据行号是否大于第四个最大值返回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。 TRUE转换为1,FALSE转换为零。 这样就留下了一个SUM函数

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

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

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

这里是移动平均UDF,处理整个列,并包含一些error handling。
您可以通过将公式=MovingAverage(A:A,3)input到单元格中来调用它。

 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 

只是一个快速的解决scheme:假设你的号码在单元格A2:A10中,在B10中input以下公式:

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

拖动公式可以得到移动平均线

如果有两个连续空白的可能性,你可以嵌套另一个,如果不止于此,这个解决scheme变得太复杂了

我已经在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)到单元格中。

任何意见,欢迎。