Issue : 我遇到的问题是,如果我尝试从另一个工作簿关闭工作簿,代码将停止运行 .
这个问题已经在几个帖子中暴露过,但似乎没有解决方案 .
What I am trying to do :
-
我在工作簿WB1.xlsm中有一个名为"Code1"的代码,它按以下方式打开WB2
Workbooks.Open("WB2.xlsm").RunAutoMacros(xlAutoOpen)
-
Auto_Open代码格式WB2现在正在运行,我在WB2中执行操作(复制数据),然后目标是将这些数据粘贴到WB3中并关闭WB1,以便在WB2的Auto_Open代码结束时继续执行以下操作在跳入WB3之前:
For Each wbk In Workbooks
If wbk.Name = "WB1.xlsm" Then
'wbk.Activate
'DoEvents
'ActiveWorkbook.Close False
wbk.Close False
'Application.OnTime Now + TimeValue("00:00:01"), "wbk.Close"
End If
Next
Workbooks.Open(PathTo_WB3).RunAutoMacros (xlAutoOpen)
问题是代码在关闭WB1后停止(上面你可以看到关闭它的不同尝试,但它们都失败了......)
Question : 实际上是否可以在不看到代码停止的情况下从另一个工作簿中关闭工作簿?
3 回答
这是正常行为 . 因为WB2的自动运行是在打开WB2的WB1中的子的上下文内 . 如果在WB2的自动运行中关闭WB1,则会立即终止该上下文,从而立即停止运行 .
解决方法可能是隐藏WB1而不是关闭(例如最小化) . 并运行WB1关闭作为WB2中自动运行的最后一个动作 . 这仍然会中止WB2的自动运行,但这并不重要,因为它是最后一个动作 .
所以WB1是WB2的来电者 . 这是一个黄金法则:
打开文件的人应该负责关闭它 .
这条黄金法则适用于编程中的许多东西,如果你从中衍生出来,那么你将会遇到许多问题 .
创造一个物体的人应该负责摧毁它 .
分配资源的人应该负责解除分配资源 .
......
所以你有一个名为
WB1.xlsm
的文件,其中包含正在运行的代码 - 就执行上下文而言,WB1是ThisWorkbook
.所以
ThisWorkbook
这样做:这假定文件成功打开,并丢弃了您实际需要的珍贵对象引用......非常糟糕 . 把它改成这个:
现在
WB2
中的自动程序可以做任何他们喜欢的事情, except attempt to close WB1 .所以
WB2
的automacro打开WB3
- 因此WB2
也应该负责关闭WB3
,因为它负责打开它 - 在WB2.xlsm
你将有一个Workbook_BeforeClose
处理程序,以确保WB3与WB2一起关闭 . 或者其他什么 - 它's not clear at all why you would need an automacro to do this, or why WB1 can' t只是打开WB2和WB3 .只记住你的执行上下文/调用堆栈(调用源自WB1,所以直到执行返回到WB1你有待处理的东西),并记住VBA代码存在于主机文档中 - 如果你关闭该文档,代码就不再存在 .
确保使用OnTime方法调用WB2中的代码 . 假设您要启动的WB2中的例程称为ContinueOpen: