查看 Excel 命名空间中可用的 worksheet events。
为此,您将使用Change event
如果您双击要监控的工作表,您可以插入一个Worksheet_Change 子。然后您可以使用intersect function 检查更改的单元格是否在您要监控的范围内(例如 D:D)。
您可以指定要更改的单元格。在这里,我只是根据您的要求举了一个例子。这会将函数的输出放入单元格 B[R] 并将当前日期放入单元格 C[R]。请注意,我使用的是 Now() 函数,因为 VBA 中没有 Today() 函数。因为这会返回日期和时间,所以我使用 Format 函数来获取日期。
为了好玩,让我们再深入一点对象模型,首先获取目标范围所属的Worksheet object。这不是 100% 必要的 - 你可以只依赖 ActiveSheet。现在,您可能不需要这样做,这主要是为了好玩,但还值得注意的是,如果您以编程方式更改此工作表,但没有先激活此工作表(因此另一个工作表处于活动状态)和你没有关闭EnableEvents 你会得到一些奇怪的结果:)
Private Sub Worksheet_Change(ByVal Target As Range)
Dim TargetSheet As Worksheet
Set TargetSheet = Target.Parent
With TargetSheet
If Not Application.Intersect(Target, .Range("D:D")) Is Nothing Then
.Cells(Target.Row, 2) = ExtractWindowsUser()
.Cells(Target.Row, 4) = Format(Now(), "YYYY-MM-DD")
End If
End With
End Sub
说明
Worksheet change sub 是这样声明的。 Worksheet 对象具有用于事件的预定义方法存根。有点像一个接口,虽然没有在文档中列为接口。如果您在该概念中考虑它,这就是您的事件握手。 有关可用工作表事件的列表,请参阅我在上面发布的链接。
Private Sub Worksheet_Change(ByVal Target As Range)
在接下来的几行中,我们将获取名为Target 的对象所属的工作表对象。您可以在子声明中看到Target 被声明为Range 类型的对象。如果您查看 Worksheet 对象(上面链接)或Range object 文档,您会看到范围对象是工作表对象的成员,并且这里的文档有点糟糕,但仅供参考,工作表对象包含在Parent property。 现在,最初我的代码使用 Application 对象的 ActiveSheet 成员 - 但出于上述答案中给出的原因,我已经对其进行了编辑。
Dim TargetSheet As Worksheet
Set TargetSheet = Target.Parent
我使用With Blocks 来节省在多个位置键入相同的工作表引用。 With 块只允许我通过键入.SomeMember 访问指定命名空间的成员(在本例中为对象TargetSheet 的成员)。编译器理解每个像这样的引用都指的是在开头的With .... 语句中指定的任何内容。我个人喜欢这样的可读性,但我也推荐它进行维护(更改引用一个地方与多个地方)。同样,拥有一个引用也会带来微小的、微不足道的、可能不值得一提的对多个引用的性能提升。
With TargetSheet
接下来我们检查Target 是否在我们想要观察的单元格范围内。 If....Then 应该看起来很熟悉。对于我们的条件,我们使用boolean operator Not 来检查相交函数(上面链接)的结果是否为Nothing。我们这样做的原因是检查是否分配了回报。如果分配了一个对象,则Not SomeObject Is Nothing 条件将评估为False。如果对象未分配(即我们的 Intersect 函数未能返回任何内容),则该语句的计算结果为 True。因此,从 Intersect 函数文档中我们知道,如果我们的 return 被分配,则范围相交并且相交范围对象被返回。因此,如果我们想知道它们是否相交,我们可以只检查失败的反面。
If Not Application.Intersect(Target, .Range("D:D")) Is Nothing Then
接下来的几行只需在与Target 相同的行中的单元格上执行一些代码。我们使用工作表对象的Cells 成员来指定要修改的单元格。根据文档,Cells 的默认属性是Item,它允许我们通过如下的行和列索引访问范围对象:.Cells[Row,Column]。因此,我只需使用我们的Target 对象的行和您想要的列(列“A”=1、“B”=2 等。如果您有兴趣,可以通过将 excel 属性更改为 R1C1 引用样式来看到这一点)。
.Cells(Target.Row, 2) = ExtractWindowsUser()
我认为Format() 和 Now() 函数在文档中得到了很好的解释。