How to handle error generated inside another workbook's Workbook_Open event?

How to handle error generated inside another workbook's Workbook_Open event?



I have two workbooks in the same folder: bkOpenErrorTest.xlsm and bkOpenErrorTest_dict.xlsm.


bkOpenErrorTest.xlsm


bkOpenErrorTest_dict.xlsm



bkOpenErrorTest_dict.xlsm has the following code in its ThisWorkbook module:


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



When this workbook is opened by double-clicking the filename, it throws the expected unhandled error:


This key is already associated with an element of this collection



bkOpenErrorTest.xlsm has the following code in Module1:


bkOpenErrorTest.xlsm


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



When error trapping is set to Break on Unhandled Errors, and I run testOpen(), the unhandled error is still raised when bkOpenErrorTest_dict.xlsm opens. Why isn't the error caught by testOpen()'s error handler? And how can I handle this error? I have an application where I'd like to cycle through many workbooks in a folder that have buggy code like this in their workbook_open() event, and I can't iterate through them if the program crashes on an unhandled error like this.


Break on Unhandled Errors


testOpen()


bkOpenErrorTest_dict.xlsm


testOpen()


workbook_open()





You can try disabling events - unless you need the Workbook_Open event to run
– urdearboy
Aug 31 at 22:05



Workbook_Open





@urdearboy thanks, that's a possibility, but i would like to trap errors selectively, so that e.g. if the workbook has trouble opening due to corruption, we would handle that error differently (e.g. by skipping that workbook in the loop)
– sigil
Aug 31 at 22:09





If that is the specific error you are trying to overcome either use the dictionary shorthand method that overwrites duplicates or more generally wrap potential errors in On Error Resume Next and On Error GoTo 0.
– Jeeped
Aug 31 at 22:25




2 Answers
2



The reason that the error is not being handled is that the two processes are not in the same thread. If you were calling a 'helper' sub procedure from a main sub procedure, you remain in the same thread and errors thrown in the 'helper' are caught by error control in the main. This is akin to why an error in a procedure launched by Application.Run will not have thrown errors handled by the error control in the procedure that launched it.



To gain any measure of control over what happens in the newly opened workbook's Workbook_Open, you need to control things on the Application instance level. The following halts execution of the Workbook_Open event procedure; if it isn't necessary to process the code, then this could be your solution.


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



If the Dictionary populating is the specific error you are trying to overcome use the dictionary shorthand method that overwrites duplicates.


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



More generally you can wrap potential errors in On Error Resume Next and 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





His problem is not the error with the dictionary...
– Pm Duda
Aug 31 at 22:34





... and when he comes to the realization that that is simply never going to happen, then he might consider these options.
– Jeeped
Aug 31 at 22:40





Shouldn't you then in your answer inform him, that what he want's is never going to work?
– Pm Duda
Aug 31 at 22:42





Perhaps I will after I find time to set up multiple external workbooks and test every scenario and possible solution I can think of. For now, the fact that the spawned workbook is not in the same thread as the calling sub procedure is the reason that the calling sub procedure's error handling is not covering the error thrown in the new workbook.
– Jeeped
Aug 31 at 22:51





@sigil - It crashes because you have events turned on. Turn them off to avoid the events, then change the code once you have a valid reference.
– Comintern
Aug 31 at 23:14



The error is unhandled because the newly opened Workbook is running inside of what is basically an asychronous process - Workbook_Open is an event handler, so it is not being called from your code. It is being invoked as a callback function from inside whatever external Excel process is opening the document. You can demonstrate the same behavior with any event handler:


Workbook_Open


'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



If you need to bulk process the files, your only (easy) option is going to be disabling events before the call to 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



If for some reason it is vitally important that the buggy Workbook_Open runs, then you can use the solution Tim Williams outlines here. Just create a public wrapper function in the target workbook, then call that from within the context of your own error handler.


Workbook_Open





As I mentioned in my comment on Jeeped's answer, modifying the code in the target workbook is impractical because of the volume of workbooks that I need to address.
– sigil
Aug 31 at 23:08





Then this answer should explain why what you want to do is impossible. ;-)
– Comintern
Aug 31 at 23:09





@sigil Note also that you don't have to save the code you emit into the workbooks via the linked answer - you just have to call it.
– Comintern
Aug 31 at 23:10





if the program crashes when the workbook opens, then the VBA-modifying code cannot be inserted in order to be run (as the program that would insert the code is no longer running).
– sigil
Sep 1 at 0:02





@sigil Look at the code in the answer again. If you disable the events the Workbook_Open event won't run, so it can't crash.
– Comintern
Sep 1 at 0:05


Workbook_Open



Thanks for contributing an answer to Stack Overflow!



But avoid



To learn more, see our tips on writing great answers.



Some of your past answers have not been well-received, and you're in danger of being blocked from answering.



Please pay close attention to the following guidance:



But avoid



To learn more, see our tips on writing great answers.



Required, but never shown



Required, but never shown






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)