Excel-여러 값을 찾는 복잡한 인덱스 일치


0

테이블에서 매우 복잡한 조회를 수행하고 여러 값을 반환하려고합니다.

나는 각을 수행해야 ID하는 경우, 그룹으로 Service Code포함하지 않는 플러스 하거나 포함되어있는 경우 예외를 무시하십시오. 경우 SalesService 하지 않는 일치를 무시합니다. 다른 모든 것들은 목록으로 출력해야합니다.

나는 고개를 숙이고 있고 어디서부터 시작해야할지조차 모른다.


에 즉, 플러스 서비스 SalesService하지 않는 일치 할 수없는 예외가 만들어졌다. A, B, C 데이터는 전혀 중요하지 않지만 거기에 있습니다.

내가하고자하는 것


VBA 솔루션을 열거 나 Excel 수식 만 사용할 수 있습니까?
Jonno

VBA는 완벽하게 허용됩니다. 방금 수식으로 가능 해야하는 것 같습니다 .
Tycho

답변:


0

좋아, 나는 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

결과:

여기에 이미지 설명을 입력하십시오.


0

내가 당신을 올바르게 이해했다면, ID의 서비스 코드에 플러스가 포함되지 않은 경우 ID 코드를 제외하려는 것을 제외하고 위의 목록을 원합니다. 또한 판매 및 서비스가 일치하지 않으면 exception서비스 코드에 없는 한 포함되지 않습니다 .

도우미 열에 대해 생각해 보셨습니까?

가장 쉬운 방법은 열 E에서 열 A + B를 연결하여 ID 번호와 서비스 코드 행을 제공하는 것입니다.

그런 다음 E 행에서 countif 문을 사용하여 where IDPLUS= 를 확인할 수 있습니다 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")

마지막으로, 나는 당신이 플러스 = 플러스와 이름 일치 = 일치하는 곳을 찾을 수 있습니다

=IF(AND(F2="Plus",H2="Match"),"Include","Exclude")

이것은 (내 공식이 다시 보정 ymmmv 경우!) 그런 다음 "포함", 등 짜잔의 목록으로 목록을 필터링 할 수 있도록해야한다 IDservicesale중 하나입니다 Exception또는 일치하고, 하나 임대에서 ID의 서비스 코드 항목이 포함plus


0

다음은 VBA보다 유연한 솔루션이지만 수동 워크 플로 하이브리드입니다.

"서비스 제공"이라는 제목 의 TRUE/ FALSE열 추가

=C2=D2

그런 다음 다른 TRUE/ FALSE라는 제목의 칼럼은 "예외를 가지고 있습니다"

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

그런 다음 단순히 테이블을 필터링하면 where Serviced by Sales = TRUEHas exception = FALSE. 목록을 얻으려면 ID를 다른 곳에 복사하여 붙여넣고를 실행하십시오 Data > Remove Duplicates.

목록의 실시간 보고서 생성을 기대하는 경우 VBA 솔루션을 연기합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.