Please, try the next code. It uses a dictionary to solve the unique part, the count and sum, then process its data and populate an array. Its content is dropped at once in the range. The code assumes that the range to be processed is in columns A:C and the processing result is placed in a range starting from "G2":
Sub testExtractDataAtOnce()
'the code needs a reference to 'Microsoft Scripting Runtime'
Dim sh As Worksheet, lastRow As Long, arr, arrIt, arrFin
Dim i As Long, dict As New Scripting.Dictionary
Set sh = ActiveSheet 'use here your necessary sheet
lastRow = sh.Range("B" & sh.Rows.count).End(xlUp).row
arr = sh.Range("B2:C" & lastRow).Value 'put the range to be processed in an array
For i = 1 To UBound(arr) 'process the array and fill the dictionary
If Not dict.Exists(arr(i, 1)) Then
dict.Add arr(i, 1), 1 & "|" & arr(i, 2) 'create the unique key and corresponding count | value
Else
arrIt = Split(dict(arr(i, 1)), "|") 'extract the count and previous value and use it in the next line
'add the count and the new value to the existing key data:
dict(arr(i, 1)) = CLng(arrIt(0)) + 1 & "|" & CDbl(arrIt(1)) + arr(i, 2)
End If
Next i
ReDim arrFin(1 To dict.count, 1 To 4) 'redim the final array to accept all the necessary fields
Dim avg As Double, std As Double
For i = 0 To dict.count - 1 'iterate between the dictionary data
arrIt = Split(dict.Items(i), "|") 'extract the count and the value (sum)
arrFin(i + 1, 1) = dict.Keys(i): arrFin(i + 1, 2) = arrIt(0) 'write the key and count
avg = arrIt(1) / arrIt(0) 'calculate the average (neccessary for the next steps, too)
arrFin(i + 1, 3) = avg 'put the average in the array
'call the adapted function (able to extract the stdDev from the array):
arrFin(i + 1, 4) = findstd(CStr(dict.Keys(i)), avg, CDbl(arrIt(0)), arr)
Next i
'Drop the processed result in the sheet, at once. You can use any range instead of "G2" and any sheet
sh.Range("G2").Resize(UBound(arrFin), 4).Value = arrFin
End Sub
Public Function findstd(tofind As String, avg As Double, rcount As Long, arr)
Dim std As Double, i As Long
For i = 1 To UBound(arr)
If arr(i, 1) = tofind Then
std = std + (arr(i, 2) - avg) ^ 2
End If
Next i
findstd = Sqr(std / (rcount - 1))
End Function
Please test it, send some feedback.
If you do not know how to add a reference, please run the next code before running the above one. It will automatically add the necessary reference:
Sub addScrRunTimeRef()
'Add a reference to 'Microsoft Scripting Runtime':
'In case of error ('Programmatic access to Visual Basic Project not trusted'):
'Options->Trust Center->Trust Center Settings->Macro Settings->Developer Macro Settings->
' check "Trust access to the VBA project object model"
Application.VBE.ActiveVBProject.References.AddFromFile "C:WindowsSysWOW64scrrun.dll"
End Sub
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…