我有一个工作簿,其中声明了全局变量:
Public var1 As Long
Public var2 As Long
Public var3 As Long
...
Public varN As Long
我还具有一个工作簿打开子项,该子项在打开工作簿时将值分配给全局变量:
Private Sub Workbook_open()
Application.Calculation = xlCalculationAutomatic
Call calculateRows
Call assignVariables
ThisWorkbook.Worksheets("Filling").Protect "somepass", UserInterfaceOnly:=True
MsgBox ("DONE Workbook_open")
End Sub
工作正常。但是,我还有一个工作表选择更改子项:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
...
End Sub
和工作表更改子:
Private Sub Worksheet_Change(ByVal Target As Range)
...
End Sub
都包含可能会导致错误的代码。无论发生什么错误,它总是擦除我的全局变量的值,这只会导致进一步的错误,并且基本上会完全关闭工作簿,因为所有工作表选择/更改子项都大量使用这些全局变量。
我应该怎么做才能确保它不会发生?使用“出现错误时转到”操作是否足够?为什么仍然要删除全局变量?
答案 0 :(得分:5)
如注释中所述,单击End
暂停执行将始终重置全局状态。哎呀,没有必要出错。点击“停止”按钮将具有相同的效果。
至少应该在输入过程中进行错误处理(例如,工作表事件处理程序是不错的选择,因为它们是Excel可以与您的VBA代码进行交互的入口点)。
如果您甚至希望使用错误处理程序也能找到有问题的错误,此模式可以帮助您:
Public Sub Example()
On Error GoTo ErrHandler
'Some code that might error
ExitProcedure:
On Error Resume Next
'Clean up
Exit Sub
ErrorHandler:
MsgBox "Oops"
Resume ExitProcedure
Resume 'for debugging
End Sub
请注意错误处理程序末尾无法访问的Resume
。由于Resume ExitProcedure
将始终首先执行,因此无法访问。因此,当您收到消息框时,可以使用ctrl+break
进入代码,然后转到Resume ExitProcedure
。然后,您可以将黄色箭头拖动到无法访问的Resume
上,按F8键一次,然后将您带回到导致错误的行。
请注意,它仅适用于过程。如果错误被冒泡,它将使您返回到错误冒泡之前被调用的过程,而不是过程中的行。
或者,如果您不喜欢所有额外的工作,则可以考虑购买诸如vbWatchDog 之类的加载项,该加载项可大大帮助错误处理。
即使如此,那些方法也无法解决根本问题-全局状态非常脆弱,可以被破坏...您可以使用“停止”按钮甚至End
。您希望避免使用尽可能多的global并将它们范围化或将它们填充在类实例中,以便当您重复代码块时,它可以在该范围内重建状态。在全局状态下拥有的东西越少越好。