2017-02-22 1 views
1

Dies ist ein Screenshot meiner Daten. data screenshotAverageIf Funktion ergibt "#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 

die obigen Makro Bezug, werden die folgenden Codezeilen gemeint pro dict einen Durchschnitt der Werte in Spalte R arbeiten (key) (sprich: pro Versuch):

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 

Dies führt dazu, dass #VALUE! in den relevanten Zellen statt der erwarteten Zahl gedruckt wird.

Screenshot: enter image description here

Was ist der Grund dafür? Was ist der richtige Weg, um diese Formel zu kodieren?

+0

Ihre Linie 'dBT (k) = Application.AverageIf (d (r, COL_FT), (d (r, COL_AOI) = "AOI Entry"))' in der Zelle den Mittelwert des Wertes nimmt in Zeile 'r + 6', Spalte R, wenn dieser Wert 'True' ist (wenn der Wert in Zeile' r + 6', Spalte I, ist "AOI Entry" ') oder' False' (wenn der Wert in Reihe 'r + 6', Spalte I, ist nicht" AOI Entry "'). Das wird immer einen Division-by-Zero-Fehler erzeugen (da Sie keine 'True'- oder' False'-Werte haben), so dass dies zweifellos Ihren '# VALUE'-Fehler erzeugt. In der Regel wird ein Durchschnittswert über mehrere Werte hinweg berechnet - welche Werte versuchen Sie zu mitteln? – YowE3K

+0

Versuchen Sie einfach, ein VBA-Äquivalent einer Formel (in der Zelle T7 zum Beispiel) von '= AVERAGEIFS ($ R: $ R, $ I: $ I," AOI Entry ", $ B: $ B, $ B7) zu generieren , $ C: $ C, $ C7) '? – YowE3K

+0

@ YowE3K Ich möchte den Durchschnitt der Werte in Spalte R, aber nur diejenigen, die in Zeilen sind, die "AOI-Eintrag" in Spalte I haben. Sagen Sie, das Problem ist mit, wie ich das Einschlusskriterium definiert habe? – shecodes

Antwort

1

Ihre aktuelle Ausgabe mit der Linie

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

ist aufgrund der Tatsache, dass man den Durchschnitt eines einzigen Wertes zu nehmen versuchen, und nur dann, wenn dieser Wert True oder False. Z.B. wenn r 1 ist, entspricht Ihr Code

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

oder

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

Da keiner der Werte im mittleren Bereich (dh der Wert -2484) entspricht die Kriterien (dh False), die Funktionsversuche die Summe der übereinstimmenden Werte (dh 0) durch die Anzahl der übereinstimmenden Werte (dh 0) und Fehler austeilen.

Ähnlich, wenn r 2 ist, entspricht der Code

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

oder

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

Wieder 31 nicht gleich True, und Sie am Ende versucht, teilen 0 von 0


Sie hätten eine Antwort (alt hough keine sinnvolle Antwort), wenn Sie eine Formel von

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

verwendet hatten, die d(r, COL_FT) summiert hätte (die durchschnittliche Reichweite), wenn d(r, COL_AOI) (der Bereich gegen die Kriterien testen) angepasst AOI Entry" (die Kriterien). (Eine einzelne Zahl zu summieren ist ein bisschen sinnlos, aber hätte es immer noch getan.) Allerdings hätte dies immer noch eine Division durch Nullfehler ergeben, wenn d(r, COL_AOI) nicht "AOI Entry" wäre, und würde in den Fällen, in denen es funktioniert, eine sinnlose Antwort geben .


Um einen aussagekräftigen Durchschnitt zu erhalten, müssen Sie durch eine Anzahl von Werten eine Summe von Werten teilen. Ihr Code ist nicht so eingerichtet, dass Sie die integrierten Funktionen von Excel zum Berechnen der Summe und der Anzahl verwenden können. Daher müssen Sie die Summe berechnen und selbst zählen.

Im folgenden Code habe ich zwei Wörterbücher hinzugefügt (eines mit der Bezeichnung Sums, das andere Cnts), um diese Nummern zu verfolgen. Der Durchschnitt kann dann leicht durch Teilen von Sums(k) durch Cnts(k) abgeleitet werden.

Ich habe mir auch die Freiheit genommen, Ihre Variable k zu einem Array zu ändern. Ihr aktueller Code berechnete den Schlüssel in mindestens 8 Positionen, also änderte ich ihn, um ihn einmal zu berechnen und dann den gleichen Wert in jeder anderen Position zu verwenden.

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 
+0

Große Antwort und der Code funktioniert. Außer ich möchte, dass es immer noch 0 druckt, wenn es keine AOI-Einträge gibt, also habe ich 'Wenn d (r, COL_AOI) =" AOI-Eintrag "Dann dBT (k (r)) = dBT (k (r)) + 1 'Anzahl erhalten Cnts (k (r)) = Cnts (k (r)) + 1' Anzahl erhalten Summe (k (r)) = Summe (k (r)) + d (r, COL_FT) 'Summe Spalte R' zu 'Wenn d (r, COL_AOI) = "AOI Eintrag" Dann dBT (k (r)) = dBT (k (r)) + 1' zählen bekommen Else dBT (k (r)) = dBT (k (r)) + 0 'Anzahl erhalten' und jetzt viele Durchschnittswerte sind negative Zahlen. Nicht sicher warum. – shecodes

+0

nvm Ich denke, ich habe es behoben. Ich gebe eine andere Aussage für den Durchschnitt ein. '' Else 'Cnts (k (r)) = Cnts (k (r)) + 0' Zählung 'Summe (k (r)) = Summe (k (r))) + d (r, COL_FT) 'Summen Spalte R' , dass ich denke, war die Ursache. Es funktioniert ohne es gut. – shecodes

Verwandte Themen