Average如果函数的结果是“#VALUE!”

这是我的数据的屏幕截图。 数据截图

Dim dBT As Object 'global dictionary Sub buttonpresscount() 'constants for column positions Const COL_BLOCK As Long = 1 Const COL_TRIAL As Long = 2 Const COL_ACT As Long = 7 Const COL_AOI As Long = 8 Const COL_RT As Long = 16 Const COL_FT As Long = 17 Dim rng As Range, lastrow As Long, sht As Worksheet Dim d, r As Long, k, resBT() Set sht = Worksheets("full test") lastrow = sht.Cells(Rows.Count, 3).End(xlUp).Row Set dBT = CreateObject("scripting.dictionary") Set rng = sht.Range("B7:T" & lastrow) d = rng.Value 'get the data into an array ReDim resBT(1 To UBound(d), 1 To 1) 'resize the array which will ' be placed in ColT 'get unique combinations of Block and Trial and pressedcounts for each For r = 1 To UBound(d, 1) k = d(r, COL_BLOCK) & "|" & d(r, COL_TRIAL) 'create key dBT(k) = dBT(k) + IIf(d(r, COL_ACT) <> "", 1, 0) Next r 'populate array with appropriate counts for each row For r = 1 To UBound(d, 1) k = d(r, 1) & "|" & d(r, 2) 'create key resBT(r, 1) = dBT(k) 'get the count Next r 'place array to sheet sht.Range("T7").Resize(UBound(resBT, 1), 1) = resBT 'clear dictionary dBT.RemoveAll 'count AOI entries For r = 1 To UBound(d, 1) k = d(r, COL_BLOCK) & "|" & d(r, COL_TRIAL) 'create key If resBT(r, 1) = 1 Then 'only proceed with trials with 1 button press dBT(k) = dBT(k) + IIf(d(r, COL_AOI) = "AOI Entry", 1, 0) 'get count Else: dBT(k) = "" End If Next r 'populate array with appropriate counts for each row For r = 1 To UBound(d, 1) k = d(r, 1) & "|" & d(r, 2) 'create key resBT(r, 1) = dBT(k) 'get the count Next r 'place array to sheet sht.Range("U7").Resize(UBound(resBT, 1), 1) = resBT Call createsummarytable Call PopSummaryAOI(dBT) dBT.RemoveAll 'retrieve and print reaction times to data summary sheet For r = 1 To UBound(d, 1) If resBT(r, 1) <> "" Then 'if buttonpresscount = 1 and AOI count exists k = d(r, COL_BLOCK) & "|" & d(r, COL_TRIAL) 'create key dBT(k) = d(r, COL_RT) End If Next r 'Populate array with last row reaction time for each trial For r = 1 To UBound(d, 1) k = d(r, 1) & "|" & d(r, 2) 'create key resBT(r, 1) = dBT(k) 'get the count Next r Call PopSummaryRT(dBT) dBT.RemoveAll 'work out avg fixation time per trial For r = 1 To UBound(d, 1) If resBT(r, 1) <> "" Then k = d(r, COL_BLOCK) & "|" & d(r, COL_TRIAL) 'create key dBT(k) = Application.AverageIf(d(r, COL_FT), (d(r, COL_AOI) = "AOI Entry")) End If Next r 'populate array For r = 1 To UBound(d, 1) k = d(r, 1) & "|" & d(r, 2) 'create key resBT(r, 1) = dBT(k) 'get the count Next r Call PopSummaryFT(dBT) End Sub 

参照上面的macros,下面的代码行是为了计算列R中每个字典(键)的平均值(读取:每个试验):

 For r = 1 To UBound(d, 1) If resBT(r, 1) <> "" Then k = d(r, COL_BLOCK) & "|" & d(r, COL_TRIAL) 'create key dBT(k) = Application.AverageIf(d(r, COL_FT), (d(r, COL_AOI) = "AOI Entry")) End If Next r 

这是#VALUE! 被打印在相关的单元格中,而不是预期的数量。

截图: 在这里输入图像说明

这是什么原因造成的? 什么是编码这个公式的正确方法?

你现在的问题与线

 dBT(k) = Application.AverageIf(d(r, COL_FT), (d(r, COL_AOI) = "AOI Entry")) 

是因为你试图取平均值的唯一值,只有当这个值是TrueFalse 。 例如,当r是1时,您的代码等同于

 dbt("Block 1|Trial, 8") = Application.AverageIf(-2484, ("" = "AOI Entry")) 

要么

 dbt("Block 1|Trial, 8") = Application.AverageIf(-2484, False) 

由于平均范围(即值-2484 )中的值-2484符合标准(即False ),函数试图将匹配值的总和(即0 )除以匹配值的计数(即0 )和错误出。

同样,当r是2时,代码等同于

 dbt("Block 1|Trial, 1") = Application.AverageIf(31, ("AOI Entry" = "AOI Entry")) 

要么

 dbt("Block 1|Trial, 1") = Application.AverageIf(31, True) 

再次, 31不等于True ,你最终试图将0除以0。


如果你使用了一个公式,你会得到一个答案(虽然不是一个有意义的答案)

 dBT(k) = Application.AverageIf(d(r, COL_AOI), "AOI Entry", d(r, COL_FT)) 

如果d(r, COL_AOI) (符合标准的testing范围)符合AOI Entry" (标准) d(r, COL_FT) (平均范围)(总结单个数字有点没有意义,但是它仍然会这样做)。但是,当d(r, COL_AOI)不是"AOI Entry"时,这仍然会给出零误差的分割,并且在它工作的情况下会给出无意义的答案。


为了得到一个有意义的平均值,你需要将一个值的总和除以一个数值。 您的代码不是以易于使用Excel的内置函数来计算总和和计数的方式设置的,因此您需要计算总和并自行计算。

在下面的代码中,我添加了两个字典(一个叫Cnts ,另一个叫Cnts )来跟踪这些数字。 然后可以通过将Cnts(k)除以Cnts(k)来容易地导出平均值。

我也冒昧把variablesk数组。 你目前的代码是至less在8个位置计算密钥,所以我改变它来计算一次,然后在每个其他位置使用相同的值。

 Dim dBT As Object 'global dictionary Sub buttonpresscount() Dim Sums As Object Dim Cnts As Object 'constants for column positions Const COL_BLOCK As Long = 1 Const COL_TRIAL As Long = 2 Const COL_ACT As Long = 7 Const COL_AOI As Long = 8 Const COL_RT As Long = 16 Const COL_FT As Long = 17 Dim rng As Range, lastrow As Long, sht As Worksheet Dim d, r As Long, resBT() Dim k() As String Set sht = Worksheets("full test") lastrow = sht.Cells(Rows.Count, 3).End(xlUp).Row Set dBT = CreateObject("scripting.dictionary") Set Sums = CreateObject("scripting.dictionary") Set Cnts = CreateObject("scripting.dictionary") Set rng = sht.Range("B7:T" & lastrow) d = rng.Value 'get the data into an array ReDim resBT(1 To UBound(d), 1 To 1) 'resize the array which will ' be placed in ColT ReDim k(1 To UBound(d, 1)) As String 'get unique combinations of Block and Trial and pressedcounts for each For r = 1 To UBound(d, 1) 'Calculate the key once, then it can be used in every other loop k(r) = d(r, COL_BLOCK) & "|" & d(r, COL_TRIAL) 'create key dBT(k(r)) = dBT(k(r)) + IIf(d(r, COL_ACT) <> "", 1, 0) Next r 'populate array with appropriate counts for each row For r = 1 To UBound(d, 1) resBT(r, 1) = dBT(k(r)) 'get the count Next r 'place array to sheet sht.Range("T7").Resize(UBound(resBT, 1), 1) = resBT 'clear dictionary dBT.RemoveAll 'count AOI entries For r = 1 To UBound(d, 1) If resBT(r, 1) = 1 Then 'only proceed with trials with 1 button press If d(r, COL_AOI) = "AOI Entry" Then dBT(k(r)) = dBT(k(r)) + 1 'get count Cnts(k(r)) = Cnts(k(r)) + 1 'get count Sums(k(r)) = Sums(k(r)) + d(r, COL_FT) 'sum column R End If Else dBT(k(r)) = "" End If Next r 'populate array with appropriate counts for each row For r = 1 To UBound(d, 1) resBT(r, 1) = dBT(k(r)) 'get the count Next r 'place array to sheet sht.Range("U7").Resize(UBound(resBT, 1), 1) = resBT createsummarytable PopSummaryAOI dBT dBT.RemoveAll 'retrieve and print reaction times to data summary sheet For r = 1 To UBound(d, 1) If resBT(r, 1) <> "" Then 'if buttonpresscount = 1 and AOI count exists dBT(k(r)) = d(r, COL_RT) End If Next r 'Populate array with last row reaction time for each trial For r = 1 To UBound(d, 1) resBT(r, 1) = dBT(k(r)) 'get the count Next r PopSummaryRT dBT dBT.RemoveAll 'work out avg fixation time per trial For r = 1 To UBound(d, 1) If resBT(r, 1) <> "" Then If Cnts(k(r)) < 1 Then 'Error if no results dBT(k(r)) = CVErr(xlErrDiv0) Else 'Determine average dBT(k(r)) = Sums(k(r)) / Cnts(k(r)) End If End If Next r 'populate array For r = 1 To UBound(d, 1) resBT(r, 1) = dBT(k(r)) 'get the count Next r PopSummaryFT dBT End Sub