2017-01-16 298 views
0

我一直在閱讀相關的線程幾個小時,但似乎無法找到解決方案。非常感謝您的幫助,謝謝。Excel vba:.find函數返回運行時錯誤91

我想找到一個範圍內的最大值,然後找到它所在的行。 此代碼適用於我的第一個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

它是在細胞範圍之間的相同的值(將細胞(672,1),將細胞( 681,1)

好像vba不能理解那兩個是一樣的嗎?

謝謝,

馬克

+3

試試'...看着:= xlValues ...'' – user3598756

+1

將.Find'如果沒有匹配搜索條件返回'Nothing'。當你稍後*使用'rSolutionRange'對象變量並且假設它被設置爲有效引用('Nothing'不是有效的對象引用)時,錯誤91被*引發*(不是「返回」) - 您需要檢查'如果rSolutionRange是Nothing,則在使用它之前。 –

+1

如果'Sheets(「MySheet」)'不是活動工作表,'Sheets(「MySheet」)。Range(Cells(672,1),Cells(681,1))''會爆炸,因爲'Cells xxx,yyy)'調用隱式引用'ActiveSheet',所以你也需要限定這些調用;使用'With Worksheets(「MySheet」)'然後'Set rSearchRange = .Range(.Cells(672,1),.Cells(681,1))'在'With'塊內(注意點)。 –

回答

0

這裏是一個函數,它會直接告訴你的行號。這與您在構建函數中使用以獲得最大值然後再次找到它的方法相反!

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 
+0

這看起來不錯 - 有沒有任何方式做同樣的事情沒有循環? – Mark

+0

謝謝,你是因爲時機問的嗎?看到我的編輯... – Wolfie

+0

@Mark,我添加了更快的版本,請參閱編輯2 – Wolfie