Private Sub Worksheet_Change(ByVal Target As Range)
Dim t, d1 As Object, d2 As Object, d3 As Object, tablo, resu(), i&, x$, y$, z$, n&, nn&
t = Timer
Set d1 = CreateObject("Scripting.Dictionary")
d1.CompareMode = vbTextCompare 'la casse est ignorée
Set d2 = CreateObject("Scripting.Dictionary")
d2.CompareMode = vbTextCompare 'la casse est ignorée
Set d3 = CreateObject("Scripting.Dictionary")
d3.CompareMode = vbTextCompare 'la casse est ignorée
tablo = [A1].CurrentRegion.Resize(, 3) 'matrice, plus rapide
ReDim resu(1 To UBound(tablo), 1 To 3)
For i = 2 To UBound(tablo)
x = tablo(i, 2): y = LCase(tablo(i, 3))
If y Like "*z*" Then d1(x) = d1(x) + 1 Else d2(x) = d2(x) + 1
Next i
For i = 2 To UBound(tablo)
x = tablo(i, 2)
If d1(x) > 1 And d2(x) = 0 Then
y = tablo(i, 3): z = x & y
If Not d3.exists(z) Then
n = n + 1
d3(z) = n 'mémorise la ligne
resu(n, 1) = x
resu(n, 2) = y
End If
nn = d3(z)
resu(nn, 3) = resu(nn, 3) + 1 'comptage
End If
Next i
'---restitution---
Application.EnableEvents = False 'désactive les évènements
With [E3] '1ère cellule de destination
If n Then .Resize(n, 3) = resu
.Offset(n).Resize(Rows.Count - n - .Row + 1, 3).ClearContents 'RAZ en dessous
End With
Application.EnableEvents = True 'réactive les évènements
With UsedRange: End With 'actualise la barre de défilement verticale
MsgBox n & " articles trouvés en " & Format(Timer - t, "0.00 \sec")
End Sub