Is this right? Sub SomeSub() Dim oDim As AcadEntity Dim vpt As Variant 'line label Choice: 'here's where I want to handle a certain error possibility On Error GoTo errhand '--------------question ------------------------------------------ 'or does On Error go before line label? '--------------question ------------------------------------------ ThisDrawing.Utility.GetEntity oDim, vpt, "Select dimension to OK" While Not TypeOf oDim Is AcadDimension ThisDrawing.Utility.GetEntity oDim, vpt, "Not a dimension, Select dimension to OK" Wend '--------------question ------------------------------------------ 'does this go here to clear out the error handling??? '(so that if other errors are encountered they just bomb the routine) On Error GoTo 0 '--------------question ------------------------------------------ '''---------rest of routine----------- '''and at end of sub there's the error handler '------------------------------ errhand: If UserEscaped Then 'UserEscaped is function that returns t or f (esc key) Exit Sub Else Go To Choice End If '------------------------------ If Not oDim is Nothing then Set oDim = Nothing End Sub I've never been clear on how to use "on Error goto 0" or where to put it in the program flow I'm also not clear on whether OnError statements are 'localized' to the sub in which they occur or if they can 'spill over' into following subs or routines that may follow in a larger program ie I've seen posts (mostly TT) that said On Error Resume Next is the wrong way to go about it because it can mask other errors. So I'm trying to figure out how to handle a specific error condition, then reset so as to let errors be "seen" if they occur after the special section where I "expect" an error. tia Mark
You have the framework pretty close. I would put the statement On Error GoTo errhand before the looping construct's label. On Error GoTo 0 does clear the error handler. An error handler defined in an upper level procedure will still be active in a subr if the subr does not redefine the error handler. See below code as a sample. Step thru Test and notice the results in the Immediate window. Then run just the RunSubTest procedure by itself and notice what happens. Also experiment with placing On Error GoTo 0 before the call to the subr, and also create a error handler for the subr. Sub Test() On Error GoTo oops Debug.Print "ok code" Err.Raise 1 RunSubTest Exit Sub oops: Debug.Print "I ran!" Err.Clear Resume Next End Sub Private Sub RunSubTest() Debug.Print "sub ok code" Err.Raise 1 End Sub -- R. Robert Bell Is this right? Sub SomeSub() Dim oDim As AcadEntity Dim vpt As Variant 'line label Choice: 'here's where I want to handle a certain error possibility On Error GoTo errhand '--------------question ------------------------------------------ 'or does On Error go before line label? '--------------question ------------------------------------------ ThisDrawing.Utility.GetEntity oDim, vpt, "Select dimension to OK" While Not TypeOf oDim Is AcadDimension ThisDrawing.Utility.GetEntity oDim, vpt, "Not a dimension, Select dimension to OK" Wend '--------------question ------------------------------------------ 'does this go here to clear out the error handling??? '(so that if other errors are encountered they just bomb the routine) On Error GoTo 0 '--------------question ------------------------------------------ '''---------rest of routine----------- '''and at end of sub there's the error handler '------------------------------ errhand: If UserEscaped Then 'UserEscaped is function that returns t or f (esc key) Exit Sub Else Go To Choice End If '------------------------------ If Not oDim is Nothing then Set oDim = Nothing End Sub I've never been clear on how to use "on Error goto 0" or where to put it in the program flow I'm also not clear on whether OnError statements are 'localized' to the sub in which they occur or if they can 'spill over' into following subs or routines that may follow in a larger program ie I've seen posts (mostly TT) that said On Error Resume Next is the wrong way to go about it because it can mask other errors. So I'm trying to figure out how to handle a specific error condition, then reset so as to let errors be "seen" if they occur after the special section where I "expect" an error. tia Mark
Mark, Here is a sample of my standard error handling. Line labels don't do anything, they are just the location where the GoTo goes. So, anything below the label gets executed. OnError GoTo 0 is used to reset error handling after you have told it to simply to ignore an errror with the Resume Next statement. Inside the error handler, use Err.Clear to clear the current error before you jump back into your procedure again. Sub testing() On Error GoTo Err_Control 'normal procedure code goes here. Exit_Here: Exit Sub Err_Control: Select Case Err.Number 'Add your Case selections here 'Case Is = 1000 'Handle error 'Err.Clear 'Resume Exit_Here Case Else MsgBox Err.Number & ", " & Err.Description, , "testing" Err.Clear Resume Exit_Here End Select End Sub
I forgot to mention this part. Where Case = 1000, you could substitute any error number that your code might cause, e.g. the error number that would be encountered where you would have used Resume Next, or a custom error caused by Err.Raise. The Case Else part handles errors not caused by your procedure.
I'm real forgetful today...By putting the procedure name in the title of the msgbox, I can readily tell where in the code the error ocurred.
Mark, when it comes to GoTo you want to be careful. In structured programming languages the use of GoTo should be kept to a minimum because it can complicate and/or defeat your logic. From the code you posted you have a couple of spots that an error could potentially occur, which are at the calls to Utility.Get... Dependign on what you want to do I would consider putting each of them in a loop with an err handler in the loop. The Err object is great for this... Sub JUNK() On Error Resume Next Dim pt As Variant Dim obj As AcadEntity Do Err.Clear pt = ThisDrawing.Utility.GetPoint(, "Specify a point: ") Loop While Err Do Err.Clear ThisDrawing.Utility.GetEntity obj, pt, "Select a line: " If Not TypeOf obj Is AcadLine Then Err.Raise 1 Loop While Err End Sub There are a lot of ways to approach it, as you can see here I'm using On Error Resume Next, which isn't bad but you do have to be careful as it can mask other errors, just make sure you provide proper error handling (easily done using the Err object) to exit the routine if something unexpected happens. If you do use GoTo and a error handler make sure you add the line: Exit Sub prior to you error handler (as Ed has done above) otherwise that code will always run at the end of your routine. Regards, Jacob Dinardi
Thanks Jacob, The learning never ends! I have seen many references to *NOT* using GOTO as being one of the worst left overs from old days of basic lang. but i had also seen it presented as preferrable to Resume Next Thanks for your amplification of this process. in that regard, (just out of curiousity) in this line: "Loop While Err" - in my understanding (or rather lack thereof) the Err object always exists... so I assume that call is "auto-translated" by vb into Loop While Err.Number <> 0 is that true???? Mark programming languages the use of GoTo should be kept to a minimum because it can complicate and/or defeat your logic. potentially occur, which are at the calls to Utility.Get... Dependign on what you want to do I would consider putting each of them in a loop with an err handler in the loop. The Err object is great for this... Error Resume Next, which isn't bad but you do have to be careful as it can mask other errors, just make sure you provide proper error handling (easily done using the Err object) to exit the routine if something unexpected happens. always run at the end of your routine.
Hi MP Maybe this can be a sample how to work with 'On Error Resume Next': Code: Public Function MeGetReal() As Variant Dim RetVal As Variant On Error Resume Next With ThisDrawing.Utility .InitializeUserInput 6, "Select" RetVal = .GetReal(vbCrLf & "Please enter a value or [Select]: ") If Err.Number <> 0 Then If Err.Number = -2145320928 Then Err.Clear GetRealTest = .GetInput Else Err.Clear GetRealTest = vbEmpty End If Else GetRealTest = RetVal End If End With End Function Ceers
Sorry, typos... Code: Public Function MeGetReal() As Variant Dim RetVal As Variant On Error Resume Next With ThisDrawing.Utility .InitializeUserInput 6, "Select" RetVal = .GetReal(vbCrLf & "Please enter a value or [Select]: ") If Err.Number <> 0 Then If Err.Number = -2145320928 Then Err.Clear MeGetReal = .GetInput Else Err.Clear MeGetReal = vbEmpty End If Else MeGetReal = RetVal End If End With End Function Cheers
Mark, to answer your questions regarding the Err object; most objects have a default property meaning you don't have to explicitly access it, just use the object name. For the Err object the default property is the Number property (current error number). So if you type: debug.print Err You'll actually see the current value of the Number property. Another example of this is when using text boxes; the default property of the textbox object is Text, so both of the followng give the same result. debug.print Text1.Text debug.print Text1 Now onto using Do...While. The "While" portion of the loop continues to run the loop as long as the condition is True. You also need to know that since the While is looking for a boolean value (True/False) and the Err.Number gives a numeric value that a conversion takes place from numeric to boolean. When this happens: 0 = False all other numbers = True So these next to statements are equivalent: Loop While Err Loop While Err <> 0 as you stated. Hope that sheds some light on things for you. Regards, Jacob
Thank you Jacob, Right, the default property...i should have thought of that already...well i kind of did in the back of my mind .sort of!...whew - kind of musty back there...eech... That was an extremely clear explanation. Thank you. And thanks again to Jacob, RRBell, EdJobe, and Jurg Menzi for taking time to help me understand this process. It is much clearer now after reading everyones' tips several times and trying various combinations. Your ongoing help is much appreciated and extremely under-paid!!! Mark a default property meaning you don't have to explicitly access it, just use the object name. For the Err object the default property is the Number property (current error number). So if you type: example of this is when using text boxes; the default property of the textbox object is Text, so both of the followng give the same result. run the loop as long as the condition is True. You also need to know that since the While is looking for a boolean value (True/False) and the Err.Number gives a numeric value that a conversion takes place from numeric to boolean. When this happens: