我想计算一列最后一个数字的移动平均值,比如 20 个。一个问题是该列的某些单元格可能是空的,它们应该被忽略。例子:
A
175
154
188
145
155
167
201
最后三个的移动平均线为 (155+167+201)/3。我尝试使用平均值、偏移量、索引来实现这一点,但我根本不知道如何。我对宏有点熟悉,所以这样的解决方案可以正常工作:=MovingAverage(A1;3)
感谢您提供任何提示或解决方案!
我想计算一列最后一个数字的移动平均值,比如 20 个。一个问题是该列的某些单元格可能是空的,它们应该被忽略。例子:
A
175
154
188
145
155
167
201
最后三个的移动平均线为 (155+167+201)/3。我尝试使用平均值、偏移量、索引来实现这一点,但我根本不知道如何。我对宏有点熟悉,所以这样的解决方案可以正常工作:=MovingAverage(A1;3)
感谢您提供任何提示或解决方案!
{=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。TRUE 转换为 1,FALSE 转换为零。这留下了这样的 SUM 函数
=SUM({0;0;0;0;0;155;0;167;201})/3
因为 155 以上的所有值都不满足行号标准,所以 get 乘以零。
如果您要使用 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
只是一个快速的解决方案:假设您的数字在单元格 A2:A10 上,请在 B10 中输入以下公式:
=IF(COUNT(A8:A10)=3,AVERAGE(A8:A10),IF(COUNT(A7:A10)=3,AVERAGE(A7:A10),"too many blanks"))
拖动公式你得到移动平均线
如果有可能存在两个连续的空白,则可以嵌套另一个,如果不止于此,并且此解决方案变得过于复杂
我用 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 个单元格。如果要更改它,请更改counter的初始值。
2) 脚本返回非四舍五入的平均值。将最后一行更改为 MovingAverage = Round(CDbl(tmp / i),2)
3) 使用如您所愿,只需在单元格中输入=MovingAverage("a1";3) 即可。
欢迎任何意见。