使用 Resume Next 在循环中处理错误
Error handling in a loop using Resume Next
作为 VBA 的新手,我们将不胜感激。我的程序的基本要点是遍历电子表格的列并计算指定范围内每列中非空白单元格的数量。
这是我的电子表格的示例。
1
2
3
1
thing
2
thing
3
thing
当列中的所有单元格均为空白时,VBA 抛出 1004 错误,未找到单元格。我想做的是说,如果发生 1004 错误,将非空白单元格 (nonBlank = 0) 的计数设置为零,如果没有发生错误,则正常计数。在类似 Python 的情况下,我会使用 try/except。这是我的尝试。
For i = 1 To 3
On Error Resume Next
Set selec_cells = Sheet1.Range(Sheet1.Cells(FirstRow, i), Sheet1.Cells(LastRow, i)).SpecialCells(xlCellTypeVisible).Cells.SpecialCells(xlCellTypeConstants)
If Err.Number <> 1004 Then
nonBlank = 0
Else
nonBlank = selec_cells.Count
End If
On Error GoTo -1
Next i
我的问题是,当我 运行 这段代码时,它每次都输出 0,即使第 2 列应该 return 3。谢谢!
编辑:selec_cells 是抛出错误的原因。
错误处理
VBA
, it's a VB
中没有 On Error Goto -1
(那些是指向不同页面的链接)。一个提示是,如果你 google VBA
东西,只需将 VBA
放在你要找的东西前面。
当使用 On Error Resume Next
(延迟错误捕获)时,您应该 'apply' 最多在一两行上使用 'close' 和 On Error Goto 0
(禁用错误捕获)或使用另一个错误处理程序。
您对 On Error Resume Next
的使用是不可接受的,因为在这种特殊情况下我们可以测试范围:1. 延迟错误处理,2. 尝试设置范围,3. 禁用错误处理.如果出现错误,则不会设置范围,因此 If Not rg Is Nothing Then
可以转换为 'If rg Is Something Then'(双重否定)或 If已创建对范围的引用 Then.
第二种解决方案说明了一种情况,其中主错误处理程序正在处理所有错误,但 SpecialCells
错误具有自己的错误处理程序。 Resume Next
表示继续发生错误的行之后的行。注意 Exit Sub
行并注意 Resume ProcExit
代码被重定向到标签的位置。
以下说明了处理此问题的两种方法。在这个阶段,我建议您使用第一个,并记住在使用 On Error Resume Next
(一两行)时使用 'closing' On Error Goto 0
。
代码
Option Explicit
Sub testOnErrorResumeNext()
Const FirstRow As Long = 2
Const LastRow As Long = 11
Dim rg As Range ' ... additionally means 'Set rg = Nothing'.
Dim nonBlank As Long ' ... additionally means 'nonBlank = 0'.
Dim j As Long
For j = 1 To 3 ' Since it's a column counter, 'j' or 'c' seems preferred.
' Since you're in a loop, you need the following line.
Set rg = Nothing
On Error Resume Next
Set rg = Sheet1.Range(Sheet1.Cells(FirstRow, j), _
Sheet1.Cells(LastRow, j)).SpecialCells(xlCellTypeVisible) _
.Cells.SpecialCells(xlCellTypeConstants)
On Error GoTo 0
If Not rg Is Nothing Then
nonBlank = rg.Cells.Count
Else
' Since you're in a loop, you need the following line.
nonBlank = 0
End If
Debug.Print nonBlank
Next j
End Sub
Sub testOnError()
On Error GoTo clearError
Const FirstRow As Long = 2
Const LastRow As Long = 11
Dim rg As Range ' ... additionally means 'Set rg = Nothing'.
Dim nonBlank As Long ' ... additionally means 'nonBlank = 0'.
Dim j As Long
For j = 1 To 3 ' Since it's a column counter, 'j' or 'c' seems preferred.
' Since you're in a loop, you need the following line.
Set rg = Nothing
On Error GoTo SpecialCellsHandler
Set rg = Sheet1.Range(Sheet1.Cells(FirstRow, j), _
Sheet1.Cells(LastRow, j)).SpecialCells(xlCellTypeVisible) _
.Cells.SpecialCells(xlCellTypeConstants)
On Error GoTo clearError
If Not rg Is Nothing Then
nonBlank = rg.Cells.Count
End If
Debug.Print nonBlank
Next j
ProcExit:
Exit Sub ' Note this.
SpecialCellsHandler:
' Since you're in a loop, you need the following line.
nonBlank = 0
Resume Next
clearError:
MsgBox "Run-time error '" & Err.Number & "': " & Err.Description
Resume ProcExit
End Sub
我的偏好是尽可能将可能导致错误的代码行封装在其自身的功能中。函数 returns true 或 false 指示是否有错误,输出参数用于 return 您想要的值。
这将错误测试限制在一个非常短且定义明确的函数中。
Sub ttest()
Dim mySheet As Excel.Worksheet
Set mySheet = ThisWorkbook.Sheet1
Dim myIndex As Long
Dim myNonBlank as long
For myIndex = 1 To 3
If AllCellsAreBlank(mySheet.Range(ThisWorkbook.Sheet1.Cells(myFirstRow, myIndex), mySheet.Cells(myLastRow, myIndex)), myIndex, mySelectCells) Then
myNonBlank = 0
Else
myNonBlank = mySelectCells.Count
End If
Next
End Sub
Public Function AllCellsAreBlank(ByRef ipRange As Excel.Range, ByVal ipIndex As Long, ByRef opSelectCells As Range) As Boolean
On Error Resume Next
set opSelectCells = ipRange.SpecialCells(xlCellTypeVisible).Cells.SpecialCells(xlCellTypeConstants)
AllCellsAreBlank = Err.Number <> 0
On Error GoTo 0
End Function
作为参考,我使用的前缀是
- ip: 仅用于输入参数
- iop: 对于将被方法改变的输入参数
- op: 对于一个参数只用于return一个值
- my:方法中声明的任何变量。
我还建议您养成使用有意义的描述性名称的习惯,myRow、myCol 比 i、j 更有意义,并确保您使用完全限定的引用而不是隐式使用活动表。
作为 VBA 的新手,我们将不胜感激。我的程序的基本要点是遍历电子表格的列并计算指定范围内每列中非空白单元格的数量。 这是我的电子表格的示例。
1 | 2 | 3 | |
---|---|---|---|
1 | thing | ||
2 | thing | ||
3 | thing |
当列中的所有单元格均为空白时,VBA 抛出 1004 错误,未找到单元格。我想做的是说,如果发生 1004 错误,将非空白单元格 (nonBlank = 0) 的计数设置为零,如果没有发生错误,则正常计数。在类似 Python 的情况下,我会使用 try/except。这是我的尝试。
For i = 1 To 3
On Error Resume Next
Set selec_cells = Sheet1.Range(Sheet1.Cells(FirstRow, i), Sheet1.Cells(LastRow, i)).SpecialCells(xlCellTypeVisible).Cells.SpecialCells(xlCellTypeConstants)
If Err.Number <> 1004 Then
nonBlank = 0
Else
nonBlank = selec_cells.Count
End If
On Error GoTo -1
Next i
我的问题是,当我 运行 这段代码时,它每次都输出 0,即使第 2 列应该 return 3。谢谢!
编辑:selec_cells 是抛出错误的原因。
错误处理
VBA
, it's aVB
中没有On Error Goto -1
(那些是指向不同页面的链接)。一个提示是,如果你 googleVBA
东西,只需将VBA
放在你要找的东西前面。当使用
On Error Resume Next
(延迟错误捕获)时,您应该 'apply' 最多在一两行上使用 'close' 和On Error Goto 0
(禁用错误捕获)或使用另一个错误处理程序。您对
On Error Resume Next
的使用是不可接受的,因为在这种特殊情况下我们可以测试范围:1. 延迟错误处理,2. 尝试设置范围,3. 禁用错误处理.如果出现错误,则不会设置范围,因此If Not rg Is Nothing Then
可以转换为 'If rg Is Something Then'(双重否定)或 If已创建对范围的引用 Then.第二种解决方案说明了一种情况,其中主错误处理程序正在处理所有错误,但
SpecialCells
错误具有自己的错误处理程序。Resume Next
表示继续发生错误的行之后的行。注意Exit Sub
行并注意Resume ProcExit
代码被重定向到标签的位置。以下说明了处理此问题的两种方法。在这个阶段,我建议您使用第一个,并记住在使用
On Error Resume Next
(一两行)时使用 'closing'On Error Goto 0
。
代码
Option Explicit
Sub testOnErrorResumeNext()
Const FirstRow As Long = 2
Const LastRow As Long = 11
Dim rg As Range ' ... additionally means 'Set rg = Nothing'.
Dim nonBlank As Long ' ... additionally means 'nonBlank = 0'.
Dim j As Long
For j = 1 To 3 ' Since it's a column counter, 'j' or 'c' seems preferred.
' Since you're in a loop, you need the following line.
Set rg = Nothing
On Error Resume Next
Set rg = Sheet1.Range(Sheet1.Cells(FirstRow, j), _
Sheet1.Cells(LastRow, j)).SpecialCells(xlCellTypeVisible) _
.Cells.SpecialCells(xlCellTypeConstants)
On Error GoTo 0
If Not rg Is Nothing Then
nonBlank = rg.Cells.Count
Else
' Since you're in a loop, you need the following line.
nonBlank = 0
End If
Debug.Print nonBlank
Next j
End Sub
Sub testOnError()
On Error GoTo clearError
Const FirstRow As Long = 2
Const LastRow As Long = 11
Dim rg As Range ' ... additionally means 'Set rg = Nothing'.
Dim nonBlank As Long ' ... additionally means 'nonBlank = 0'.
Dim j As Long
For j = 1 To 3 ' Since it's a column counter, 'j' or 'c' seems preferred.
' Since you're in a loop, you need the following line.
Set rg = Nothing
On Error GoTo SpecialCellsHandler
Set rg = Sheet1.Range(Sheet1.Cells(FirstRow, j), _
Sheet1.Cells(LastRow, j)).SpecialCells(xlCellTypeVisible) _
.Cells.SpecialCells(xlCellTypeConstants)
On Error GoTo clearError
If Not rg Is Nothing Then
nonBlank = rg.Cells.Count
End If
Debug.Print nonBlank
Next j
ProcExit:
Exit Sub ' Note this.
SpecialCellsHandler:
' Since you're in a loop, you need the following line.
nonBlank = 0
Resume Next
clearError:
MsgBox "Run-time error '" & Err.Number & "': " & Err.Description
Resume ProcExit
End Sub
我的偏好是尽可能将可能导致错误的代码行封装在其自身的功能中。函数 returns true 或 false 指示是否有错误,输出参数用于 return 您想要的值。
这将错误测试限制在一个非常短且定义明确的函数中。
Sub ttest()
Dim mySheet As Excel.Worksheet
Set mySheet = ThisWorkbook.Sheet1
Dim myIndex As Long
Dim myNonBlank as long
For myIndex = 1 To 3
If AllCellsAreBlank(mySheet.Range(ThisWorkbook.Sheet1.Cells(myFirstRow, myIndex), mySheet.Cells(myLastRow, myIndex)), myIndex, mySelectCells) Then
myNonBlank = 0
Else
myNonBlank = mySelectCells.Count
End If
Next
End Sub
Public Function AllCellsAreBlank(ByRef ipRange As Excel.Range, ByVal ipIndex As Long, ByRef opSelectCells As Range) As Boolean
On Error Resume Next
set opSelectCells = ipRange.SpecialCells(xlCellTypeVisible).Cells.SpecialCells(xlCellTypeConstants)
AllCellsAreBlank = Err.Number <> 0
On Error GoTo 0
End Function
作为参考,我使用的前缀是
- ip: 仅用于输入参数
- iop: 对于将被方法改变的输入参数
- op: 对于一个参数只用于return一个值
- my:方法中声明的任何变量。
我还建议您养成使用有意义的描述性名称的习惯,myRow、myCol 比 i、j 更有意义,并确保您使用完全限定的引用而不是隐式使用活动表。