Excel vba:.find 函数返回运行时错误 91

Posted

技术标签:

【中文标题】Excel vba:.find 函数返回运行时错误 91【英文标题】:Excel vba: .find function returns runtime error 91 【发布时间】:2017-01-16 14:52:53 【问题描述】:

我已经阅读了几个小时的相关主题,但似乎找不到解决方案。非常感谢您的帮助,谢谢。

我试图找到一个范围内的最大值,然后找到它在哪一行。 这段代码适用于我的前 600 多行数字,然后崩溃并给我运行时错误 91。它似乎总是在同一个地方崩溃,与我所做的无关。

Dim rSearchRange As Range
Dim dMaxToFind As Double
Dim rSolutionrange As Range

Set rSearchRange = Sheets("MySheet").Range(Cells(672, 1), Cells(681, 1))

With Application.WorksheetFunction
       dMaxToFind = .Max(rSearchRange)
End With

'This bit here returns "nothing" even though i found the max value in this range
Set rSolutionrange = rSearchRange _
            .Find(What:=dMaxToFind, _
            LookIn:=xlFormulas, LookAt:=xlWhole, SearchOrder:=xlByRows, _
            SearchDirection:=xlNext, MatchCase:=False)

查看我的数据,这些行中的格式似乎发生了变化?

    Row 670 - 0.000458587
    Row 671 - 0.000458587
    Row 672 - 9.80465E-05
    Row 673 - 9.80465E-05

编辑:

dMaxToFind 返回 9.80465352566588E-05

单元格公式返回 0.0000980465352566588

Range(Cells(672, 1), Cells(681, 1) 之间的单元格中的值相同

似乎 vba 无法理解这两个是相同的?

谢谢,

标记

【问题讨论】:

试试... LookIn:=xlValues... 如果搜索条件不匹配,.Find 将返回 Nothing。当您稍后使用 rSolutionRange 对象变量并假设它设置为有效引用时,错误 91 被引发(不是“返回”)(Nothing 不是有效的对象引用) - 您需要在使用之前检查If rSolutionRange Is Nothing 如果Sheets("MySheet") 不是活动工作表,Sheets("MySheet").Range(Cells(672, 1), Cells(681, 1)) 也会爆炸,因为Cells(xxx, yyy) 调用隐含地引用ActiveSheet,所以你也需要限定这些调用;使用With Worksheets("MySheet"),然后在With 块内执行Set rSearchRange = .Range(.Cells(672, 1), .Cells(681,1))(注意点)。 谢谢大家,还是没有运气。 user3598756 - 似乎没有改变结果 Mat's Mug - 我尝试了各种方法来调用范围的行或直接使用行而不使用范围。该范围不返回任何内容,因此该行返回错误 91。我也合并了工作表(“MySheet”),但没有运气 【参考方案1】:

这是一个直接告诉你行号的函数。这与您使用内置函数获取最大值然后再次找到它的方法相反!

Function GetMaxRow(ByRef myRange As Range) As Long

    Dim aCell As Range

    Dim maxVal As Double
    Dim maxRow As Long

    maxVal = Application.WorksheetFunction.Min(myRange)
    maxRow = 0

    For Each aCell In myRange

        If aCell.Value > maxVal Then

            maxRow = aCell.row
            maxVal = aCell.Value

        End If

    Next aCell

    GetMaxRow = maxRow

End Function

您可能希望在此函数的结果中添加一些错误检查代码,例如,当函数返回 0 时,这意味着您没有向其传递超过 1 个单元格的范围。

例子:

1 - 3.0
2 - 5.2
3 - 7.8
4 - 2.2
5 - 4.5
6 - 3.6

Dim rw as Long
rw = GetMaxRow(ActiveSheet.Range("A1:A6"))
' >> rw = 3

编辑:

您询问了循环的使用,大概是因为节省时间。下面是一个时序表,当然这在计算机之间会有所不同,但您可以看到这是一个相当快的例程,除非您的数据集很大......而且操作的顺序是线性的,正如预期的那样,这意味着范围加倍大约加倍花费的时间。

2000  rows: 0.0050000s
4000  rows: 0.0099219s
8000  rows: 0.0196875s
16000 rows: 0.0392969s

测试的单元格值是 0 到 1 之间的随机双精度值。

编辑 2:

您使我对速度的兴趣达到了顶峰...因此,我没有在范围内循环(慢),而是编写了相同的函数,但使用了数组。范围被转换为数组,然后循环。这提供了约 10 倍的速度提升!有关相同数据的代码和时序,请参见下文。

Function GetMaxRow(ByRef myRange As Range) As Long

    Dim i As Long

    Dim maxVal As Variant
    Dim maxRow As Long

    maxVal = Application.WorksheetFunction.Min(myRange)
    maxRow = 0

    Dim myArray() As Variant
    myArray = myRange

    For i = 1 To myRange.Count

        If myArray(i, 1) > maxVal Then

            maxRow = i
            maxVal = myArray(i, 1)

        End If

    Next i

    GetMaxRow = myRange.Cells(maxRow).Row

End Function

时间安排:

2000  rows: 0.0006250s
4000  rows: 0.0018750s
8000  rows: 0.0034375s
16000 rows: 0.0068750s

【讨论】:

这看起来不错 - 有没有办法在不循环的情况下做同样的事情? @Mark,我添加了一个更快的版本,请参阅编辑 2 @Mark 不用担心,请注意上面的函数中没有没有错误检查。例如,我没有测试过,如果您的范围包含字符串(可能没问题,但可能会产生意外结果)或错误代码(如 #DIV/0!#VALUE!,这可能会使函数崩溃!)会发生什么情况!

以上是关于Excel vba:.find 函数返回运行时错误 91的主要内容,如果未能解决你的问题,请参考以下文章

Excel VBA 使用 .Find 和 .FindNext 查找精确字符串

用Excel使用VBA时显示运行错误5,错误调用参数,程序特别简单,如图,求问哪里出错了

从嵌套字典中返回密钥excel vba

从 Excel 调用 VBA 函数 - 在选定工作表上的选定列中查找

用户定义的函数在 vba 中工作正常,而从显示“值”错误的 excel 表调用时

excel vba 运行时错误