tags:

views:

2256

answers:

5

Hi, I am having a bit of trouble with errors occurring in a loop in VBA. First, 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 shape, the shape doesn't always exist. The first time through the loop, this is fine. It goes to the ErrorHandler and everything works good. The second time it goes through and can't find the shape, it comes up with the "End/Debug" error box. I can't work out why it doesn't just go straight to the ErrorHandler. Any suggestions?

A: 

Sorry everyone, I have worked out a solution. Clearing the error code didn't work, so I had to use a number of GOTOs instead, and now the code works (even if it isn't 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_m0d
A: 

You can't have two different ShapeRange objects with the same name on the same Worksheet. Is there a chance that one of the existing Shape objects that gets copied is a member of a ShapeRange with the same name as one of the new ShapeRange objects that you are creating?

barrowc
No, all of these are unique names. The only objects with the same names are shape ranges that I am not concerned with any way.
a_m0d
A: 

OMG - you should not be using gotos to get in and out of a loop!!!

If you want to handle an 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 - no 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
DJ
I have tried using Err.clear but it didn't work - I added a watch on Err and saw that it did indeed clear - but when it reached the line that was concerning me, it still didn't jump to the error handler.
a_m0d
You are going about it backwards - you are going though all kinds of contortions to get you program flow back after an error. If you use On Error Resume Next before your problem line you can handle the error yourself and continue on in a much more controlled fashion...
DJ
Yes, but the thing is that the error will occur quite often - I don't want to pop up a MsgBox every time that happens. I want to just silently handle the error by skipping over that image.
a_m0d
That's what the On Error Resume Next does - it skips over the error
DJ
+1  A: 

First of all you have a for loop with only 3 iterations, and you have a switch case for three!!. why can't you move your common code to a new function and call it thrice?

And more over each error has a unique number (incase of VBA errors like Subscript out of range etc, or a description if its a generic number like 1004, and other office errors). You need to check the error number, then decide how to proceed, if to skip the part or work around.

Please go through this code..I have moved your comon code to a new function, and in that function we will be resizing the shape. If the shape is missing then we will just return false, and move to next shape.

'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
Adarsha
Okay, that looks like it will work - but you are only increasing d1 if ResizeShape returns true, whereas I want it increased no matter what - I don't care if the shape doesn't exist, coz then I just skip over it. Also, please note that this is not my own code - I am working with someone else's mess, so I don't really want to change too much. I just want to fix the bad code that he originally put in there and make it work with the changes I have had to make to the app.
a_m0d
I think that is self explanatory..Just replace If ResizeShape(drnme, nme, d1) Then d1 = d1 + 160End Ifwith ResizeShape(drnme, nme, d1)d1 = d1 + 160
Adarsha
Alright - used that code with only a few changes - I don't actually need a function, since it doesn't have to return anything, and there are a couple small typos in there (I hate it when 1's and l's are used together) but overall your code works great and eliminates the need for the horrible gotos. Thanks a lot!
a_m0d
A: 

I know this is an old post, but perhaps this will help someone else. Use the original code but replace ErrorHandler: GoTo 25

with

ErrorHandler: Resume 25