如何在特定的工作表中运行宏,但根据另一个Excel文件/工作表中维护的值控制启动



嗨,

如何在特定工作表的后台运行宏,并且仅使用和控制基于另一Excel文件/工作表中维护的计算值的宏触发器?用例是,我想运行一个名为"TargetCalc"的宏,它会触发特定工作表中的Marcro_01或Marcro_02,具体取决于该工作表中单元格C3的值是1还是2。

如果所有内容都在活动Excel工作表本身中进行维护或计算,则下面的宏示例效果良好。但是,如果我想从我打开的另一个Excel文件(我的焦点所在)控制Cell C3中的值,那么我会收到错误消息"运行时错误'9':订阅超出范围">

测试设置:

  1. 保存名为"DisplayExcelFile.xlsm"的Excel文件,并将"Sheet1"重命名为"DisplaySheet1">
  2. 复制下面的VBA代码
  3. 在文件"DisplayExcelFile.xlsm"-单元格C3中,输入:=IF(D3<100,1,2)
  4. 在文件"DisplayExcelFile.xlsm"-单元格D3中,输入值105

结果:

a) 单元C3将显示2,因为单元D3是大于100的105=>Macro_01触发

b) 如果手动将Cell D3从105更新为78=>Macro_02被触发到目前为止一切都很好,这个例子也很好。

  1. 在同一台机器上打开第二个Excel,将"Sheet1"重命名为"CalcSheet",并将该Excel文件保存为"CalcFromExcelFile.xlsm">
  2. 在文件"CalcExcelFile.xlsm"-单元格A2中,输入值130
  3. 下一步:在同一台机器上打开两个Excel文件,返回第一个Excel文件"DisplayExcelFile.xlsm"单元格D3,将单元格D3从值(105或78…)更改为引用另一个打开的Excel文件中另一个单元格A2的公式:=[CalcFromExcelFile.xlsm]CalcSheet$A 2美元

结果:

a) 只要"焦点"位于第一个"DisplayExcelFile.xlsm"中名为"DisplaySheet1"的工作表内,则在使用不同编号更新单元格D3时,该功能即可正常工作。

b) 但是:如果您在第二个Excel文件"CalcExcelFile.xlsm"中有"焦点",并将第二个Excel文件中的单元格A2更新为值97——那么第一个"DisplayExcelFile.xllm"中的工作表"DisplaySheet1"中的宏将不起作用。

弹出的VBA错误显示:运行时错误"9":订阅超出范围

当我"调试"时,它指向Macro_01的行:"工作表("DisplaySheet")。范围("A3")。选择">

此外:

  • 我所追求的工作流程是在同一台机器上打开两个Excel文件——第一个Excel文件"DisplayExcelFile.xlsm"用于显示和运行宏——但所有手动更新(重点)都在第二个Excel文件"CalcFromExcelFile.xlsm"上
  • 在第一个"DisplayExcelFile.xlsm"中,工作表将始终命名为"DisplaySheet1",因此无需修改代码,以便在重命名工作表时工作。我希望当我使用这个用例时,我会在同一个First Excel文件中创建第二个和第三个工作表("DisplaySheet2"one_answers"DisplaySheet2-"),这样我也可以为这些工作表复制同样的东西
  • 当我试图让VBA代码工作时——我试图直接引用图纸名称——我也试图提高"选择"的使用率,但我被卡住了

代码

模块1

Option Explicit
Public TargetValue As Variant
Private Const cTarget As String = "C3"
Sub TargetCalc(ws As Worksheet)
'
If ws.Range(cTarget) <> TargetValue Then
Application.EnableEvents = False
Select Case ws.Range(cTarget).Value
Case 1
Macro_01
Case 2
Macro_02
End Select
TargetValue = ws.Range(cTarget).Value
Application.EnableEvents = True
End If
End Sub
Sub Macro_01()
'
Worksheets("DisplaySheet").Range("A3").Select
ActiveCell.FormulaR1C1 = "Hi_01"
Application.Wait Now + TimeValue("0:00:01")
ActiveCell.FormulaR1C1 = "There_01"
End Sub
Sub Macro_02()
'
Worksheets("DisplaySheet").Range("A3").Select
ActiveCell.FormulaR1C1 = "Hi_02"
Application.Wait Now + TimeValue("0:00:01")
ActiveCell.FormulaR1C1 = "There_02"
End Sub

Sheet1(DisplaySheet)

Option Explicit
Private Sub Worksheet_Calculate()
TargetCalc Me
End Sub

本工作簿

空的

非常感谢!

不要选择任何东西,[几乎]永远不要。如果你告诉VBA地址,VBA就会找到它。因此,你需要非常小心地对工作簿和工作表进行排序。我通常在开始编程之前执行此操作。这就是为什么您可以在下面的代码顶部找到这些定义。

不要担心图纸名称。左侧的第一个选项卡始终为Worksheets(1)。你可以通过它的索引号来称呼它。我想你可能会坚持使用";DisplaySheet1";在显示手册中,但使用计算工作簿中的索引。重点是:准确识别工作簿和工作表。请注意,工作表一旦用Set语句定义,就知道它所属的工作簿,您可以用"Ws.workbook.name"检索该工作簿的名称。

请注意,ThisWorkbook标识代码所在的工作簿,而ActiveWorkbook是具有焦点的工作簿。它们可以是相同的,但不一定是相同的。

不要为宏数字而烦恼。相反,学习争论。一个基本上只做一项工作的宏,如macro_01和macro_02,可以组合成一个宏,并将1或2作为参数提供。

下面的代码将帮助您。

Option Explicit
Sub Main()
' 149

Dim WsDisplay           As Worksheet
Dim WsCalc              As Worksheet
Dim Arg                 As String

Set WsDisplay = ThisWorkbook.Sheets(1)
Set WsCalc = ActiveWorkbook.Sheets(1)

If WsDisplay.Cells(3, "D").Value < 100 Then
Arg = 1
Else
Arg = 2
End If
'    ' Note: I would use the following in place of the above
'    '       because it's only a single line
'    Arg = 2 + (WbDisplay.Worksheets(1).Cells(3, "D").Value < 100)

Action WsDisplay, Arg
End Sub
Private Sub Action(WsDisplay As Worksheet, _
ByVal Switch As Integer)
' 149
Dim Target              As Range
Dim Txt                 As String

Select Case Switch
Case 1
Set Target = WsDisplay.Cells(3, 1)     ' 1 = column A
Txt = "Hi"
Case 2
Set Target = WsDisplay.Cells(3, 2)     ' 2 = column B
Txt = "Hello"
Case Else
MsgBox "Invalid switch"
Exit Sub
End Select

With Target
.Value = Txt
.Offset(1).Value = "there!"
End With
End Sub

Main过程中查找工作表和工作簿定义。设计是让CalcSheet成为活动的CalcSheet,但在代码的后面,该工作表永远不会被使用。所有操作都在非活动的DisplaySheet上。

Macro_01和Macro_02需要知道他们在操作哪个工作簿。

例如:

Sub Macro_01()
With ThisWorkbook.Worksheets("DisplaySheet").Range("A3")
.Value = "Hi_01"
Application.Wait Now + TimeValue("0:00:01")
.Value = "There_01"
End With
End Sub