Excel 关闭不同工作簿将结束当前工作簿的代码执行
我正试图在Excel 关闭不同工作簿将结束当前工作簿的代码执行,excel,vba,Excel,Vba,我正试图在Book1.xlsm中运行foo,它在Book2.xlsm中运行另一个子项bar。以下是两者的代码: 在第1册中: Sub foo() Dim oldBook As Workbook: Set oldBook = ActiveWorkbook Dim newBook As Workbook: Set newBook = Workbooks("Book2.xlsm") Application.Run "'Book2.xlsm'!Module1.bar", old
Book1.xlsm
中运行foo
,它在Book2.xlsm
中运行另一个子项bar
。以下是两者的代码:
在第1册中:
Sub foo()
Dim oldBook As Workbook: Set oldBook = ActiveWorkbook
Dim newBook As Workbook: Set newBook = Workbooks("Book2.xlsm")
Application.Run "'Book2.xlsm'!Module1.bar", oldBook
End Sub
第二册:
Sub bar(book As Workbook)
book.Close False
Debug.Print "Closed Workbook!"
MsgBox "Closed workbook!"
End Sub
foo
的执行运行良好,控件被传递到Book2.xlsm
中的bar
。行book.Close false
运行正常(关闭Book1.xlsm
),但代码执行立即停止,没有任何警告(控制台或弹出窗口中没有消息)。既然控件被传递到了bar
,那么这两行不是都应该在Book2.xlsm
中执行吗
我通过调用条形工作簿(1)
(工作簿(1)=Book1.xlsm
)尝试了这一点,整个代码运行良好,正如预期的那样。难道不应该发生同样的事情吗
如何在第一个场景中保持代码执行,即运行
foo
运行bar
,更改工作簿,关闭Book1.xlsm
并继续执行bar
?您可以使用Application.OnTime完成此任务
Book2.xlsm
Public wb As Workbook
Public Sub bar(book As Workbook)
'set the variable for the workbook we want to close - We do this because we cannot pass a workbook object
Set wb = book
'set it to call 1 second from now
Application.OnTime DateTime.DateAdd("s", 1, DateTime.Now), "CloseIt"
End Sub
Sub CloseIt()
wb.Close False
Debug.Print "Closed Workbook!"
MsgBox "Closed workbook!"
End Sub
重新考虑谁对什么负责。给工作簿一个随机的
workbook
对象,然后继续关闭它,这是不正常的
当然,您可以绕过这样一个事实,即您实际上是在关闭调用堆栈的所有者,但问题的根源是,当您有WorkbookA
负责执行某项操作,并且某项操作涉及打开或创建WorkbookB
时,然后,WorkbookA
有责任在完成后关闭WorkbookB
Book2
没有关闭任何内容的业务。假设真正的宏实际上做的不仅仅是关闭它,那么它应该做它自己的事情,然后让调用者决定是关闭工作簿还是保持工作簿打开<代码>第二册!条形码被赋予了一个它不拥有的资源:关闭该资源超出了它的责任范围
也许这可以作为一个简单的例子:
Public Sub DoSomething()
Set t = New Thing
UseTheThing t
t.SomeMethod ' error 91: object reference is gone!
End Sub
Private Sub UseTheThing(ByRef t As Thing)
t.Foobar 42
Set t = Nothing ' not your job!
End Sub
围绕事物的自然顺序(调用者->被调用者->返回调用者)工作既不推荐也不有用。从更大的角度来看,有些东西被破坏了-后退一步,修复更高的级别,而不是与整个范例抗争。因为foo()是堆栈上的调用方,一旦关闭,它的所有子进程都将关闭,这是有意义的。至于我问题的第二部分,如果首先关闭了原始工作簿,我如何继续使用bar
?为什么不关闭第1册中的第1册?在运行第2册中的代码并将控制权转移回第2册之后,不要像这样断章取义。负责打开资源的代码/工作簿(无论是工作簿、文件、数据库连接、任何东西)都应该是负责关闭该资源/清理的代码。如果需要在应用程序级别上运行代码和控制事项,请考虑制作Excel外接程序。这样,您就得到了一个“总体”组件,可以协调谁可以做什么。