【问题标题】:How to find a matching row in Excel?如何在 Excel 中找到匹配的行?
【发布时间】:2010-09-21 15:19:08
【问题描述】:

给定

一个搜索键

---------------------------
|   |  A  | B | C |   D   |
---------------------------
| 1 | 01  | 2 | 4 | TextA |
---------------------------

Excel 表格

------------------------------
|   |  A | B | C |   D   | E |
------------------------------
| 1 | 03 | 5 | C | TextZ |   |
------------------------------
| 2 | 01 | 2 | 4 | TextN |   |
------------------------------
| 3 | 01 | 2 | 4 | TextA |   |
------------------------------
| 4 | 22 | T | N | TextX |   |
------------------------------

问题

我想要一个这样的函数:f(key) -> result_row.

这意味着:给定一个搜索键 (01, 2, 4, TextA),该函数应该告诉我在上面的示例中匹配的行是 3。

搜索键(A、B、C、D)中的值是唯一标识符。

如何获取匹配行的行号?

一个解决方案

我首先想到的解决方案是使用 Visual Basic for Application (VBA) 在 A 列中扫描“01”。找到包含“01”的单元格后,我会检查 B、C 和 D 列中的相邻单元格是否符合我的搜索条件。

我猜这个算法会起作用。但是:有更好的解决方案吗?

版本

  • Excel 2000 9.0.8961 SP3
  • VBA 6.5

但是,如果您碰巧知道任何更高版本的 Excel 或 VBA 中的解决方案,我也很想知道。

编辑:22.09.2010

谢谢大家的回答。 @MikeD:非常好的功能,谢谢!

我的解决方案

这是我原型化的解决方案。这都是硬编码的,太冗长了,不像 MikeD 的解决方案那样是一个函数。但我会在我的实际应用程序中重写它以获取参数并返回结果值。

Sub FindMatchingRow()
    Dim searchKeyD As Variant
    Dim searchKeyE As Variant
    Dim searchKeyF As Variant
    Dim searchKeyG As Variant

    Const indexStartOfRange As String = "D6"
    Const indexEndOfRange As String = "D9"

    ' Initialize search key
    searchKeyD = Range("D2").Value
    searchKeyE = Range("E2").Value
    searchKeyF = Range("F2").Value
    searchKeyG = Range("G2").Value


    ' Initialize search range
    myRange = indexStartOfRange + ":" + indexEndOfRange

    ' Iterate over given Excel range
    For Each myCell In Range(myRange)

        foundValueInD = myCell.Offset(0, 0).Value
        foundValueInE = myCell.Offset(0, 1).Value
        foundValueInF = myCell.Offset(0, 2).Value
        foundValueInG = myCell.Offset(0, 3).Value

        isUnitMatching = (searchKeyD = foundValueInD)
        isGroupMatching = (searchKeyE = foundValueInE)
        isPortionMatching = (searchKeyF = foundValueInF)
        isDesignationMatching = (searchKeyG = foundValueInG)
        isRowMatching = isUnitMatching And isGroupMatching And isPortionMatching And isDesignationMatching

        If (isRowMatching) Then
            Range("D21").Value = myCell.Row
            Exit For
        End If

    Next myCell
End Sub

这是与上述代码一起使用的 Excel 表格:

【问题讨论】:

    标签: vba excel


    【解决方案1】:

    这是我经常用于这种目的的一个小型 VBA 函数

    Function FindInRange(InRange As Range, Arg As Range) As Integer
    Dim Idx As Integer, Jdx As Integer, IsFound As Boolean
    
        FindInRange = 0
        IsFound = False
    
        For Idx = 1 To InRange.Rows.Count
            IsFound = True
            For Jdx = 1 To InRange.Columns.Count
                If InRange(Idx, Jdx) <> Arg(1, Jdx) Then
                    IsFound = False
                    Exit For
                End If
            Next Jdx
    
            If IsFound Then
                FindInRange = Idx
                Exit For
            End If
        Next Idx
    
    End Function
    

    InRange 的宽度必须与Arg 相同或更宽,但当然可以大于或小于您的 A:D

    在您的示例表中,在空单元格中输入“=findinrange(A1:D4,A3:D3)”

    如果没有找到,公式将返回“0”,否则返回行#

    祝你好运 - MikeD

    【讨论】:

    • 很不错的功能,谢谢!我用我的解决方案更新了我的问题,但我更喜欢你的例子。
    • Danke für die Blumen!我在股票上有这个功能;-) ...我们都在以某种方式做同样的事情。我想这里的关键可能是将问题带到更高的抽象级别:“逐行比较给定范围内具有相同列数的多个标准”
    【解决方案2】:

    假设您的搜索关键字从 A1​​ 开始,而您的数据从 A3 开始。此数组公式将返回所有数据与搜索键匹配的行号

    =SUM(($A$3:$A$6=A1)*($B$3:$B$6=B1)*($C$3:$C$6=C1)*($D$3:$D$6=D1)*(ROW($A$3:$A$6)))
    

    使用 Control+Shift+Enter 输入,而不仅仅是 Enter。请注意,它返回工作表行,而不是表中的位置。如果您想要表格中的位置,您可以从结果中减去表格的起始行(在这种情况下为 2,因为表格从第 3 行开始)。

    如果有多个匹配的行,这将返回所有行的总和(不是很有帮助)。但我假设只有一个匹配的行。

    【讨论】:

      【解决方案3】:

      另一种选择是在 Excel 工作表中添加一个新列,其中列 A:D 连接在一起,然后使用 lookup/sverweis 函数。这可能比 VBA 解决方案更快。

      【讨论】:

      • 您如何从 VLOOKUP 中获得“匹配行数”?
      • hmm,看来行号需要多一列。但是,如果您有复合键,为什么要使用行号作为 id 呢?如果您使用的是 Excel2007,sumifs 和行号列是另一种选择...
      • 我不想质疑获取行号的意图 - 如果以这种方式提出问题,那将是有充分理由的。另一方面,我同意您的观点,在许多情况下,“级联密钥”是一个很好的解决方案。我通常会添加一个分隔符来避免像“12_34”和“123_4”这样的奇怪效果。
      • 匹配而不是查找会给你行。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-07
      • 1970-01-01
      • 2021-05-04
      • 1970-01-01
      • 2013-05-18
      • 1970-01-01
      相关资源
      最近更新 更多