Entschuldigung für die späte Antwort.
Ich habe eine UDF erstellt, die sich darauf konzentriert, die Berechnung mehrmals durchzuführen, ohne den gesamten Bereich mehrmals zu durchlaufen.
Public Function getCounts(AreaStr As Variant, AreaRng As Range, CustomerRng As Range, ProductRng As Range, SalesRng As Range, Optional ProductName As String = "Product 1", Optional lessThan As Double = 5) As Variant
'make sure AreaStr is an array
If TypeOf AreaStr Is Range Then AreaStr = AreaStr.Value2
If Not IsArray(AreaStr) Then
AreaStr = Array(AreaStr)
ReDim Preserve AreaStr(1 To 1)
End If
'shorten the range (this way you can use whole columns)
If SalesRng(SalesRng.Cells.Count).Formula = "" Then Set SalesRng = SalesRng.Parent.Range(SalesRng.Cells(1), SalesRng(SalesRng.Cells.Count).End(xlUp))
'make sure all ranges have the same size
Set AreaRng = AreaRng.Resize(SalesRng.Rows.Count)
Set CustomerRng = CustomerRng.Resize(SalesRng.Rows.Count)
Set ProductRng = ProductRng.Resize(SalesRng.Rows.Count)
'Load values in variables to increase speed
Dim SalesValues As Variant, UserValues As Variant, ProductValues As Variant
SalesValues = AreaRng
UserValues = CustomerRng
ProductValues = ProductRng
'create temporary arrays to hold the values
Dim buffer() As Variant, expList() As Variant
ReDim buffer(1 To UBound(UserValues))
ReDim expList(1 To UBound(AreaStr), 1 To 1)
Dim i As Long, j As Double, k As Long
For i = 1 To UBound(AreaStr)
expList(i, 1) = buffer
Next
buffer = Array(buffer, buffer)
buffer(0)(1) = 0
For i = 1 To UBound(UserValues)
If ProductValues(i, 1) = ProductName Then 'this customer purchased our product
j = Application.IfError(Application.Match(UserValues(i, 1), buffer(0), 0), 0)
If j = 0 Then 'first time this customer in this calculation
j = i
buffer(0)(j) = UserValues(i, 1) 'remember the customer name (to not calculate him again later)
If Application.SumIfs(SalesRng, CustomerRng, UserValues(i, 1), ProductRng, ProductName) < lessThan Then
buffer(1)(j) = 1 'customer got less than "lessThan" -> remember that
End If
End If
If buffer(1)(j) = 1 Then 'check if we need to count the customer
k = Application.IfError(Application.Match(SalesValues(i, 1), AreaStr, 0), 0) 'check if the area is one of the areas we are looking for
If k Then expList(k, 1)(j) = 1 'it is -> set 1 for this customer/area combo
End If
End If
Next
For i = 1 To UBound(AreaStr) 'sum each area
expList(i, 1) = Application.Sum(expList(i, 1))
Next
getCounts = expList 'output array
End Function
Ich nehme an, dass Sie es als eine UDF ohne meine Hilfe aufnehmen können.
Im Blatt, das Sie (für Beispiel) E11 verwenden würden:
E16
=getCounts(D11:D15,G2:G7,E2:E7,I2:I7,J2:J7)
wählen Sie einfach den Bereich von E11: E16 und geben Sie die Formel, es dann mit CSE bestätigen.
können Sie auch nur =getCounts(D11,$G$2:$G$7,$E$2:$E$7,$I$2:$I$7,$J$2:$J$7)
bei E11 verwenden und dann nach unten kopieren ... aber das wäre ziemlich langsam.
Der Trick ist, dass wir die Summe des Sets für jeden Kunden berechnen, der es mindestens einmal gekauft hat. Dann speichern wir 1, wenn es weniger als Ihre Kriterien ist. Dies gilt für das allgemeine Array. Jeder Bereich, den Sie suchen, wird auch ein eigenes Array bekommen. Hier lagern wir auch die 1 auf der gleichen Position. Da jeder Kunde nur einmal berechnet wird, spielt es keine Rolle, ob er ihn mehrere Male hat.
getCounts(AreaStr,AreaRng,CustomerRng,ProductRng,SalesRng,[ProductName],[lessThan])
Die meisten Teile selbst sein sollte, zu erklären, aber wenn Sie noch Fragen haben, fragen Sie einfach;)
vba wird Ihre beste Wette. Meine Vermutung, ohne zu sehr darauf einzugehen, werden Sie nicht in der Lage sein, Array-Formeln zu umgehen. –
Vielen Dank für Ihren Hinweis, zur gleichen Zeit macht mir nichts dagegen, VBA zu verwenden, aber ich weiß nicht, um solche Formel in VBA-Code zu konvertieren :) .... Ich werde alles tun, um all diese vergeudeten Stunden zu vermeiden, auf Excel zu warten Berechnen Sie solche Formeln :) –
Stack Overflow ist keine "Code für mich", "Teach me to code" oder "Finde mich Code" -Site. –