Excel VBA 全局错误处理

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14940697/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-11 19:40:20  来源:igfitidea点击:

Excel VBA Global error handling

excelexcel-vbavba

提问by evoandy

Is there a way to do global error handling?

有没有办法进行全局错误处理?

Can I put some code in the Workbook code that will catch any errors that occur within all modules?

我可以在工作簿代码中放入一些代码来捕获所有模块中发生的任何错误吗?

I could put the same error handler in each module but I'm looking for something more general.

我可以在每个模块中放置相同的错误处理程序,但我正在寻找更通用的东西。

I ask because I have sheet names that are stored as global variables like this Sheets(QuoteName). If there is an error then these global variables are lost. I have a macro that will rename the global variables but I put this within Workbook_BeforeSave.

我问是因为我有像这样存储为全局变量的工作表名称Sheets(QuoteName)。如果出现错误,则这些全局变量将丢失。我有一个宏可以重命名全局变量,但我把它放在Workbook_BeforeSave.

I want it to go to the global error handler and rename the global variable if I get a Subscript out of rangeerror for Sheets(QuoteName)

如果出现下标超出范围错误,我希望它转到全局错误处理程序并重命名全局变量Sheets(QuoteName)

回答by Peter Albert

As Sid already mentioned in the comment, there is no central error handler.

正如 Sid 在评论中已经提到的,没有中央错误处理程序。

Best practice is to have a central error handling routine that gets called from the local error handlers. Take a look at the great MZ-Tools: it has the possibility to define a default error handler at the press of a button (Ctrl-E). You can customize this error handler - and it can also contain module and/or sub name!

最佳实践是拥有一个从本地错误处理程序调用的中央错误处理例程。看看伟大的MZ-Tools:它可以在按下按钮 ( Ctrl- E) 时定义默认错误处理程序。您可以自定义此错误处理程序 - 它也可以包含模块和/或子名称!

Additionally, check out this post at Daily Dose of Excel. It is Dick Kusleika's OO version of the error handler proposed in this book(which I can highly recommend).

此外,请在Daily Dose of Excel 上查看这篇文章。这是本书中提出的错误处理程序的 Dick Kusleika 的 OO 版本(我强烈推荐)。

回答by user3666385

Here's some code I threw together to handle the problem in access

这是我为处理访问问题而拼凑的一些代码

It puts error checking in all subs, but not functions. subs have to have a parent form (ACCESS), or alternatively, you have to put the form name in manually. subs that are continued over more than one line will be mercilessly whacked.

它在所有子程序中进行错误检查,但不是函数。subs 必须有一个父表单 (ACCESS),或者,您必须手动输入表单名称。连续超过一条线路的潜艇将被无情地打击。

The two subs have to be at the bottom of a module.

两个潜艇必须位于模块的底部。

  • globalerroris your error management routine
  • CleaVBA_clickchanges your VBA code, adds line #s to everything
  • globalerror是您的错误管理例程
  • CleaVBA_click更改您的 VBA 代码,向所有内容添加行 #s

globalerror looks at a boolean global errortrackingto see if it logs everything or only errors

globalerror 查看布尔全局错误跟踪以查看它是否记录所有内容或仅记录错误

There is a table ErrorTracking that has to be created otherwise just comment out from 1990 to 2160

必须创建一个表 ErrorTracking 否则只需注释掉从 1990 到 2160

When running, it removes then adds line numbers to everything in the project, so your error message can include a line #

运行时,它会删除然后向项目中的所有内容添加行号,因此您的错误消息可以包含一行 #

Not sure if it works on anything other than stuff I've coded.

不确定它是否适用于我编码的东西以外的任何东西。

Be sure to run and test on a copy of your VBA, because it literally rewrites every line of code in your project, and if I screwed up, and you didn't back up, then your project is broken.

一定要在你的 VBA 副本上运行和测试,因为它实际上重写了你项目中的每一行代码,如果我搞砸了,而你没有备份,那么你的项目就坏了。

    Public Sub globalerror(Name As String, number As Integer, Description As String, source As String)


    1970  Dim db As DAO.Database
    1980  Dim rst As DAO.Recordset



    1990  If errortracking Or (Err.number <> 0) Then
    2000     Set db = CurrentDb
    2010     Set rst = db.OpenRecordset("ErrorTracking")
    2020     rst.AddNew

    2030     rst.Fields("FormModule") = Name
    2040     rst.Fields("ErrorNumber") = number
    2050     rst.Fields("Description") = Description
    2060     rst.Fields("Source") = source
    2070     rst.Fields("timestamp") = Now()
    2080     rst.Fields("Line") = Erl

    2100     rst.Update
    2110     rst.Close
    2120     db.Close
    2130  End If

    2140  If Err.number = 0 Then
    2150     Exit Sub
    2160  End If

    2170  MsgBox "ERROR" & vbCrLf & "Location: " & Name & vbCrLf & "Line: " & Erl & vbCrLf & "Number: " & number & vbCrLf & "Description: " & Description & vbCrLf & source & vbCrLf & Now() & vbCrLf & vbCrLf & "custom message"

    2180  End Sub






    Private Sub CleanVBA_Click()

        Dim linekill As Integer
        Dim component As Object
        Dim index As Integer
        Dim str As String
        Dim str2a As String
        Dim linenumber As Integer
        Dim doline As Boolean
        Dim skipline As Boolean
        Dim selectflag As Boolean
        Dim numstring() As String


        skipline = False
        selectflag = False
        tabcounter = 0

        For Each component In Application.VBE.ActiveVBProject.VBComponents

            linekill = component.CodeModule.CountOfLines
            linenumber = 0
            For i = 1 To linekill

                str = component.CodeModule.Lines(i, 1)
                doline = True

                If Right(Trim(str), 1) = "_" Then
                    doline = False
                    skipline = True
                End If

                If Len(Trim(str)) = 0 Then
                    doline = False
                End If

                If InStr(Trim(str), "'") = 1 Then
                    doline = False
                End If

                If selectflag Then
                    doline = False
                End If

                If InStr(str, "Select Case") > 0 Then
                    selectflag = True
                End If

                If InStr(str, "End Select") > 0 Then
                    selectflag = False
                End If

                If InStr(str, "Global ") > 0 Then
                    doline = False
                End If

                If InStr(str, "Sub ") > 0 Then
                    doline = False
                End If

                If InStr(str, "Option ") > 0 Then
                    doline = False
                End If

                If InStr(str, "Function ") > 0 Then
                    doline = False
                End If


                If (InStr(str, "Sub ") > 0) Then


                    If InStr(component.CodeModule.Lines(i + 1, 1), "On Error GoTo error") <> 0 Then
                        GoTo skipsub
                    End If

                    str2a = component.CodeModule.Name

                    index = InStr(str, "Sub ")  ' sub
                    str = Right(str, Len(str) - index - 3)    ' sub

                    '           index = InStr(str, "Function ") ' function
                    '             str = Right(str, Len(str) - index - 8) 'function

                    index = InStr(str, "(")
                    str = Left(str, index - 1)

                    varReturn = SysCmd(acSysCmdSetStatus, "Editing: " & str2a & " : " & str)
                    DoEvents

                    If (str = "CleanVBA_Click") Then
                        MsgBox "skipping self"
                        GoTo selfie
                    End If

                    If str = "globalerror" Then
                        MsgBox "skipping globalerror"
                        GoTo skipsub
                    End If

                    component.CodeModule.InsertLines i + 1, "On Error GoTo error"
                    i = i + 1
                    linekill = linekill + 1

                    component.CodeModule.InsertLines i + 1, "error:"
                    i = i + 1
                    linekill = linekill + 1

                    component.CodeModule.InsertLines i + 1, "Call globalerror(Me.Form.Name & """ & "-" & str & """, Err.number, Err.description, Err.source)"
                    i = i + 1
                    linekill = linekill + 1

                    component.CodeModule.InsertLines i + 1, " "
                    i = i + 1
                    linekill = linekill + 1

                    If (str = "MashVBA_Click") Then
                        MsgBox "skipping self"
                        MsgBox component.CodeModule.Name & " " & str
                        GoTo selfie
                    End If
                Else
                    If skipline Then
                        If doline Then
                            skipline = False
                        End If
                        doline = False
                    End If
                    If doline Then
                        linenumber = linenumber + 10
                        numstring = Split(Trim(str), " ")
                        If Len(numstring(0)) >= 2 Then
                            If IsNumeric(numstring(0)) Then
                                str = Replace(str, numstring(0), "")
                            End If
                        End If
                        component.CodeModule.ReplaceLine i, linenumber & " " & str

                    End If

                End If
    skipsub:

            Next i
    selfie:
        Next

        varReturn = SysCmd(acSysCmdSetStatus, " ")
        MsgBox "Finished"
    End Sub