当单元格被公式更改时,VBA 代码不运行

Posted

技术标签:

【中文标题】当单元格被公式更改时,VBA 代码不运行【英文标题】:VBA code doesn't run when cell is changed by a formula 【发布时间】:2012-07-10 04:30:39 【问题描述】:

工作表 A 具有从 工作表 B 收集的数据范围。 工作表 A 有一个宏,用于计算数据是否高于某个值,然后调用电子邮件模块向选定的用户发送电子邮件。

当在工作表A上手动输入数据时,宏可以工作,但是当从工作表B中提取数据时,它不会触发。

我不确定我需要在 VBA 代码中进行哪些更改。

Private Sub Worksheet_Change(ByVal Target As Range)
    Call MailAlert(Target, "B5:M5", 4) 
    Call MailAlert(Target, "B8:M8", 7) 
    Call MailAlert(Target, "B11:M11", 6)
    Call MailAlert(Target, "B14:M14", 2) 
    Call MailAlert(Target, "B17:M17", 4) 
    Call MailAlert(Target, "B20:M20", 1) 
    Call MailAlert(Target, "B23:M23", 3) 
    Call MailAlert(Target, "B26:M26", 1) 
    Call MailAlert(Target, "B29:M29", 5) 
    Call MailAlert(Target, "B32:M32", 1) 
    Call MailAlert(Target, "B35:M35", 7) 
    Call MailAlert(Target, "B38:M38", 20) 
    Call MailAlert(Target, "B41:M41", 0) 
End Sub

Private Sub MailAlert(ByVal Target As Range, ByVal Address As String, ByVal Value As Integer)
    If Target.Cells.Count > 1 Then Exit Sub
    If Not Application.Intersect(Range(Address), Target) Is Nothing Then
        If IsNumeric(Target.Value) And Target.Value > Value Then
        Call Mail_small_Text_Outlook
        End If
        Application.EnableEvents = True
    End If
End Sub

【问题讨论】:

【参考方案1】:

要通过公式捕获更改,您必须使用Worksheet_Calculate() 事件。为了理解它是如何工作的,让我们举个例子。

    创建一个新工作簿。 在 Sheet1 单元格 A1 中,输入此公式=Sheet2!A1+1

现在在一个模块中粘贴这段代码

Public PrevVal As Variant

将此粘贴​​到工作表代码区域

Private Sub Worksheet_Calculate()
    If Range("A1").Value <> PrevVal Then
        MsgBox "Value Changed"
        PrevVal = Range("A1").Value
    End If
End Sub

最后在ThisWorkbook代码区粘贴此代码

Private Sub Workbook_Open()
    PrevVal = Sheet1.Range("A1").Value
End Sub

关闭并保存工作簿并重新打开它。现在对Sheet2 的单元格A1 进行任何更改。您会注意到您将收到消息框MsgBox "Value Changed"

快照

【讨论】:

如何在一系列单元格上使用它?【参考方案2】:

worksheet_change 事件只会在用户手动更改时触发。我认为您最好的选择是将其作为工作表 B 上的工作表更改事件来实现,我认为用户输入更改正在发生。

如果这真的不适合您,我会建议一些替代方案,但我认为这可能是迄今为止最好的选择。

编辑:以下 cmets 的另一个建议

ThisWorkbook 对象有一个事件 SheetChange,只要工作簿中的任何工作表发生更改,就会触发该事件。如果您可以确定将在每张 B 表上输入数据的范围,那么您可以像在原始代码中一样使用这些范围。

Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
    If Not Sh Is Sheets("Worksheet A") Then
        If Intersect(Sh.Range("B1:B5"), Target) Then
            'Call MailAlert as required here
        ElseIf Intersect(Sh.Range("B10:B20"), Target) Then
            'Call MailAlert as required here
        Else ' Etc...
            'Call MailAlert as required here
        End If
    End If
End Sub

让我知道这是怎么回事。

【讨论】:

有 12 个“工作表 B”(每个月),所以我会对您的其他建议感兴趣。澄清一下,工作表 A 将所有月份的工作表转换为易于阅读的格式。 所以工作表 A 中的公式类似于 =WorksheetJan!A1+WorksheetFeb!A2+WorksheetMar!A3... 等?我马上就要下班了,应该会在大约 1 小时后再次回复。 每个工作表 B 都有一组值,工作表 A 只需使用简单的 ='WorksheetB'!B31' 等来拉取它们 看起来不错,但是当指定范围内的值超过目标值时,如何调用 MailAlert 模块?我明天才能测试。 差不多了,它不调用 MailAlert 子。 (见原始代码贴)

以上是关于当单元格被公式更改时,VBA 代码不运行的主要内容,如果未能解决你的问题,请参考以下文章

Excel VBA 用户定义函数:在工作表函数中获取单元格被调用

将公式插入单元格 VBA Excel 时出现运行时错误 1004

当参考范围内的值发生变化时,VBA 更新公式

根据另一个单元格的值自动填充单元格,不带公式

更改单元格引用的 VBA 到 FillDown 公式

VBA将单元格内容分配为公式而不是其结果