【问题标题】:Fire 'Worksheet_Change' event only when cell value is actually different仅当单元格值实际上不同时才触发“Worksheet_Change”事件
【发布时间】:2018-03-09 12:45:43
【问题描述】:

我编写了代码来从特定页面的 URL 中提取数据。 第一次运行代码时,它会从 URL 中提取数据到单元格 C1

我想在单元格值更改时显示MsgBox

例如:

  • 我第一次运行代码时,"Happy" 被提取到单元格 C1。
    (单元格值变了,所以msgbox“值变了”)

  • 第二次运行代码时,"Happy" 也被提取到单元格 C1。
    (表示没有变化,注意发生)

  • 第三次运行代码,"Sad" 被提取到单元格 C1,
    所以在这一点上,我想要一个单元格更改的 msgbox。

我尝试了下面的代码,但即使在单元格中更改了相同的值,它也会显示 msgbox。

例如 - 单元格包含文本 "Happy"。我在单元格中重写"Happy" 并按回车键,因此尽管单元格中的文本相同,但它显示单元格的 msgbox 已更改。

Private Sub Worksheet_Change(ByVal Target As Range)
    Dim KeyCells As Range

    ' The variable KeyCells contains the cells that will
    ' cause an alert when they are changed.
    Set KeyCells = Range("A1:C10")

    If Not Application.Intersect(KeyCells, Range(Target.Address)) Is Nothing Then
        ' Display a message when one of the designated cells has been 
        ' changed.
        ' Place your code here.
        MsgBox "Cell " & Target.Address & " has changed."
    End If
End Sub

【问题讨论】:

  • 你的问题不是很清楚。当指定范围内的单元格发生变化时,您希望发生一些事情,对吗?应该怎么办?
  • @ashleedawg 你说得对。如果单元格值发生变化,我想调用一个宏。假设我将单元格 B1 的值更改为“Happy”,它应该运行宏。那么如果我再次将 B1 的值更改为“快乐”,它不应该做任何事情。
  • 哦 - 如果单元格更改为“相同的值”,则不显示消息...快乐 -> 就 Excel 而言,快乐仍然是一个变化,但有办法解决这个问题...等一下。
  • Ahkil - 希望你不要介意,我把你的问题标题写得更清楚了

标签: vba excel events onchange


【解决方案1】:

这使用Undo 检查单元格的先前值是什么,然后将其与新值进行比较。

这也区分大小写,所以HAPPY = HAPpy。如果您希望它区分大小写,请删除strconv 函数。

请注意,这些过程中的任何一个(包括您的)都不会对多个单元格同时更改(例如粘贴到一系列单元格)做出正确反应,但您可以添加代码来处理该问题但是您需要按照注释行中的说明进行操作。

但是对于单个单元格,这会解决问题:

Private Sub Worksheet_Change(ByVal Target As Range)

    Dim KeyCells As Range, vNew, vOld

    If Target.Cells.Count > 1 Then
        MsgBox ("multiple cells changed: " & vbLf & Target.Address)
        'to handle multiple cells changing at omce you'll need to loop like:
        ' dim c as cell
        ' for each c in Target.Cells
        ' ... etc
        Exit Sub
    End If

    Set KeyCells = Range("A1:C10") ' cells to watch

    If Not Application.Intersect(KeyCells, Target) Is Nothing Then

        vNew = Target.Value
        Application.EnableEvents = False
        Application.Undo
        vOld = Target.Value
        Target.Value = vNew
        Application.EnableEvents = True

        'make sure value is different (NOT case sensitive)
        If StrConv(vNew, vbLowerCase) <> StrConv(vOld, vbLowerCase) Then

            'do something here
            MsgBox "Cell " & Target.Address & " changed" & vblf & _
                "From: " & vOld & vblf & _
                "To:   " & vNew

        End If
    End If
End Sub

更多信息:

【讨论】:

  • @AkhilChaudhary:如果您对答案感到满意,请不要忘记将其标记为已接受,原因有两个:1. 它关闭了查询。 2.提供答案的人将获得答案
【解决方案2】:

替换:

If Not Application.Intersect(KeyCells, Range(Target.Address))

与:

If Not Application.Intersect(KeyCells, Target)

【讨论】:

  • 如果值被替换为相同的值,它仍然会触发。
  • 加里的学生的意思是Range(Target.Address) 没有多大意义,因为Target 已经是一个范围。因此,您尝试使地址超出范围以使地址超出范围。
  • @ashleedawg 你是对的。如果你通过重新输入相同的值来更新单元格,将触发事件。
  • @Pᴇʜ - 我想知道,但我很惊讶他把它作为答案留下了。大概是疏忽。 (我什至测试了它是否有我不知道的秘密功能!)
【解决方案3】:

试试这样:

Public PrevValue

Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
If Target.Value <> PrevValue Then
    MsgBox ("value changed")
    PrevValue = Target.Value
End If
End Sub

之前的值现在存储在全局变量中。当值发生变化时,它首先检查该值是否与之前的值相同。

编辑: 如果每次换不同的cell,也可以用

Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
PrevValue = Target.Value
End Sub

设置更改前当前选中单元格的值。

【讨论】:

  • 只有在同一单元格连续两次更改时才有效,对吗?或者,两个单元格连续更改为相同的值。
  • 你是对的!多个单元格需要额外的代码。改变了答案:)
  • 我假设你说的事件顺序是:selectionchange > (单元格实际发生变化) > change ?
  • 是的。但无论如何,我更喜欢你的想法。从未想过使用撤消。
  • 搞笑,我更喜欢你的想法!
猜你喜欢
  • 1970-01-01
  • 2019-06-08
  • 1970-01-01
  • 2018-09-13
  • 2021-02-27
  • 1970-01-01
  • 2017-09-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多