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 函数 - 在选定工作表上的选定列中查找