在单元格更改时自动执行 Excel 宏

Posted

技术标签:

【中文标题】在单元格更改时自动执行 Excel 宏【英文标题】:automatically execute an Excel macro on a cell change 【发布时间】:2010-09-29 09:28:41 【问题描述】:

如何在每次特定单元格中的值更改时自动执行 Excel 宏?

现在,我的工作代码是:

Private Sub Worksheet_Change(ByVal Target As Range)
    If Not Intersect(Target, Range("H5")) Is Nothing Then Macro
End Sub

其中"H5" 是被监控的特定单元,Macro 是宏的名称。

有没有更好的办法?

【问题讨论】:

FormulaDesk 中的 RunMacroWhenValueChanges UDF 是否满足您的要求? formuladesk.com excel VBA run macro automatically whenever a cell is changed的可能重复 【参考方案1】:

处理Worksheet_Change 事件或Workbook_SheetChange 事件。

事件处理程序接受一个参数“Target As Range”,因此您可以检查正在更改的范围是否包括您感兴趣的单元格。

【讨论】:

谢谢,它有效。我用Target.Address = Range("H5").Address 检查范围。有没有更简单的方法? 另一种选择:Not (Intersect(Target, Range("H5")) Is Nothing) 。你会这样做吗? 如果您的单元格只是更改范围的部分,则第一条评论 (Target.Address = Range("H5").Address) 将不起作用。第二条评论仍然存在 Mike Rosenblum 所描述的问题。【参考方案2】:

我更喜欢这种方式,不是使用单元格而是使用范围

    Dim cell_to_test As Range, cells_changed As Range

    Set cells_changed = Target(1, 1)
    Set cell_to_test = Range( RANGE_OF_CELLS_TO_DETECT )

    If Not Intersect(cells_changed, cell_to_test) Is Nothing Then 
       Macro
    End If

【讨论】:

同一个单元格。您可以将范围设置为一个单元格、连续单元格的范围,甚至是分散的单元格(全部用逗号分隔)。【参考方案3】:

您的代码看起来不错。

但是请注意,您对Range("H5") 的调用是对Application.Range("H5") 的快捷命令,它等效于Application.ActiveSheet.Range("H5")。如果唯一的更改是用户更改(这是最典型的),这可能很好,但是当工作表的单元格值不是活动工作表时,它可能会通过编程更改来更改,例如VBA。

考虑到这一点,我会使用Target.Worksheet.Range("H5")

Private Sub Worksheet_Change(ByVal Target As Range)
    If Not Intersect(Target, Target.Worksheet.Range("H5")) Is Nothing Then Macro
End Sub

或者您可以使用Me.Range("H5"),如果事件处理程序位于相关工作表的代码页上(通常是):

Private Sub Worksheet_Change(ByVal Target As Range)
    If Not Intersect(Target, Me.Range("H5")) Is Nothing Then Macro
End Sub

希望这会有所帮助...

【讨论】:

如果单元格H5 是从另一张纸上更改的,比如sheet2,那么上述功能不起作用。请帮忙。 对于从谷歌搜索来到这里的任何人,请确保将此代码粘贴到 vba 中的工作表中,而不是像我那样粘贴到模块中。看***.com/questions/15337008/… Application.ActiveSheet.Range("H5")。 ==> target.parent.range("H5") 更安全 @WillEdiger 每当您未明确指定工作表引用时,Excel 将假定为 ActiveSheet,而只要您未明确指定正在使用的是 Excel,Excel 将假定为 Application 请注意,在工作表代码模块(Worksheet_Change 事件必须位于的位置)中,不合格的Range 不是默认为 ActiveSheet 但而是指包含代码的工作表。因此,此答案中的代码实际上与问题中的代码相同。 (注意:早在 2009 年撰写此答案时,它可能有所不同,但我很确定它不是。)【参考方案4】:

我有一个链接到在线股票数据库并经常更新的单元格。我想在单元格值更新时触发宏。

我相信这类似于程序或任何外部数据更新的单元格值更改,但以上示例对我不起作用。我认为问题在于没有触发excel内部事件,但这是我的猜测。

我做了以下,

Private Sub Worksheet_Change(ByVal Target As Range) 
  If Not Intersect(Target, Target.Worksheets("Symbols").Range("$C$3")) Is Nothing Then
   'Run Macro
End Sub

【讨论】:

由于某种原因我无法让它工作。当我告诉代码在 VBA 中运行时,它会弹出一个菜单并询问我是否要运行宏而不是自动运行宏?【参考方案5】:

在真正搞砸了事件触发器之后,我花了很多时间研究这个并了解它是如何工作的。由于信息非常分散,我决定将我发现的所有内容都分享在一个地方,一步一步如下:

1) 打开 VBA 编辑器,在 VBA 项目 (YourWorkBookName.xlsm) 下打开 Microsoft Excel 对象并选择更改事件将涉及的工作表。

2) 默认代码视图是“常规”。从顶部中间的下拉列表中,选择“工作表”。

3) Private Sub Worksheet_SelectionChange 应该已经存在,不要管它。从上面复制/粘贴 Mike Rosenblum 的代码并将 .Range 引用更改为您正在观察更改的单元格(在我的情况下为 B3)。但是,不要放置您的宏(我在“然后”之后删除了“宏”这个词):

Private Sub Worksheet_Change(ByVal Target As Range)
    If Not Intersect(Target, Me.Range("H5")) Is Nothing Then
End Sub

或从左上角的下拉列表中选择“更改”,然后在 Private Sub 和 End Sub 之间的空白处粘贴If Not Intersect(Target, Me.Range("H5")) Is Nothing Then

4) 在“Then”之后的行中关闭事件,这样当您调用宏时,它不会触发事件并尝试在永无止境的循环中再次运行此 Worksheet_Change,这会导致 Excel 崩溃和/或以其他方式将一切搞砸:

Application.EnableEvents = False

5) 调用你的宏

Call YourMacroName

6) 重新开启事件,以便下一次更改(以及任何/所有其他事件)触发:

Application.EnableEvents = True

7) 结束 If 块和 Sub:

    End If
End Sub

整个代码:

Private Sub Worksheet_Change(ByVal Target As Range)
    If Not Intersect(Target, Me.Range("B3")) Is Nothing Then
        Application.EnableEvents = False
        Call UpdateAndViewOnly
        Application.EnableEvents = True
    End If
End Sub

这会从模块中打开/关闭事件,这会产生问题,并且只是让更改触发、关闭事件、运行宏并重新打开事件。

【讨论】:

以上是关于在单元格更改时自动执行 Excel 宏的主要内容,如果未能解决你的问题,请参考以下文章

MS Excel - 如何每 5 秒自动刷新一次单元格?

Excel:更改单元格时运行宏

Excel在单元格按回车触发宏问题

如何在复制/粘贴后禁用 Excel 自动单元格引用更改?

Excel VBA - 基于活动单元格运行宏

根据excel中的下拉列表自动填充单元格