如何在VBA中捕获未知错误并赋值给ErrorMsg变量
VBA全局错误信息捕获:处理未知错误的通用方案
我定义了全局变量ErrorMsg As String,用来存储代码中所有已知的错误信息。现在需要实现:当VBA抛出未被捕获的错误或意外错误时,自动将ErrorMsg赋值为"Unknown Error"。请问能否通过通用代码实现这个功能?相关代码如下:
主程序代码
Global Parameter As Long, RoutingStep As Long, wsName As String, ErrorMsg As String, SectionName As String, SDtab As Worksheet, subsysnum As String Global wb As Workbook, sysrow As Long, sysnum As String, ws As Worksheet Global center_wavelength_value As Double, sweeprate_value As Double Public Sub Main() Dim syswaiver As Long, axsunpart As Long Dim startcell As String, cell As Range Dim syscol As Long, dict As Object, wbSrc As Workbook Set wb = Workbooks("SD093_KW.xlsm") Set ws = wb.Worksheets("Data Sheet") syswaiver = GetColumnIndex(ws, "System Waiver Number(s)") axsunpart = GetColumnIndex(ws, "Part Number") Set wbSrc = Workbooks.Open("Q:\Documents\Specification Document.xlsx") Set dict = CreateObject("scripting.dictionary") If Not syswaiver = 0 Then startcell = ws.cells(2, syswaiver).Address Else ErrorMsg = "System waiver number column index not found. Value needed to proceed" GoTo Skip End If For Each cell In ws.Range(startcell, ws.cells(ws.Rows.Count, syswaiver).End(xlUp)).cells sysnum = cell.value sysrow = cell.row syscol = cell.column If Not dict.Exists(sysnum) Then dict.Add sysnum, True If Not SheetExists(sysnum, wb) Then If Not axsunpart = 0 Then wsName = cell.EntireRow.Columns(axsunpart).value If SheetExists(wsName, wbSrc) Then wbSrc.Worksheets(wsName).copy After:=ws wb.Worksheets(wsName).Name = sysnum Set SDtab = wb.Worksheets(ws.Index + 1) Else ErrorMsg = ErrorMsg & IIf(ErrorMsg = "", "", "") & "Axsun part number for " & sysnum & " sheet to be copied could not be copied" cell.Interior.Color = vbRed ' GoTo Skip End If SDTabHeaders Sheets(1).Select ' Power Section Power Skip: Dim begincell As Long With logsht ' wb.Worksheets("Log Sheet") begincell = .cells(Rows.Count, 1).End(xlUp).row .cells(begincell + 1, 3).value = sysnum .cells(begincell + 1, 3).Font.Bold = True .cells(begincell + 1, 2).value = Date .cells(begincell + 1, 2).Font.Bold = True If Not ErrorMsg = "" Then .cells(begincell + 1, 4).value = vbNewLine & "Complete with Erorr - " & vbNewLine & ErrorMsg .cells(begincell + 1, 4).Font.Bold = True .cells(begincell + 1, 4).Interior.Color = vbRed Else .cells(begincell + 1, 4).value = "All Sections Completed without Errors" .cells(begincell + 1, 4).Font.Bold = True .cells(begincell + 1, 4).Interior.Color = vbGreen End If End With Next cell End Sub
SheetExists函数
Function SheetExists(SheetName As String, wb As Workbook) If wb Is Nothing Then Set wb = ActiveWorkbook On Error Resume Next SheetExists = Not wb.Sheets(SheetName) Is Nothing On Error GoTo 0 End Function
SDTabHeaders过程
Sub SDTabHeaders() SectionName = "SD Tab Headers" On Error GoTo errormessage Parameter = GetColumnIndex(SDtab, "PARAMETER") RoutingStep = GetColumnIndex(SDtab, "Routing Step 1") specmin = GetColumnIndex(SDtab, "SPEC min") specmax = GetColumnIndex(SDtab, "SPEC max") errormessage: ErrorMsg = ErrorMsg End Sub
Power过程
Sub Power() Dim power_col As Long, power_value As Double, power_rowindex As Double SectionName = "Power" On Error GoTo errormessage power_col = GetColumnIndex(ws, "Average Power (mW)") power_value = Getdata(ws, sysrow, power_col) errormessage: ErrorMsg = ErrorMsg End Sub
GetColumnIndex函数
Function GetColumnIndex(sht As Worksheet, colname As String) As Double Dim paramname As Range Set paramname = sht.Range("A1", sht.cells(2, sht.Columns.Count).End(xlToLeft)).cells.Find(What:=colname, LookAt:=xlWhole, LookIn:=xlFormulas, searchorder:=xlByColumns, searchdirection:=xlPrevious, MatchCase:=True) If Not paramname Is Nothing Then GetColumnIndex = paramname.column ElseIf paramname Is Nothing Then ErrorMsg = ErrorMsg & IIf(ErrorMsg = "", "", "") & SectionName & ": " & colname & "column index could not be found" & vbNewLine End If End Function
Getdata函数
Function Getdata(sht As Worksheet, WDrow As Long, parametercol As Long) As Variant ' locates the cell with the jira data Getdata = sht.cells(WDrow, parametercol) If Getdata < 0 Or GetJIRAdata = Empty Then ErrorMsg = ErrorMsg & IIf(ErrorMsg = "", "", "") & SectionName & ": " & "data could not be found" & vbNewLine End If End Function
解决方案
可以通过统一的错误处理逻辑实现需求,核心是创建通用错误处理过程,并为所有过程添加规范的错误陷阱:
1. 创建通用错误处理过程
这个过程会判断当前是否为未被捕获的意外错误,然后给ErrorMsg赋值:
Sub HandleUnexpectedError(Optional sectionName As String = "") ' 仅当ErrorMsg为空(无已知错误信息)时,设置为未知错误 If ErrorMsg = "" Then If sectionName <> "" Then ErrorMsg = sectionName & ": Unknown Error" Else ErrorMsg = "Unknown Error" End If End If Err.Clear ' 清除错误状态 End Sub
2. 修改现有过程的错误处理分支
为所有带On Error GoTo的过程添加Exit Sub/Function(避免正常执行时进入错误分支),并替换原错误处理代码:
- 修改SDTabHeaders:
Sub SDTabHeaders() SectionName = "SD Tab Headers" On Error GoTo errormessage Parameter = GetColumnIndex(SDtab, "PARAMETER") RoutingStep = GetColumnIndex(SDtab, "Routing Step 1") specmin = GetColumnIndex(SDtab, "SPEC min") specmax = GetColumnIndex(SDtab, "SPEC max") Exit Sub ' 正常结束时跳过错误处理 errormessage: HandleUnexpectedError SectionName End Sub
- 修改Power过程:
Sub Power() Dim power_col As Long, power_value As Double, power_rowindex As Double SectionName = "Power" On Error GoTo errormessage power_col = GetColumnIndex(ws, "Average Power (mW)") power_value = Getdata(ws, sysrow, power_col) Exit Sub ' 正常结束时跳过错误处理 errormessage: HandleUnexpectedError SectionName End Sub
3. 为主程序添加全局错误捕获
在Main过程开头添加全局错误陷阱,处理主流程中未被局部捕获的意外错误:
Public Sub Main() Dim syswaiver As Long, axsunpart As Long Dim startcell As String, cell As Range Dim syscol As Long, dict As Object, wbSrc As Workbook ' 全局错误捕获 On Error GoTo GlobalErrorHandler Set wb = Workbooks("SD093_KW.xlsm") Set ws = wb.Worksheets("Data Sheet") ' ... 原代码保持不变 ... ' 正常结束时跳过全局错误处理 Exit Sub GlobalErrorHandler: HandleUnexpectedError "Main Procedure" GoTo Skip ' 跳转到日志记录部分 End Sub
4. 为函数添加错误处理
修改GetColumnIndex和Getdata,确保函数执行中出现的意外错误也能被处理:
- 修改GetColumnIndex:
Function GetColumnIndex(sht As Worksheet, colname As String) As Double Dim paramname As Range On Error GoTo errormessage Set paramname = sht.Range("A1", sht.cells(2, sht.Columns.Count).End(xlToLeft)).cells.Find(What:=colname, LookAt:=xlWhole, LookIn:=xlFormulas, searchorder:=xlByColumns, searchdirection:=xlPrevious, MatchCase:=True) If Not paramname Is Nothing Then GetColumnIndex = paramname.column ElseIf paramname Is Nothing Then ErrorMsg = ErrorMsg & IIf(ErrorMsg = "", "", "") & SectionName & ": " & colname & "column index could not be found" & vbNewLine End If Exit Function errormessage: HandleUnexpectedError SectionName GetColumnIndex = 0 ' 返回无效值标记错误 End Function
关键说明
- 所有过程必须添加
Exit Sub/Function,防止正常执行时误触发错误处理分支。 - 只有当
ErrorMsg为空(无已知错误信息)时,才会被设置为“Unknown Error”,不会覆盖已有的已知错误信息。 - 全局错误陷阱确保主流程中任何未被局部处理的意外错误都能被捕获并标记。
内容的提问来源于stack exchange,提问作者user20114520
相关产品推荐
相关产品推荐

