[英]Count unique values based on criteria given in another column
我有一个列表,列出了正在制造的批次和零件号。
我需要在一台机器上运行的批次的唯一计数。 此长列表每天更新。 我在这里附上一个例子。
我有这个粗糙的代码。
last_row = ws.Cells(Rows.Count,1).End(xlUp).Row
For Each M_cCell in M_cRange
Counter = 0
For i = 2 to last_row
If Cells(1, 1).Value = M_cCell Then
Counter = Counter + (1/(WorksheetFunction.CountIF _
(Range(Cells(2,2),Cells(Last_row,2),M_ccell.Value)))
End If
Next i
Next M_cCell
这会以十进制数字给出不希望的结果。
假设: A:C列中的数据b。 数据表中唯一使用的范围是A:C c列。 结果将在范围(“ E1”)中打印
考虑到需要大量数据,使用字典可能是删除重复项的最有效方法之一。 让我知道是否有帮助。
Sub test()
Dim dictMachine As Object: Set dictMachine = CreateObject("scripting.dictionary")
Dim dictBatch As Object
Dim vTemp As Variant: vTemp = ActiveSheet.UsedRange
Dim vTemp2 As Variant
Dim i As Long
For i = LBound(vTemp, 1) + 1 To UBound(vTemp, 1)
Set dictBatch = CreateObject("scripting.dictionary")
If dictMachine.exists(vTemp(i, 1)) Then
dictMachine(vTemp(i, 1))(vTemp(i, 2)) = dictMachine(vTemp(i, 1))(vTemp(i, 2)) + 1
Else
dictBatch(vTemp(i, 2)) = dictBatch(vTemp(i, 2)) + 1
Set dictMachine(vTemp(i, 1)) = dictBatch
End If
Next i
vTemp = dictMachine.Keys
ReDim vTemp2(0 To UBound(vTemp, 1) + 1, 0 To 1)
vTemp2(0, 0) = "Machine"
vTemp2(0, 1) = "Number of Batches"
For i = LBound(vTemp, 1) To UBound(vTemp, 1)
vTemp2(i + 1, 0) = vTemp(i)
vTemp2(i + 1, 1) = dictMachine(vTemp(i)).Count
Next i
ActiveSheet.Range("E1").Resize(UBound(vTemp2, 1) - LBound(vTemp2, 1) + 1, UBound(vTemp2, 2) - LBound(vTemp2, 2) + 1) = vTemp2
End Sub
也不是最干净的方法,但是您可以完全避免循环,而在使用AdvancedFilter
之后仅使用COUNTIF
-在处理大量数据时,与循环相比,这是非常有效的。
Public Sub Test()
Dim TargetSheet As Worksheet
Set TargetSheet = Worksheets("Sheet2")
With ActiveSheet
.Range("A1:B20").AdvancedFilter xlFilterCopy, CopyToRange:=TargetSheet.Range("A1"), Unique:=True 'Get unique combinations
End With
With TargetSheet
.Range("A1:A" & .Range("A1").End(xlDown).Row).AdvancedFilter xlFilterCopy, CopyToRange:=.Range("C1"), Unique:=True 'Get unique machines
.Range("D2").Value = "=countif(A:A, C2)" 'Count batches per machine
.Range("D2").AutoFill .Range("D2:D" & .Range("C2").End(xlDown).Row)
.Range("D1").Value = "Count of batches:" 'Add count header
.Range("D:D").value = .Range("D:D").value 'replace formula's by values.
.Range("A:B").Delete shift:=xlToLeft 'Get rid of helper columns from first advanced filter.
End With
Set TargetSheet = Nothing
End Sub
另一个解决方案:
Sub Demo()
Dim rng As Range
For Each rng In Range("A2:A" & Cells(Rows.Count, "A").End(xlUp).Row)
Cells(rng.Row(), "E").Value = Evaluate(Replace("IFERROR(INDEX($A$2:$A$15,MATCH(0,INDEX(COUNTIF($E$1:E#,$A$2:$A$15),0,0),0)),"""")", "#", rng.Row()))
If Cells(rng.Row(), "E").Value = "" Then Exit For
Cells(rng.Row, "F").FormulaArray = Evaluate(Replace("SUM(IF($A$2:$A$15=E#, 1/(COUNTIFS($A$2:$A$15, E#, $B$2:$B$15, $B$2:$B$15)), 0))", "#", rng.Row()))
Next rng
End Sub
这将结果显示在Column EF
,请参阅图像以供参考。
我会通过更简单的方法来解决这个问题。 没有任何代码示例。 只需考虑一下:
遍历所有数据并根据两列查找唯一性-在这种情况下,您将仅获得2个结果。 每个新结果将保存到临时数组。
再次循环遍历所有数据,并将每一行与存储的临时数组的每个字段进行比较。 为此添加计数器,仅此而已。
代码的效率在很大程度上取决于代码“命中”工作表的次数-对于您来说,在处理数据之前将数据读入数组会更快。 当涉及唯一计数时,应该想到字典。 假设您的数据在A到C列中,并在E列中输出...
Public Sub sub_UniqueCount()
Dim wsThis As Worksheet: Set wsThis = ActiveSheet
Dim vData As Variant
Dim vOutput() As Variant
Dim vKey
Dim dicCount As Object: Set dicCount = CreateObject("scripting.dictionary")
Dim dicTemp As Object
Dim i As Long, j As Long
Application.ScreenUpdating = False
With wsThis
' load data into memory
vData = .Range(.Range("A1").End(xlToRight), .Range("A1").End(xlDown))
For i = LBound(vData, 1) + 1 To UBound(vData, 1)
If dicCount.Exists(vData(i, 1)) Then
dicCount(vData(i, 1))(vData(i, 2)) = dicCount(vData(i, 1))(vData(i, 2)) + 1
Else
Set dicTemp = CreateObject("scripting.dictionary")
dicTemp(vData(i, 2)) = 1
Set dicCount(vData(i, 1)) = dicTemp
End If
Next i
ReDim vOutput(1 To dicCount.Count, 1 To 2)
i = 1
For Each vKey In dicCount.keys
vOutput(i, 1) = vKey
vOutput(i, 2) = dicCount(vKey).Count
i = i + 1
Next vKey
.Range("E1").Resize(UBound(vOutput, 1) - LBound(vOutput, 1) + 1, UBound(vOutput, 2) - LBound(vOutput, 2) + 1) = vOutput
End With
Application.ScreenUpdating = True
End Sub
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.