当某些单元格在Excel中更改但从我的个人工作簿更改时运行宏

时间:2013-08-05 21:18:50

标签: excel vba

问题:我发现了许多帖子(包括微软自己的支持网站),其中包含有关在Excel中某些单元格更改时如何运行宏的信息。我可以让它工作,但我需要将该子存储在我的Personal.xlsb工作簿中,并使其影响另一个工作簿中的命名工作表。

背景:我经常从第三方收到一个Excel文件,并在其上运行一系列例程,所有宏都存储在我的Personal.xlsb隐藏工作簿中。部分过程要求我“撤消”用户在特定单元格中输入日期时自动进行的许多格式更改。一旦用户在任何给定的5个工作表上指定的单元格中创建日期条目,我想在5个单独的工作表上调用这些“撤消”子。但是,我已经在线阅读的所有帮助都让我将代码添加到需要进行更改的确切工作表中。我想将该代码存储在我的个人工作簿中的模块中,以便它可以在包含工作表名称的任何工作簿上运行...类似于我的其他查询的布局方式。

到目前为止

代码

Private Sub Worksheet_Change(ByVal Target As Range)
    Dim KeyCells As Range
    Set KeyCells = Range("W9")

    If Not Application.Intersect(KeyCells, Range(Target.Address)) Is Nothing Then
        MsgBox "You changed THE CELL!"
    End If
End Sub

问题:如何修改sub以使其在包含指定工作表的所有工作簿中生效?或者在那里的某个地方有更好的选择吗?

1 个答案:

答案 0 :(得分:0)

由于我遇到了同样的问题,我通过Chip Pearson的指示工作,并将为您提供更全面的指南。

我也非常鼓励您通过Chip Pearson's great summary了解事件。我知道要消化很多,但它会帮助你理解我们在这里做的事情。

概述,这些是我们要执行的步骤:

  1. 为我们的事件处理程序添加一个类模块(这是实际的事件处理代码所在的位置)
  2. 为我们的 personal.xlsb ThisWorkbook模块添加一个事件处理程序,以连接我们的事件处理程序类
  3. 享受无限的事件处理循环,因为我们更改了Target.Value: - P(可选
  4. 让我们开始。

    1。添加一个类模块

    首先,我们需要创建一个舒适的广告来放置我们所有的事件处理程序。我们将使用类模块,因为它提供了一些很好的结构,您可以立即知道在哪里查找应用程序级事件处理程序。

    personal.xlsb的VBA项目中,通过在项目浏览器中右键单击创建一个新类 - > 插入 - > 类模块

    通过更改属性窗格中的名称,将类重命名为 CAppEventHandler

    将下面列出的源代码(设置部分和事件处理部分)添加到刚刚创建的类中。 (请务必阅读评论,因为他们会为我们正在做的事情和原因添加一些其他信息。

    2。添加初始化事件处理程序

    现在我们需要确保我们的事件处理程序已被激活"当我们打开personal.xlsb时(所以当你打开Excel时):)。

    要执行此操作,请双击ThisWorkbook模块并添加以下代码。

    现在你已经很好了,可以测试你的事件处理。您必须事先做的事情(为了触发"布线"流程)重新启动Excel

    备注

    • 我在事件处理程序的开头添加了对当前工作表名称的检查 - 因此请确保您的工作表已命名为" MySheet" :)
    • 您可以在处理程序中设置断点,并像其他任何VBA代码一样在行动中查看
      

    并发出警告(又名 3.享受无限的事件处理循环
      当我测试这个时,如果我们在右侧工作表上更改了右侧单元格,我会天真地使用Target.Value = "It wooooorks!"作为要执行的代码。 那不好。
      请参阅最后一段代码(也来自Chip's post),了解如何防止此类事件循环。

    源代码

    CAppEventHandler类(设置)

    Option Explicit
    
    ' Declare our own reference to the Application object
    ' WithEvents is needed to capture the events of the application object
    ' (Note: The events 'bubble up' from the Worksheet to the Workbook and
    '        finally to the Application.
    '        So event handlers in the Sheet module are executed first
    '        (if any handlers are declared), then the ones in the Workbook
    '        module (again, if they are declared) and finally the ones
    '        in the Application module.)
    Private WithEvents App As Application
    
    ' Whenever a new object of a class is instantiated, the _Initialize-Sub is called,
    ' that's why we use this Sub to get the reference to the current Application object
    Private Sub Class_Initialize()
        Set App = Application
    End Sub
    

    CAppEventHandler类(实际事件处理)

    ' Here is the actual code executed whenever the event reaches the Application level
    ' (see above for the order of 'bubbling up' of the events) and hasn't been marked
    ' as handled before
    Private Sub App_SheetChange(ByVal Sh As Object, ByVal Target As Range)
    
        If Sh.Name <> "MySheet" Then
            Exit Sub
        End If
    
        Dim rngKeyCells As Range
        Set rngKeyCells = Sh.Range("A5")
    
        If Intersect(rngKeyCells, Target) Is Nothing Then
            Exit Sub
        End If
    
        ' Do our actual work
        MsgBox "It wooooorks!", vbInformation
    
        ' Note: If you want to change the contents of your keyCells, you will
        '       have to make sure to prevent an infinite event loop (i.e. using
        '       Application.EnableEvents = False because otherwise changing
        '       the value in your macro will trigger the event again
    
    End Sub
    

    ThisWorkbook模块

    '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ' The following code must be placed in the "ThisWorkbook" module of your personal.xlsb
    '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Option Explicit
    
    Private OurEventHandler As CAppEventHandler
    
    Private Sub Workbook_Open()
        ' Since we declared so in our _Initialize-Sub this wire-up the current
        ' Application object in our EventHandler class
        Set OurEventHandler = New CAppEventHandler
    End Sub
    

    如何防止事件循环

    Private Sub Worksheet_Change(ByVal Target As Range)
        Application.EnableEvents = False
        Target.Value = Target.Value + 1
        Application.EnableEvents = True
    End Sub
    

    (来自Chip Pearson's comprehensive post on events