单元格值更改时自动执行VBA宏

时间:2018-10-27 20:37:30

标签: excel vba

我有一个工作表(sheet1),其中包含带有公式A1的单元格='sheet2'!D10。我想每次A1中的单元格sheet1变化时运行一个宏(由于D10sheet2中的变化)。 sheet2正在流式传输财务数据。

由于它是值的更改,因此Worksheet_Change不会触发事件。我似乎也找不到Worksheet_Calculate的解决方案。

在我的研究中,提供了我能找到的最接近的解决方案here,但我无法成功实现它。

2 个答案:

答案 0 :(得分:0)

您将不得不使用Worksheet_Calculate。尚不清楚“流”是否会触发Sheet2中的Worksheet_Calculate,但如果您将计算设置为自动,则Sheet1中的链接单元格肯定会触发该工作表的私有代码表中的Worksheet_Calculate。

您需要一个变量,该变量将保存Sheet1!A1的先前值,该值可以与Sheet1!A1的当前值进行比较。一些人更喜欢使用在公共模块的声明区域中声明的公共变量。我更喜欢在Sheet1的Worksheet_Calculate本身中使用静态变量。

Microsoft Docs

  

通常,过程一旦停止,过程中的局部变量将不复存在。静态变量继续存在并保留其最新值。下次您的代码调用该过程时,该变量不会重新初始化,并且仍保留您为其分配的最新值。静态变量在定义它的类或模块的生存期内一直存在。

第一个问题是为静态变量的首次使用植入种子。当使用IsEmpty测试时,从未给过变量类型变量的值报告为True,因此,当第一次打开工作簿时,第一个计算周期将简单地将Sheet1!A1的值记录到静态var中。以后的任何计算周期都将Sheet1!A1中的值与静态var中的值进行比较,如果它们不同,则外部子过程('...运行宏...'将以您的问题的叙述形式运行),Sheet1!A1的新值将存储在静态变量中。这样,Sheet1!A1中公式返回的值的任何更改都会强制执行计算周期,因此工作表的Worksheet_Calculate事件子过程将依次运行您的外部子过程。

In Sheet1's private code sheet

Option Explicit

Private Sub Worksheet_Calculate()

    Static s2d10 As Variant

    If IsEmpty(s2d10) Then
        'load static var with expected value
        s2d10 = Cells(1, "A").Value2
    ElseIf s2d10 <> Cells(1, "A").Value2 Then
        'run sub procedure here
        '... run a macro ...'

        'load A1's current value into the static var
        s2d10 = Cells(1, "A").Value2
    End If

End Sub

答案 1 :(得分:0)

选择更改和更改

我朝一个不同的方向迷路了。我认为这里可能有一些有用的东西,所以这里还是代码。它可能在大多数情况下都可以工作,只是丢失了' str1 '行。

' str1 '行用于调试目的,显示单元在不同条件下的行为。

不确定子ChangeD10是否在模拟您的条件。

扔掉毛巾,但希望能指出代码中的错误。

Option Explicit

Private TargetValue As Variant
Private TargetAddress As String

Private Sub Worksheet_Change(ByVal Target As Range)

  'The Playground
  Const cStrWs1 As String = "Sheet1"
  Const cStrWs2 As String = "Sheet2"
  Const cStrCell1 As String = "A1"
  Const cStrCell2 As String = "D10"
  'Other Variables
  Dim oWs1 As Worksheet
  Dim oWs2 As Worksheet
  Dim oRng As Range
  Dim varA1_Before As Variant
  Dim varA1_Now As Variant
  'Debug
  Const r1 As String = vbCr
  Dim str1 As String
  'Initialize
  Set oWs1 = ThisWorkbook.Worksheets(cStrWs1)
  Set oWs2 = ThisWorkbook.Worksheets(cStrWs2)
  Set oRng = oWs2.Range(cStrCell2)
  varA1_Before = oWs1.Range(cStrCell1).Value

            str1 = "Worksheet_Change"

  'Play
  If Target.Address = oRng.Address Then
    If Target.Value <> TargetValue Then
      varA1_Now = oWs2.Range(cStrCell2).Value
      oWs1.Range(cStrCell1).Value = varA1_Now

            str1 = str1 & r1 & Space(1) & "Cell '" & cStrCell2 & "' changed " _
                & "(Target.Value <> TargetValue)" & r1 & Space(2) _
                & "Before: TargetValue (" & TargetAddress & ") = '" _
                & TargetValue & "'," & r1 _
                & "         varA1_Before (" & Range(cStrCell1).Address _
                & ") = " & varA1_Before & "'," & r1 & Space(2) _
                & "Now:   Target.Value (" & Target.Address & ") = '" _
                & Target.Value & "'," & r1 _
                & "            varA1_Now (" & Range(cStrCell1).Address _
                & ") = " & varA1_Now & "'."

     Else

            str1 = str1 & r1 & Space(1) & "Cell '" & cStrCell2 _
                & "' didn't change. TargetValue = '" & TargetValue _
                & "' and Target.Value = '" & Target.Value & "'."

    End If
   Else

            str1 = str1 & r1 & Space(1) & "Cell '" & cStrCell2 _
                & "' not changed. The Target.Address is '" _
                & Target.Address & "', TargetValue is '" & TargetValue _
                & "' and Target.Value is '" & Target.Value & "'."

  End If

            Debug.Print str1

End Sub

Private Sub Worksheet_SelectionChange(ByVal Target As Range)

  Const r1 As String = vbCr
  Dim str1 As String

            str1 = "Worksheet_SelectionChange"

  If Target.Cells.Count = 1 Then

            str1 = str1 & r1 & Space(1) & "Cell '" & Target.Address _
                & "' selected " & r1 & Space(2) _
                & "Before: TargetValue (" & TargetAddress & ") = '" _
                & TargetValue & "'," & r1 & Space(2) _
                & "Now:    Target.Value (" & Target.Address & ") = '" _
                & Target.Value & "'."

    TargetValue = Target.Value
    TargetAddress = Target.Address

   Else
            str1 = str1 & r1 & Space(1) & "Multiple cells in range '" _
                & Target.Address & "'."
  End If

  Debug.Print str1

End Sub

Sub ChangeD10()
  ThisWorkbook.Worksheets("Sheet2").Cells(10, 4) = 22
End Sub