Error handling in MS Excel VBA
I am having problems with errors occurring in a loop in VBA. Firstly, here is the code I am using
dl = 20
For dnme = 1 To 3
Select Case dnme
Case 1
drnme = kt + " 90"
nme = "door90"
drnme1 = nme
Case 2
drnme = kt + " dec"
nme = "door70" 'decorative glazed'
Case 3
drnme = kt + " gl"
nme = "door80" 'plain glazed'
End Select
On Error GoTo ErrorHandler
Set sh = Worksheets("kitchen doors").Shapes(drnme) 'This line here is where the problem is'
sh.Copy
ActiveSheet.Paste
Selection.ShapeRange.Name = nme
Selection.ShapeRange.Top = 50
Selection.ShapeRange.Left = dl
Selection.ShapeRange.Width = 150
Selection.ShapeRange.Height = 220
25
dl = dl + 160
Next dnme
Exit Sub
ErrorHandler:
GoTo 25
The problem is that when it tries to access the form, the form doesn't always exist. The first time through the loop is fine. This goes to the ErrorHandler and everything works well. The second time it passes and cannot find the form, the "End / Debug" field appears in it. I can't figure out why it doesn't just fit the ErrorHandler. Any suggestions?
a source to share
First of all, you have a for loop with three iterations, and you have a case of switching to three !. why can't you move your shared code to a new function and call it three times?
And what's more, each error has a unique number (taking into account VBA errors such as Subscript out of range, etc., or a description if its general number, such as 1004 and other service errors). You need to check the error number and then decide how to proceed if you skip a part or work.
Read this code. I have moved your comon code to a new function and in this function we will resize the form. If there is no form, we will simply return false and move on to the next form.
'i am assuming you have defined drnme, nme as strings and d1 as integer
'if not please do so
Dim drnme As String, nme As String, d1 As Integer
dl = 20
drnme = kt + " 90"
nme = "door90"
If ResizeShape(drnme, nme, d1) Then
d1 = d1 + 160
End If
'Just call
'ResizeShape(drnme, nme, d1)
'd1 = d1 + 160
'If you don't care if the shape exists or not to increase d1
'in that case whether the function returns true or false d1 will be increased
drnme = kt + " dec"
nme = "door70" 'decorative glazed'
If ResizeShape(drnme, nme, d1) Then
d1 = d1 + 160
End If
drnme = kt + " gl"
nme = "door80" 'plain glazed'
If ResizeShape(drnme, nme, d1) Then
d1 = d1 + 160
End If
ActiveSheet.Shapes("Txtdoors").Select
Selection.Characters.Text = kt & ": " & kttxt
Worksheets("kts close").Protect Password:="UPS"
End Sub
'resizes the shape passed in.
'if the shape does not exists then returns false.
'in that case you can skip incrementing d1 by 160
Public Function ResizeShape(drnme As String, nme As String, d1 As Integer) As Integer
On Error GoTo ErrorHandler
Dim sh As Shape
Set sh = Worksheets("kitchen doors").Shapes(drnme)
sh.Copy
ActiveSheet.Paste
Selection.ShapeRange.Name = nme
Selection.ShapeRange.Top = 50
Selection.ShapeRange.Left = dl
Selection.ShapeRange.Width = 150
Selection.ShapeRange.Height = 220
Exit Function
ErrorHandler:
'Err -2147024809 will be raised if the shape does not exists
'then just return false
'for the other errors you can examine the number and go back to next line or the same line
'by using Resume Next or Resume
'not GOTO!!
If Err.Number = -2147024809 Or Err.Description = "The item with the specified name wasn't found." Then
ResizeShape = False
Exit Function
End If
End Function
a source to share
Sorry I worked out a solution. Clearing the error code didn't work, so I had to use multiple GOTOs instead and the code now works (even if it's not the most elegant solution). Below is my new code:
dl = 20
For dnme = 1 To 3
BeginLoop:
Select Case dnme
Case 1
drnme = kt + " 90"
nme = "door90"
drnme1 = nme
Case 2
drnme = kt + " dec"
nme = "door70" 'decorative glazed'
Case 3
drnme = kt + " gl"
nme = "door80" 'plain glazed'
Case Else
GoTo EndLoop
End Select
On Error GoTo ErrorHandler
Set sh = Worksheets("kitchen doors").Shapes(drnme)
sh.Copy
ActiveSheet.Paste
Selection.ShapeRange.Name = nme
Selection.ShapeRange.Top = 50
Selection.ShapeRange.Left = dl
Selection.ShapeRange.Width = 150
Selection.ShapeRange.Height = 220
25
dl = dl + 160
Next dnme
EndLoop:
ActiveSheet.Shapes("Txtdoors").Select
Selection.Characters.Text = kt & ": " & kttxt
Worksheets("kts close").Protect Password:="UPS"
Exit Sub
ErrorHandler:
Err.Clear
dl = dl + 160
dnme = dnme + 1
Resume BeginLoop
End Sub
a source to share
OMG - you shouldn't use gotos to enter and exit a loop !!!
If you want to handle the error yourself, you use something like this:
''turn off error handling temporarily
On Error Resume Next
''code that may cause error
If Err.Number <> 0 then
''clear error
Err.clear
''do stuff to handle error
End if
''resume error handling
On Error GoTo ErrorHandler
EDIT - try this - not a messy GOTOS
dl = 20
For dnme = 1 To 3
Select Case dnme
Case 1
drnme = kt + " 90"
nme = "door90"
drnme1 = nme
Case 2
drnme = kt + " dec"
nme = "door70" 'decorative glazed'
Case 3
drnme = kt + " gl"
nme = "door80" 'plain glazed'
End Select
'temporarily disable error handling'
On Error Resume Next
Set sh = Worksheets("kitchen doors").Shapes(drnme)
'save error'
ErrNum = Err.Number
'reset error handling'
On Error GoTo ErrorHandler
If ErrNum = 0 Then
sh.Copy
ActiveSheet.Paste
Selection.ShapeRange.Name = nme
Selection.ShapeRange.Top = 50
Selection.ShapeRange.Left = dl
Selection.ShapeRange.Width = 150
Selection.ShapeRange.Height = 220
End If
dl = dl + 160
Next dnme
ActiveSheet.Shapes("Txtdoors").Select
Selection.Characters.Text = kt & ": " & kttxt
Worksheets("kts close").Protect Password:="UPS"
NormalExit:
Exit Sub
ErrorHandler:
MsgBox "Error Occurred: " & Err.Number & " - " & Err.Description
Exit Sub
End Sub
a source to share