【问题标题】:excel vlookup with multiple results具有多个结果的excel vlookup
【发布时间】:2011-07-19 21:53:39
【问题描述】:

我正在尝试使用 vlookup 或类似功能来搜索工作表,匹配帐号,然后返回指定值。我的问题是有重复的帐号,我希望将结果连接成一个字符串。

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

在第一个工作表中,在第二个工作表上,我有Acct No 和其他信息,我需要将所有匹配结果放入第二个工作表的一列中,即。 “谷物油籽干草”

【问题讨论】:

  • +1 便于理解第一个问题:)

标签: excel excel-formula


【解决方案1】:

这是一个可以为您完成的功能。它与 Vlookup 有点不同,你只会给它搜索列,而不是整个范围,然后作为第三个参数,你会告诉它要向左(负数)或向右(正)多少列才能得到你的返回值。

我还添加了使用分隔符的选项,在您的情况下,您将使用“”。这是为您调用的函数,假设帐户编号的第一行是 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

注意事项:

  • 如果您不输入结果分隔符,我将“,”设为默认分隔符。
  • 如果有一个或多个命中,我在最后添加了一些检查以 确保字符串不以额外的分隔符结尾。
  • 我使用 A:A 作为范围,因为我不知道您的范围,但是 如果输入实际范围显然会更快。

【讨论】:

  • 效果很好!可悲的是它需要很长时间:(
  • 使用此代码传递无限范围绝对不是一个好主意。如果您像此处的示例一样传入 A:A,则代码将在每次运行时检查所有 1,048,576 行。最好只输入一个实际范围,而不是传入整个列。
  • @aevanko 使用 WorksheetFunction.CountA(lookup_column) 进行计数,速度更快!
【解决方案2】:

执行此操作的一种方法是使用数组公式将所有匹配项填充到隐藏列中,然后将这些值连接到您的字符串中以进行显示:

=IFERROR(INDEX(cropTypeValues,SMALL(IF(accLookup=accNumValues,ROW(accNumValues)-MIN(ROW(accNumValues))+1,""),ROW(A1))),"")
  • cropTypeValues:包含作物类型列表的命名范围。
  • accLookup:保存要查找的帐号的命名范围。
  • accNumValues:保存您帐户列表的命名范围 数字。

以数组公式的形式输入 (Ctrl+Shift+Enter),然后根据需要向下复制。

如果您需要解释公式的任何部分,请告诉我。

【讨论】:

  • 这是我的首选解决方案,因为它避免了共享时可能被禁用的宏。这对于无限数量的匹配并不理想,但如果您只期待一些匹配就可以了。 extendoffice.com/documents/excel/… 给出了很好的例子。
【解决方案3】:

我刚刚遇到了类似的问题,并且我已经查找了很长时间的类似解决方案,但没有什么能真正说服我。要么你必须编写一个宏,要么是一些特殊的函数,然而,为了我的需要,最简单的解决方案是在例如使用数据透视表。 Excel。

如果您从数据创建一个新的数据透视表,并首先添加“Acct No”作为行标签,然后将“CropType”添加为 RowLabel,您将拥有一个非常好的分组,为每个帐户列出所有作物类型。但它不会在单个单元格中执行此操作。

【讨论】:

    【解决方案4】:

    这是我的代码,它甚至比 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
    

    【讨论】:

      【解决方案5】:
      Function VLookupAll(vValue, rngAll As Range, iCol As Integer, Optional sSep As String = ", ")
          Dim rCell As Range
          Dim rng As Range
          On Error GoTo ErrHandler
          Set rng = Intersect(rngAll, rngAll.Columns(1))
          For Each rCell In rng
              If rCell.Value = vValue Then
                  VLookupAll = VLookupAll & sSep & rCell.Offset(0, iCol - 1).Value
              End If
          Next rCell
          If VLookupAll = "" Then
              VLookupAll = CVErr(xlErrNA)
          Else
              VLookupAll = Right(VLookupAll, Len(VLookupAll) - Len(sSep))
          End If
      ErrHandler:
          If Err.Number <> 0 Then VLookupAll = CVErr(xlErrValue)
      End Function
      

      这样使用:

      =VLookupAll(K1, A1:C25, 3)

      查找范围 A1:A25 中所有出现的 K1 值,并从 C 列返回相应的值,以逗号分隔。

      如果要对值求和,可以使用 SUMIF,例如

      =SUMIF(A1:A25, K1, C1:C25)

      对 C1:C25 中的值求和,其中 A 列中的相应值等于 K1 的值。

      一切顺利。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多