Страницы: 1
RSS
Скорость проверки на пустоту в диапозоне/массиве
 
Всем привет!

Во вложении пример небольшой таблички. Написал макрос который проверяет есть ли пустые ячейки в таблице.
Попробовал с помощью массива и без. Оба варианта не особо быстрые (причем без массива на доли секунд быстрее). Можно как-то ускорить обработку?
Код
Sub check_inbound()
Dim arr_check As Variant
Dim t As Single
t = Timer
Application.ScreenUpdating = False
With Sheets("Приход")

'arr_check = .Range(.Cells(6, 3), .Cells(.UsedRange.Rows.Count, 10))
'For i = LBound(arr_check, 1) To UBound(arr_check, 1)
'    For j = LBound(arr_check, 2) To UBound(arr_check, 2)
'        If IsEmpty(arr_check(i, j)) Then
'            .Cells(i + 5, 2).Value = "NOK"
'            GoTo next_i
'        Else: .Cells(i + 5, 2).Value = "OK"
'        End If
'    Next j
'next_i:
'Next i

For i = .UsedRange.Rows.Count To 6 Step -1
    For j = 3 To 10
        If IsEmpty(.Cells(i, j).Value) Then
            .Cells(i, 2).Value = "NOK"
            GoTo next_i
        Else: .Cells(i, 2).Value = "OK"
        End If
    Next j
next_i:
Next i

End With
t = Timer - t
MsgBox t
Application.ScreenUpdating = True
End Sub
 
Код
Sub check_inbound()
Dim i As Long
Dim j As Long
Dim arr_check As Variant
Dim arr_report As Variant
Dim t As Single
t = Timer
Application.ScreenUpdating = False
With Sheets("Приход")
 
arr_check = .Range(.Cells(1, 3), .Cells(.UsedRange.Rows.Count, 10))
ReDim arr_report(1 To UBound(arr_check, 1), 1 To 1)
For i = 6 To UBound(arr_check, 1)
    For j = LBound(arr_check, 2) To UBound(arr_check, 2)
        If IsEmpty(arr_check(i, j)) Then
            arr_report(i, 1) = "NOK"
            GoTo next_i
        Else: arr_report(i, 1) = "OK"
        End If
    Next j
next_i:
Next i
 
'For i = .UsedRange.Rows.Count To 6 Step -1
'    For j = 3 To 10
'        If IsEmpty(.Cells(i, j).Value) Then
'            .Cells(i, 2).Value = "NOK"
'            GoTo next_i
'        Else: .Cells(i, 2).Value = "OK"
'        End If
'    Next j
'next_i:
'Next i
 
    .Cells(1, 2).Resize(UBound(arr_report, 1)) = arr_report
 
End With
t = Timer - t
MsgBox t
Application.ScreenUpdating = True
End Sub
 
Vladimir69, здравствуйте

Цитата
Vladimir69: причем без массива на доли секунд быстрее
значит неправильно делаете, т.к. перебор ячеек всегда заметно дольше перебора массива
Цитата
Vladimir69: Можно как-то ускорить обработку?
есть ещё методы Range.SpecialCells(xlCellTypeBlanks) и Range.Find. Если пустых нет, их мало и они в конце диапазона (а перебираете массив с начала) или диапазон для проверки очень большой, то методы (ставлю на .Find) могут быть заметно быстрее. В прочих случаях - массив.
  Ещё можно использовать штатные функции {=ЕПУСТО(диапазон)} (формула массива) или =СЧИТАТЬПУСТОТЫ() (обычная), но я не сравнивал скорости…
  Ещё вот тут обсуждалось много интересного

Поиск и выделение/сбор данных в диапазоне
Изменено: Jack Famous - 17.05.2022 09:33:05
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
 
Еще вариант:
Код
Sub check_inbound()
Dim arr_check As Variant
Dim t As Single
t = Timer
Application.ScreenUpdating = False
With Sheets("Приход")
    With .Range(.Cells(6, 2), .Cells(.UsedRange.Rows.Count, 2))
        .FormulaR1C1 = "=IF(COUNTIF(RC3:RC10,""""),""NOK"",""OK"")"
        .Calculate
        .Value = .Value
    End With
End With
t = Timer - t
MsgBox t
Application.ScreenUpdating = True
End Sub

На больших массивах должен работать весьма шустро. Если автопересчет формул и так включен - то строку .Calculate можно убрать.
Так же можно заменить и формулу на такую:
Код
.FormulaR1C1 = "=IF(COUNTBLANK(RC3:RC10),""NOK"",""OK"")"

но будет ли это быстрее - не сравнивал. СЧЁТЕСЛИ весьма шустрая, но т.к. ячеек для проверки внутри одной функции мало - возможно COUNTBLANK будет быстрее.
Изменено: Дмитрий(The_Prist) Щербаков - 17.05.2022 09:37:43
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
МатросНаЗебре, Спасибо. Решение отлично зашло.
 
Дмитрий(The_Prist) Щербаков, кстати, да. В моем пример COUNTBLANK для проверки построчно точно подошел бы.
 
Цитата
МатросНаЗебре: IsEmpty
для большинства ситуаций подойдёт, но нужно помнить, что она не считает пустыми ячейки со строками нулевой длины. А Len()=0 быстрая и "схавает" такие строки.
Как отличить одно от другого показано в моей теме VBA. UDF. Функция для проверки значения на строку нулевой длины «=""»
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
Страницы: 1
Наверх