如何处理在另一个工作簿的Workbook_Open事件中生成的错误?

问题描述 投票:4回答:2

我在同一个文件夹中有两个工作簿:bkOpenErrorTest.xlsmbkOpenErrorTest_dict.xlsm

bkOpenErrorTest_dict.xlsm在其ThisWorkbook模块中具有以下代码:

Private Sub workbook_open()

Dim dict As Dictionary

Set dict = New Dictionary
dict.Add 0, 0
dict.Add 0, 0

End Sub

通过双击文件名打开此工作簿时,它会抛出预期的未处理错误:

This key is already associated with an element of this collection

bkOpenErrorTest.xlsm在Module1中有以下代码:

Sub testOpen()

Dim bk As Workbook

On Error GoTo errHandler

Workbooks.Open ThisWorkbook.Path & "\bkOpenErrorTest_dict.xlsm"

Exit Sub

errHandler:
Debug.Print "reached error handler"

End Sub

当错误捕获设置为Break on Unhandled Errors,并且我运行testOpen()时,当bkOpenErrorTest_dict.xlsm打开时,仍会引发未处理的错误。为什么testOpen()的错误处理程序没有捕获错误?我该如何处理这个错误?我有一个应用程序,我想循环遍历一个文件夹中的许多工作簿,这些文件夹在他们的workbook_open()事件中有这样的错误代码,如果程序在这样的未处理错误上崩溃,我无法迭代它们。

excel vba excel-vba exception-handling
2个回答
4
投票

不处理错误的原因是两个进程不在同一个线程中。如果从主子过程调用'helper'子过程,则保留在同一个线程中,并且'helper'中抛出的错误会被main中的错误控制捕获。这类似于为什么Application.Run启动的过程中的错误不会在启动它的过程中由错误控件处理抛出的错误。

要获得对新打开的工作簿的Workbook_Open中发生的事情的任何控制措施,您需要在Application实例级别上控制事物。以下内容将停止执行Workbook_Open事件过程;如果没有必要处理代码,那么这可能是你的解决方案。

Application.EnableEvents = False
Set bk = Workbooks.Open(ThisWorkbook.Path & "\bkOpenErrorTest_dict.xlsb")
Application.EnableEvents = True

如果“字典”填充是您尝试克服的特定错误,请使用覆盖重复项的字典速记方法。

Dim dict As Dictionary

Set dict = New Dictionary
dict.Item(0) = 0
dict.Item(0) = 1
'dict.count = 1 with key as 0 and item as 1

更一般地说,您可以在On Error Resume Next和On Error GoTo 0中包含潜在错误。

Dim dict As Dictionary

Set dict = New Dictionary
On Error Resume Next
dict.Add 0, 0
dict.Add 0, 1
On Error GoTo 0
'dict.count = 1 with key as 0 and item as 0

4
投票

错误是未处理的,因为新打开的工作簿在基本上是一个非同步进程内部运行 - Workbook_Open是一个事件处理程序,因此它不是从您的代码中调用的。它从内部Excel进程打开文档时被调用为回调函数。您可以使用任何事件处理程序演示相同的行为:

'In Sheet1
Sub Example()
    On Error GoTo Handler
    Sheet1.Cells(1, 1).Value = "Foo"
    Exit Sub

Handler:
    Debug.Print "Handled"
End Sub

Private Sub Worksheet_Change(ByVal Target As Range)
    If Target.Row = 1 And Target.Column = 1 Then
        Err.Raise 6
    End If
End Sub

如果您需要批量处理文件,那么您唯一的(简单)选项是在调用open之前禁用事件:

Sub testOpen()
    Dim bk As Workbook

    On Error GoTo errHandler

    Application.EnableEvents = False
    Set bk = Workbooks.Open ThisWorkbook.Path & "\bkOpenErrorTest_dict.xlsm"
    Application.EnableEvents = True

    Exit Sub

errHandler:
    Debug.Print "reached error handler"
End Sub

如果由于某种原因,有缺陷的Workbook_Open运行是至关重要的,那么你可以使用解决方案Tim Williams outlines here。只需在目标工作簿中创建一个公共包装函数,然后在您自己的错误处理程序的上下文中调用它。

© www.soinside.com 2019 - 2024. All rights reserved.