为什么此VBA功能运行缓慢?

时间:2019-06-04 14:34:59

标签: excel vba

我有一个很大的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到10秒之间重新开始响应并接受键盘输入。我不知道为什么它这么慢,因为它从未检查多个单元格。只有一个单元格范围。

诚然,这是一个复杂的电子表格,具有多个自定义功能,相当多的条件格式设置规则以及大量图表。但是,通过测试,我确定只有在我编辑此特定条件格式设置规则范围内的单元格时,才会出现这种减速。如果我编辑范围以排除正在编辑的单元格,则性能问题将消失。

此功能非常简单;为什么这么慢?

1 个答案:

答案 0 :(得分:3)

在我的测试中,此函数的执行速度提高了大约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秒。