web-dev-qa-db-ja.com

複数の結果でvlookupに優れています

Vlookupまたは同様の関数を使用してワークシートを検索し、アカウント番号を照合してから、指定された値を返そうとしています。私の問題は、アカウント番号が重複しているため、結果を1つの文字列に連結したいということです。

Acct No   CropType
-------   ---------
0001      Grain
0001      OilSeed
0001      Hay
0002      Grain  

最初のワークシートにあり、2番目のワークシートには他の情報を含むAcct Noがあり、一致するすべての結果を2番目のワークシートの1つの列にまとめる必要があります。 「穀物油糧種子干し草」

13
Jose Quervo

これがあなたのためにそれをする関数です。 Vlookupとは少し異なり、範囲全体ではなく検索列のみを指定します。次に、3番目のパラメーターとして、取得するために左(負の数)または右(正)に移動する列の数を指定します。あなたの戻り値。

セパレーターを使用するオプションも追加しました。あなたの場合は「」を使用します。アカウント番号の最初の行がAで、結果が行Bであると仮定した場合の、関数呼び出しは次のとおりです。

=vlookupall("0001", A:A, 1, " ")

関数は次のとおりです。

Function VLookupAll(ByVal lookup_value As String, _
                    ByVal lookup_column As range, _
                    ByVal return_value_column As Long, _
                    Optional seperator As String = ", ") As String

Dim i As Long
Dim result As String

For i = 1 To lookup_column.Rows.count
    If Len(lookup_column(i, 1).text) <> 0 Then
        If lookup_column(i, 1).text = lookup_value Then
            result = result & (lookup_column(i).offset(0, return_value_column).text & seperator)
        End If
    End If
Next

If Len(result) <> 0 Then
    result = Left(result, Len(result) - Len(seperator))
End If

VLookupAll = result

End Function

ノート:

  • 「、」を入力しない場合の結果のデフォルトの区切り文字にしました。
  • ヒットが1つ以上ある場合は、最後にチェックを追加して、文字列が余分な区切り文字で終わっていないことを確認します。
  • 範囲がわからないので範囲としてA:Aを使用しましたが、実際の範囲を入力すると明らかに高速になります。
8
aevanko

これを行う1つの方法は、配列数式を使用してすべての一致を非表示の列に入力し、それらの値を文字列に連結して表示することです。

=IFERROR(INDEX(cropTypeValues,SMALL(IF(accLookup=accNumValues,ROW(accNumValues)-MIN(ROW(accNumValues))+1,""),ROW(A1))),"")
  • cropTypeValues:作物タイプのリストを保持する名前付き範囲。
  • accLookup:検索するアカウント番号を保持する名前付き範囲。
  • accNumValues:アカウント番号のリストを保持する名前付き範囲。

配列数式として入力し(Ctrl + Shift + Enter)、必要なだけコピーします。

数式の説明が必要な場合はお知らせください。

2
ChrisO

これが私のコードです。これは、列を基準にすることを選択できるため、Excelのvlookupよりも優れており、確実にセパレーター(キャリッジリターンも)...

Function Lookup_concat(source As String, tableau As Range, separator As String, colSRC As Integer, colDST As Integer) As String
    Dim i, y As Integer
    Dim result As String

    If separator = "CRLF" Then
        separator = Chr(10)
    End If

    y = tableau.Rows.Count
    result = ""
    For i = 1 To y
        If (tableau.Cells(i, colSRC) = source) Then
            If result = "" Then
                result = tableau.Cells(i, colDST)
            Else
                result = result & separator & tableau.Cells(i, colDST)
            End If
        End If
    Next
    Lookup_concat = result
End Function

また、ギフトとして、同じセルの複数の要素を(同じセパレーターに基づいて)検索することもできます。本当に便利

Function Concat_Lookup(source As String, tableau As Range, separator As String, colSRC As Integer, colDST As Integer) As String
    Dim i, y As Integer
    Dim result As String

    Dim Splitted As Variant

    If separator = "CRLF" Then
        separator = Chr(10)
    End If

    Splitted = split(source, separator)

    y = tableau.Rows.Count
    result = ""
    For i = 1 To y
        For Each Word In Splitted
            If (tableau.Cells(i, colSRC) = Word) Then
                If result = "" Then
                    result = tableau.Cells(i, colDST)
                Else
                    Dim Splitted1 As Variant
                    Splitted1 = split(result, separator)
                    If IsInArray(tableau.Cells(i, colDST), Splitted1) = False Then
                        result = result & separator & tableau.Cells(i, colDST)
                    End If
                End If
            End If
        Next
    Next
    Concat_Lookup = result
End Function

前のサブにはこの機能が必要です

Function IsInArray(stringToBeFound As String, arr As Variant) As Boolean
  IsInArray = (UBound(Filter(arr, stringToBeFound)) > -1)
End Function
0
Xavier XB

私はちょうど同じような問題を抱えていて、長い間同じような解決策を探してきましたが、私を本当に納得させるものは何もありませんでした。マクロまたは特別な関数を作成する必要がありましたが、私のニーズでは、最も簡単な解決策は、たとえば、ピボットテーブルを使用することです。 Excel。

データから新しいピボットテーブルを作成し、最初に行ラベルとして「Acct No」を追加し、次にRowLabelとして「CropType」を追加すると、アカウントごとにすべての作物タイプが一覧表示される非常に優れたグループになります。ただし、単一のセルではそれは行われません。

0
Andreas