iamlaosong文

我们经常需要监督Excel工作表中单元格的值是否变化,例如我们客服有一个报表要通报,报表的内容来自很多地方,需要将这些数据复制到这个表中,由于数据较多,为了防止有遗漏,希望更新后的数据有个标志,这样没有更新的就一目了然了。为此,很自然就会想起利用Worksheet_Change事件完成。当工作表任何单元格发生变化时就会激活这个事件。另一个事件函数Worksheet_SelectionChange则是活动单元格发生变化时激活。

1、用Worksheet_Change事件完成

先看代码,其中的 Date_Change()是用于日期变化的微调按钮指定的宏:


Public Sub Date_Change()
    '日期变化时,将标志还原
    Range("C1:K1") = "Old"
End Sub


Private Sub Worksheet_Change(ByVal Target As Range)
    If Target.Row >= 4 And Target.Row <= 21 Then
        If Target.Column >= 3 And Target.Column <= 11 Then
            '选定范围的值发生变化时
            Cells(1, Target.Column) = "New"
        End If
    End If
End Sub


变点检测ruptures 变点检测Excel_数据备份


2、自定义函数,比较备份值确定

如果不想用worksheet 的 change 事件,也可以自己写个函数,因为用来change 事件,一点改变都会激活这个事件,关键一点是,只要进入了编辑状态,即使值没有变化,也会激活这个事件,使你无法判断值是否真的变了。

为了达到这个目标,在日期变更时,将数据做个备份,标志单元格用个if函数判断一下是不是改变了即可。为了简化判断,只对报表的最后一行总和进行比较。
先看代码,日期变更时将21行的数据备份到24行:


Sub cp_data()

    Application.ScreenUpdating = True
    
    Rows("21:21").Copy
    Range("A24").PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
        :=False, Transpose:=False
    Range("A5").Select
    Application.CutCopyMode = False
    
    Application.ScreenUpdating = True
End Sub

25行的状态单元格内容为公式,如C25:=IF(C24=C21,"Old","New"),如下图所示:


变点检测ruptures 变点检测Excel_数据_02


最后说一下,为了显示明显,标志单元格设置了条件格式,当内容为New时显示为红底。

3、用Worksheet_SelectionChange事件确定值是否真的改变

对于手工修改单元格的值,可以用Worksheet_SelectionChange事件记录修改前的值,这样就可以判断单元格的值是否真的变了,因为要手工修改一个单元格的值,首先要选择它。注意:一次只能选一个单元格。代码如下:


Dim OldValue

Private Sub Worksheet_Change(ByVal Target As Range)
    If Target.Value <> OldValue Then
        MsgBox Target.Address & "单元格由" & OldValue & "变为" & Target.Value
    End If
End Sub

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    OldValue = Target.Value
End Sub