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.80465352566588 E-05

Формула ячейки возвращает 0.0000980465352566588

одинаковое значение в ячейках между диапазонами (ячейки (672, 1), ячейки (681, 1)

кажется, что vba не понимает, что эти два одинаковы?

Спасибо,

Отметка

1 ответ

  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.

    Edit 2:

    Ты достиг пика моего интереса к скорости… Поэтому вместо циклического обхода диапазона (медленного) я написал ту же функцию, но с использованием массива. Диапазон преобразуется в массив, а затем зацикливается. Это предлагает улучшения скорости ~10x! Код и тайминги для одних и тех же данных см. ниже.

    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