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

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

背景 :我经常收到来自第三方的Excel文件,并在其上运行一系列例程,所有macros存储在我的Personal.xlsb隐藏工作簿中。 部分过程需要我“撤消”用户在特定单元格中inputdate时自动进行的许多格式更改。 只要用户在给定的5个工作表中指定的单元格中inputdate条目,我想在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 

问题 :如何修改子文件以便在包含指定工作表的所有工作簿中生效? 还是有一个更好的select,我在那里的某个地方?

由于我面临同样的问题 ,我按照Chip Pearson的指示开展工作,并为您提供更全面的指导。

我也可以鼓励你通过Chip Pearson关于事件的精彩总结来阅读你的方式。 我知道消化需要很多东西,但这会大大帮助你理解我们在这里所做的。

作为一个概述,这些是我们将要执行的步骤:

  1. 为我们的事件处理程序添加一个类模块(这是实际的事件处理代码将去的地方)
  2. 为我们的personal.xlsbThisWorkbook模块添加一个事件处理程序来连接我们的事件处理程序类
  3. 享受无限的事件处理循环,因为我们改变了Target.Value :-P( 可选

让我们开始吧。

1.添加一个类模块

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

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

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

将下面列出的源代码(设置部分和事件处理部分)添加到刚创build的类中。 ( 确保阅读评论,因为他们添加了一些额外的信息,我们正在做什么,为什么。

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

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

为此,请双击您的ThisWorkbook模块并添加下面的代码。

现在你已经很好了,可以testing你的事件处理。 事先您必须做的唯一事情(为了触发“接线”过程) 重新启动Excel

笔记

  • 我在事件处理程序的开头添加了对当前工作表名称的检查 – 所以请确保您的工作表被命名为“MySheet”:)
  • 您可以在处理程序中设置一个断点,并像其他任何VBA代码一样在动作中观察它

和一个警告 (又名3.享受无限的事件处理循环
当我testing这个,我天真地使用Target.Value = "It wooooorks!" 作为代码,如果我们改变了正确的单元格在右边的表格。 那不好。
查看最后一段代码(也取自Chip的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 (ie 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关于事件的综合post )