Excel VBA中监听单元格更改的最佳方式

时间:2017-10-30 18:22:43

标签: excel vba

我正在尝试观察细胞的变化。单元可以通过来自加载项的某些VBA代码触发每秒多次更改。我想计算值更新的次数。

到目前为止我所拥有的是:

Private Sub Worksheet_Calculate()
    Static oldval
    If Range("C3").Value <> oldval Then
        oldval = Range("C1").Value
        Blad1.Range("N18").Value = Blad1.Range("N18").Value + 1
    End If
End Sub

问题在于,当我启动Excel工作表时,代码会立即崩溃并出现错误:Out of stack space

我现在的问题是为什么我会收到此错误,这是我想要做的最好的实现吗?

1 个答案:

答案 0 :(得分:6)

StackOverflow上有关堆栈溢出的问题。

递增计数器单元会触发Calculate事件,该事件会递增计数器,从而触发Calculate事件等。使用另一个静态变量来防止递归。静态变量在对托管它的过程的调用中保持其值。

Private Sub Worksheet_Calculate()
    Static bWorking as Boolean
    Static oldval As Variant

    If Not bWorking Then
        If Range("C3").Value <> oldval Then
            oldval = Range("C1").Value

            bWorking = True
            Blad1.Range("N18").Value = Blad1.Range("N18").Value + 1
            bWorking = False
        End If
    End If
End Sub

还要考虑@YowE3关于为什么你的代码将oldval设置为C1的值的评论。

编辑:对于问题的性能部分,假设您想要将计数器的值实时存储到单元格中,您可以通过重复使用单元格引用来获得边际收益,维护静态变量中的计数,并使用Value2属性。

Private Sub Worksheet_Calculate()
    Static monitoredCell As Excel.Range
    Static counterCell As Excel.Range
    Static counter As Long
    Static bWorking As Boolean
    Static oldVal As Variant

    If Not bWorking Then
        If monitoredCell Is Nothing Then
            'Initialize the ranges.
            Set monitoredCell = Me.Range("C3")
            Set counterCell = Blad1.Range("N18")
            'Comment out the line below if you don't wish to keep counting from the last saved value.
            counter = counterCell.Value2
        End If

        If monitoredCell.Value2 <> oldVal Then
            oldVal = monitoredCell.Value2
            counter = counter + 1

            bWorking = True
            counterCell.Value2 = counter
            bWorking = False
        End If
    End If
End Sub