我有一个工作表(sheet1)
,其中包含带有公式A1
的单元格='sheet2'!D10
。我想每次A1
中的单元格sheet1
变化时运行一个宏(由于D10
中sheet2
中的变化)。 sheet2
正在流式传输财务数据。
由于它是值的更改,因此Worksheet_Change
不会触发事件。我似乎也找不到Worksheet_Calculate
的解决方案。
在我的研究中,提供了我能找到的最接近的解决方案here,但我无法成功实现它。
答案 0 :(得分:0)
您将不得不使用Worksheet_Calculate。尚不清楚“流”是否会触发Sheet2中的Worksheet_Calculate,但如果您将计算设置为自动,则Sheet1中的链接单元格肯定会触发该工作表的私有代码表中的Worksheet_Calculate。
您需要一个变量,该变量将保存Sheet1!A1的先前值,该值可以与Sheet1!A1的当前值进行比较。一些人更喜欢使用在公共模块的声明区域中声明的公共变量。我更喜欢在Sheet1的Worksheet_Calculate本身中使用静态变量。
通常,过程一旦停止,过程中的局部变量将不复存在。静态变量继续存在并保留其最新值。下次您的代码调用该过程时,该变量不会重新初始化,并且仍保留您为其分配的最新值。静态变量在定义它的类或模块的生存期内一直存在。
第一个问题是为静态变量的首次使用植入种子。当使用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