【发布时间】:2017-02-22 06:38:09
【问题描述】:
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
参考上述宏,以下代码行旨在计算每个 dict(key) 列 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! 被打印在相关单元格中,而不是预期的数字。
这是什么原因造成的?编写此公式的正确方法是什么?
【问题讨论】:
-
如果该值是
True(如果r+6行中的值,则您的行dBT(k) = Application.AverageIf(d(r, COL_FT), (d(r, COL_AOI) = "AOI Entry"))正在取位于行r+6、列R 的单元格中的值的平均值,第 I 列是"AOI Entry") 或False(如果行中的值r+6,第 I 列不是"AOI Entry")。这总是会产生除以零错误(因为你没有True或False值),所以这无疑会产生你的#VALUE错误。通常对多个值执行平均 - 您要对哪些值进行平均? -
您是否只是想生成与
=AVERAGEIFS($R:$R,$I:$I,"AOI Entry",$B:$B,$B7,$C:$C,$C7)的公式(例如在单元格 T7 中)等效的 VBA? -
@YowE3K 我想要 R 列中的值的平均值,但只有那些在 I 列中具有“AOI 条目”的行中的值。你是说问题在于我如何定义纳入标准?
-
@YowE3K 我不希望单元格中的公式,我希望它被键入到字典对象,字典键应该定义哪些行包含在平均值中。
-
如果您想计算 VBA 中的平均值(不参考工作表中的范围),我认为您需要手动计算它(即,将您需要的值相加并除以如何许多值求和)或使用
Application.AverageIfs,使用与在 Excel 中使用的参数相似的参数 - 但每个范围(例如R:R)必须是一维数组 - 即你不能只使用d数组的一个“切片”,您必须将“切片”创建为一个单独的数组。