【问题标题】:Excel VBA - Find Row Number for Given Value in a Table ColumnExcel VBA - 在表格列中查找给定值的行号
【发布时间】:2021-01-21 22:32:35
【问题描述】:

背景

我不久前构建了这段代码,它可以在一个电子表格中运行。它本质上被调用以在第一个表列中查找给定值的表行号。然后,其余代码使用此表行号来更新该行的值。

我最近将同样的方法应用到另一个电子表格中,并且它一直工作到昨天。现在在 myArray = tbl.DataBodyRange 行上,我得到一个运行时错误“6”(溢出)。最近的电子表格中的表格有更多的数据,所以 myArray 不能再保存表格数据了。

我已经修改了我的代码以使用 ListRows 搜索表格行,然后检查第一列的每个值,直到找到我要查找的内容。

在这两个例程中,如果未找到该值,则返回 0,并且其他代码知道不尝试更新表行。

问题

我是否可能会在修改后的方法中遇到更多问题和/或是否有更有效的方法来查找我正在寻找的行号。该表目前有大约 700 行数据,未来几个月将增长到 4000 多行。

出现溢出错误的代码

Function getRowNum(ByVal valueToFind As String)
    Dim tbl As ListObject
    Dim myArray As Variant
    Dim x As Long
    Dim checkvalueToFind As String
    Dim rowFound As Integer
    
    rowFound = 0
    
    Set tbl = Range("table_masterList").ListObject
    
    myArray = tbl.DataBodyRange
    
    For x = LBound(myArray) To UBound(myArray)
        checkvalueToFind = myArray(x, 1)
        'Debug.Print checkvalueToFind
        If checkvalueToFind = valueToFind Then
            rowFound = x
            GoTo foundIt
        End If
    Next x
    
foundIt:
    
    Set tbl = Nothing
    getRowNum = rowFound
    
End Function

修改后的代码

Function getRowNum2(ByVal valueToFind As String)
    Dim tbl As ListObject
    Dim row As ListRow
    Dim checkvalueToFind As String
    Dim rowFound As Integer
    
    rowFound = 0
    
    Set tbl = Range("table_masterList").ListObject
    
    For Each row In tbl.ListRows
        checkvalueToFind = tbl.DataBodyRange.Cells(row.Index, 1).Value
         If checkvalueToFind = valueToFind Then
            rowFound = row.Index
            GoTo foundIt
        End If
    Next row
        
foundIt:
    
    Set tbl = Nothing
    getRowNum2 = rowFound
    
End Function

【问题讨论】:

    标签: excel vba


    【解决方案1】:

    循环过于复杂。只需使用Match

    Function getRowNum(ByVal valueToFind As String) As Long
        ...
        Dim matchResult As Variant
        matchResult = Application.Match(valueToFind, tbl.ListColumns(1).DataBodyRange, 0)
    
        If IsError(matchResult) Then
           getRowNum = 0
        Else
           getRowNum = matchResult
        End If
    End Function
    

    或者稍微简单一点:

    Function getRowNum(ByVal valueToFind As String) As Long
        ...
        Dim matchResult As Variant
        matchResult = Application.Match(valueToFind, tbl.ListColumns(1).DataBodyRange, 0)
    
        If Not IsError(matchResult) Then
           getRowNum = matchResult
        End If
    End Function
    

    【讨论】:

    • 感谢 BigBen,这样效率更高。我刚刚对其进行了测试并进行了治疗。关于显式设置 getRowNum = 0,我猜是因为 getRowNum 已被声明为 Long,无论如何它都会被初始化为 0,因此代码更短?
    • 嗨@Bigben,出于好奇,如果表中有多个匹配项怎么办?您如何建议获得每场比赛的所有行位置?你的回复对我来说意义重大。谢谢!
    • @Owennn 可能将数据读入Variant 数组并使用循环。
    • @BigBen,-谢谢你的想法!它会与您的功能一起使用还是必须是一个循环?似乎 Application.Match 只给出了表中的第一个匹配项。
    • @Owennn yes Application.Match 只给出第一个匹配项,因此您只需使用循环;但是,循环数组应该非常快。
    猜你喜欢
    • 2021-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-16
    • 2011-08-21
    • 2013-08-18
    相关资源
    最近更新 更多