Excel - 複雜索引符合以尋找多個值

Excel - 複雜索引符合以尋找多個值

我正在嘗試對錶進行非常複雜的查找並返回多個值。

我需要將每個ID作為一個組,如果Service Code不包含或者如果它包含例外, 忽略它。如果SalesService 匹配,忽略它。其他一切,我需要輸出到一個列表。

我有點不知所措,甚至不知道從哪裡開始。


換句話說,關於服務Sales並且Service無法匹配,除非例外已經做了。 A、B、C 數據根本不重要,但它就在那裡。

我想做什麼

答案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 語句來檢查 whereIDPLUS= 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是或匹配,並且至少其中一個的服務代碼條目包含servicesaleExceptionIDplus

答案3

這是比 VBA 更靈活的解決方案,但有點手動工作流程混合。

新增標題為「由銷售人員提供服務」的TRUE/列FALSE

=C2=D2

然後是另一列TRUE標題FALSE為「有例外」的列

=COUNTIFS(A:A, A2, B:B, "Exception")

然後您只需過濾表 whereServiced by Sales = TRUEHas exception = FALSE。要取得列表,您可以將 ID 複製並貼上到其他位置,然後執行Data > Remove Duplicates.

如果您期望即時產生清單報告,我會採用 VBA 解決方案。

相關內容