Excel单元格更改时调用自定义的VBA函数

我想先说这个问题,说我是大学里的一个知道C ++的大学生,对VBA有一个非常基本的理解。

现在,正如标题所述,我需要一些帮助为Excel工作表configuration一些VBA代码,以便每当某列(特别是D列)中的单元格被修改时,它将自动更新同一行内的其他单元格。

基本上我想这样工作,以便当用户鲍勃修改单元格D26(例如)时,它将调用我build立的自定义函数,并将该代码插入单元格B26,然后重复使用单元格C26不同的function。

但是,这个函数必须是这样的:如果单元格D27被修改,它将只修改第27行中的其他单元格,只保留第26行以及之前或之后的行,直到在D28中调用此函数为止,等等。

我不完全确定这是否可能,但如果有人能帮我configuration这个,我会很有礼貌。

我为自定义函数从互联网上构build/清理的代码是: http : //pastebin.com/RE0V2nrT

我想调用这个项目的第二个函数是Excel中内置的= TODAY()函数。

我已经拼凑到目前为止检查单元格是否已经改变的代码是这样的: http : //pastebin.com/S5E8cmty

如果有人能帮助我理解如何编写我正在寻找的东西,将不胜感激。 如果你有不同的方法来解决这个问题,我也很乐意听到…只要你能帮助我,然后制定你的解决scheme,哈哈!

无论如何,多亏了谁回复。

查看Excel命名空间中可用的工作表事件 。 为此,您将使用更改事件

如果双击要监视的工作表,则可以插入Worksheet_Change子项。 然后,您可以使用交叉函数来检查更改的单元格是否在您要监视的范围内(例如D:D)。

您可以指定要更改的单元格。 这里我只是根据你提出的问题举了一个例子。 这将把你的函数的输出放到单元格B [R]中,并把当前date放到单元格C [R]中。 请注意,因为在VBA中没有Today()函数,所以使用的是Now()函数。 既然这返回date和时间,我使用格式函数来获取date。

为了好玩,让我们进一步深入对象模型,首先获取目标范围所属的Worksheet对象 。 这不是100%必要的 – 你可以依靠ActiveSheet 。 现在,您可能不需要这样做,而且大多只是为了好玩,但是值得注意的是,如果您是以编程方式对此工作表进行更改,但尚未先激活此工作表(因此另一个工作表处于活动状态),并且你还没有closuresEnableEvents你会得到一些奇怪的结果:)

 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 

说明

工作表更改子是这样声明的。 工作表对象具有事件的预定义方法存根。 有点像一个接口,虽然没有在文档中列为接口。 如果你想到这个概念,这是你的事件握手。 查看我上面发布的链接,了解可用的工作表事件列表。
Private Sub Worksheet_Change(ByVal Target As Range)

在接下来的几行中,我们得到了名为Target的对象所属的工作表对象。 您可以在子声明中看到Target已声明为Rangetypes的对象。 如果你签出工作表对象(上面链接)或Range对象文档,你会发现范围对象是工作表对象的成员,这里的文档types很烂,但FYI工作表对象包含在父对象财产 。 现在,我最初的代码是使用Application对象的ActiveSheet成员 – 但是我已经按照上面的答案给出了原因。

 Dim TargetSheet As Worksheet Set TargetSheet = Target.Parent 

我使用Blocks来保存在多个地方input相同的工作表参考。 With块通过键入.SomeMember可以访问指定名称空间的成员(在本例中为TargetSheet对象的TargetSheet )。 编译器明白,像这样的每一个引用指的是在开头With ....语句中指定的任何引用。 我个人喜欢这个可读性,但我也推荐它维护(更改参考一个地方比很多)。 也有一个单一的参考提供了一个微小的,微不足道的,可能不值得一提的性能提升多个参考以及。

With TargetSheet

接下来我们检查Target是否在我们想要观察的单元格范围内。 If....Then应该看起来很熟悉。 对于我们的条件,我们使用布尔运算符不检查交叉函数的结果(上面链接)是否为Nothing 。 我们这样做的原因是检查是否分配了回报。 如果一个对象被分配了Not SomeObject Is Nothing条件将评估为False 。 如果对象没有被分配(即我们的相交函数没有返回任何东西),那么语句的计算结果为True 。 因此,从Intersect函数文档中我们知道,如果我们的返回被分配,范围相交并且返回相交范围对象。 因此,如果我们想知道它们是否相交,我们可以检查相反的一个失败。

If Not Application.Intersect(Target, .Range("D:D")) Is Nothing Then

接下来的行然后在与Target相同的行内的单元格上执行一些代码。 我们使用工作表对象的单元格成员来指定要修改的单元格。 根据文档, Cells的默认属性是Item ,它允许我们像下面这样通过行和列索引访问一个范围对象: .Cells[Row,Column] 。 所以,我简单地使用我们的Target对象的行和你想要的列(列“A”= 1,“B”= 2等,如果你感兴趣,可以通过将excel属性更改为R1C1引用样式来查看。

.Cells(Target.Row, 2) = ExtractWindowsUser()

我认为Format()和Now()函数在文档中有很好的解释。