
答案1
好吧,我接受了 VBA 挑戰。我對你想要的東西有點困惑例外存在,因此目前如果出現異常,它將完全跳過該組。如果這不是您想要的行為,請告訴我。你可能是對的,一個公式的存在可能會讓這個看起來愚蠢地過度設計。希望它可以幫助別人!
Sub CalculateList()
Dim startRowCount As Integer: startRowCount = 2 'Row to start on
Dim columnId As Integer: columnId = 1 'Column containing ID
Dim OutputColumn As Integer: OutputColumn = 7 'Column to output into
'------ Begin
Cells(1, OutputColumn).Select 'Selects the output cell, incase there are any successes
Dim rowCount: rowCount = startRowCount 'Sets our start row count for the loop
Dim RowsContainingId() 'Array containing the row ID's matching the current ID of the loop
ReDim RowsContainingId(1)
Dim CompletedIds() 'Array containing the ID's that have already been done
ReDim CompletedIds(1)
Do 'Begin loop
nextNumberStart: 'Label to go back to if we hit an already completed ID
Dim CurrentID As String: CurrentID = Cells(rowCount, columnId).Value 'Get the CurrentID of this loop
If (CurrentID = "") Then 'If we hit a blank, we're done, so...
Exit Do 'Exit the loop
End If
If (IsInArray(CurrentID, CompletedIds)) Then 'Check if this ID has already been handled
rowCount = rowCount + 1 'It has, so select the next row
GoTo nextNumberStart: '...And begin the loop again
End If
GetAllMatchingRowIds CurrentID, RowsContainingId, startRowCount, columnId 'Runs sub lower down to populate the array with all the rows with this ID
If (TestIdMeetsCriteria(RowsContainingId)) Then 'Test these rows to see if it meets your criteria (function below)
ActiveCell.Value = CurrentID 'It's a success, so write this ID in our active cell
ActiveCell.Offset(1, 0).Activate 'And select the cell one row down, ready to write again if needed
End If
CompletedIds(UBound(CompletedIds) - 1) = CurrentID 'Add this ID to our completed list
ReDim Preserve CompletedIds(UBound(CompletedIds) + 1) 'Grow our array one more ready for next completed item
Erase RowsContainingId 'Wipe out our Matching ID array for next loop
ReDim RowsContainingId(1)
rowCount = rowCount + 1
Loop
End Sub
Function IsInArray(stringToBeFound As String, arr As Variant) As Boolean
IsInArray = (UBound(Filter(arr, stringToBeFound)) > -1) 'Checks if a string is in the array
End Function
Function TestIdMeetsCriteria(arr As Variant) As Boolean
Dim row
Dim HasException, ValidPlus: HasException = False: ValidPlus = False 'Set our bools to False
For Each row In arr 'Loop through each row containing our ID
If (LCase(Cells(row, 2).Value) = "plus") Then 'Check for "Plus" (case insensitively)
If (LCase(Cells(row, 3).Value) = LCase(Cells(row, 4).Value)) Then 'We got Plus, do we have matching Service and Sales (case insensitive)?
ValidPlus = True 'We do. Set ValidPlus to true for comparison later
End If
ElseIf (LCase(Cells(row, 2).Value) = "exception") Then 'Now check if any rows contains Exception (case insensitive)
HasException = True 'We do. Set HasException to true for later comparison
End If
Next
TestIdMeetsCriteria = Not (HasException) And ValidPlus 'We finished the loop. If HasException is still false, and ValidPlus is now true, it was a success, otherwise a failure
End Function
Sub GetAllMatchingRowIds(idToFind As String, arr As Variant, startRowId As Integer, columnId As Integer)
Dim rowCount: rowCount = startRowId
Do 'Loop through our ID column rows
If (Cells(rowCount, columnId).Value = idToFind) Then 'Check if the ID is the one we're after
arr(UBound(arr) - 1) = rowCount 'It is, add it to our array
ReDim Preserve arr(UBound(arr) + 1) 'Grow our array for next lop
End If
rowCount = rowCount + 1 'Next row
Loop Until IsEmpty(Cells(rowCount, columnId).Value) 'Keep looping until we hit a blank
ReDim Preserve arr(UBound(arr) - 2) 'Remove additional entries in array we don't need
End Sub
結果:
答案2
如果我沒理解錯的話,您需要上面的列表,除非您希望排除 ID 代碼(如果 ID 的服務代碼不包含加號)。此外,如果銷售和服務不匹配,則不會包含它們 - 除非exception
服務代碼中有。
您是否考慮過輔助列?
最簡單的方法是將 A+B 列連接到 E 列中,這將為您提供一行 ID 號碼和服務代碼。
然後,您可以在 E 行中使用 countif 語句來檢查 whereID
和PLUS
= true
。
然後您需要檢查名稱和異常。
然後,您可以使用巢狀 IF 語句來檢查符合、異常和加號。
在E中顯然是=CONCATENATE(a2,b2)
F 看起來像這樣=if(countif(E:E,CONCATENATE(a2,"PLUS"))>0,"PLUS","")
G 你需要用來檢查名稱 - 所以你需要使用=Concatenate(a2,if(c2=d2,"Match","ERROR")
您需要使用 H 來檢查名稱是否全部正確或是否有異常。
=if(and(countif(g:G,concatenate(a2,"ERROR")>0,NOT(countif(e:e,concatenate(a2,"EXCEPTION")>0))),"No match","match")
最後,在 I 中,您可以找到 Plus = Plus 和 name match = Match 的位置
=IF(AND(F2="Plus",H2="Match"),"Include","Exclude")
這(如果我的公式是正確的 - ymmmv!)應該允許您通過“INCLUDE”過濾列表,瞧,您的列表中的和ID
是或匹配,並且至少其中一個的服務代碼條目包含service
sale
Exception
ID
plus
答案3
這是比 VBA 更靈活的解決方案,但有點手動工作流程混合。
新增標題為「由銷售人員提供服務」的TRUE
/列FALSE
=C2=D2
然後是另一列TRUE
標題FALSE
為「有例外」的列
=COUNTIFS(A:A, A2, B:B, "Exception")
然後您只需過濾表 whereServiced by Sales = TRUE
和Has exception = FALSE
。要取得列表,您可以將 ID 複製並貼上到其他位置,然後執行Data > Remove Duplicates
.
如果您期望即時產生清單報告,我會採用 VBA 解決方案。