Почему эта функция VBA работает медленно? - PullRequest
0 голосов
/ 04 июня 2019

У меня довольно большой файл Excel с большим количеством введенных вручную данных и большим количеством вычисляемых столбцов. Один набор столбцов содержит номера стойки, которые отформатированы как текст и представляют собой трехзначные числа. Ячейка может содержать ноль или более номеров стойки. Если в ячейке существует несколько номеров стойки, они разделяются /. Поскольку я часто набираю жирные номера стойки и по ошибке вводю четырехзначные числа, я установил правило условного форматирования, чтобы цвета ячеек с номерами неисправных стоек были красными.

Вот мое правило:

=HAS_BAD_RACK_NO(L1834)

, который применяется к диапазону =$L$1834:$S$1981. Точный диапазон меняется день ото дня, но он всегда примерно одинакового размера. Вот функция VBA, которая управляет этим:

Public Function HAS_BAD_RACK_NO(ref As Range) As Boolean
    Dim re As New RegExp
    Dim cell As Range
    Dim found As Boolean
    found = False
    re.Pattern = "[0-9]{4,}"
    For Each cell In ref.Cells
        If re.Test(cell.value) Then
            HAS_BAD_RACK_NO = True
            found = True
            Exit For
        End If
    Next cell
    If Not found Then
        HAS_BAD_RACK_NO = False
    End If
End Function

Проблема заключается в том, что это правило условного форматирования значительно замедляет работу Excel при вводе данных в одну из покрываемых им ячеек. Я полагаю, что после того, как я покину ячейку Excel, я снова начну отвечать на запросы и принимать ввод с клавиатуры. Я не могу понять, почему это так медленно, потому что он никогда не проверяет более одной клетки. Есть только один диапазон ячеек.

По общему признанию, это сложная электронная таблица с несколькими пользовательскими функциями и довольно большим количеством правил условного форматирования, а также большим количеством диаграмм. Тем не менее, путем тестирования я установил, что это замедление происходит только при редактировании ячейки в диапазоне этого конкретного правила условного форматирования. Если я изменю диапазон, чтобы исключить редактируемую ячейку, проблемы с производительностью исчезнут.

Эта функция действительно проста; почему так медленно?

1 Ответ

3 голосов
/ 04 июня 2019

В моем тестировании эта функция будет выполняться примерно в 30 раз быстрее - вместо статического выражения каждый раз при запуске будет использоваться статическое регулярное выражение:

Public Function HAS_BAD_RACK_NO(ref As Range) As Boolean

    Static re As RegExp    '<< use a static object

    'only create if needed
    If re is nothing then
        Set re = New RegExp
        re.Pattern = "[0-9]{4,}"
    end if

    if ref.countlarge > 1 then
        HAS_BAD_RACK_NO = True 'don't allow multiple-cell inputs
    else
        HAS_BAD_RACK_NO = re.Test(ref.value)
    end if
End Function

Тестирующая подпрограмма:

Sub Driver()
    Dim t
    t = Timer
    'L34:S181 contains the data which the UDF processes
    With ActiveSheet.Range("L34:S181")
        .Value = .Value
    End With
    Debug.Print Timer - t
End Sub

~ 1,3 сек для исходной версии, против ~ 0,04 сек для той, которая использует статическое регулярное выражение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...