In a Word I am running a macro which triggers Error dialog sometimes. In PHP there I am used to use #command syntax which causes that in case of error the error is not printed to the output. Is there something similar to prevent the VBA debugger stop working?
My code is
Documents.Add.Content.Paste
and I want to create code, which would test if the result is valid, without breaking the debugger and printing the error, In the case that it failed, I would create timer 1s, and try the command again.
Edit:
Current code:
On Error GoTo ErrHandler
Documents.Add.Content.Paste
If False Then
ErrHandler:
' Add a delay
Dim tmpStart
tmpStart = Timer
Do
DoEvents
Loop While (tmpStart + 1) > Timer
Documents.Add.Content.Paste
End If
Currently error happens at line #11: 4605 - property not available because clipboard is empty or damaged
In your sub-routine or function, insert as the first line:
On Error Resume Next
Or if you want to handle the error:
On Error Goto ErrHandler
If False Then
ErrHandler:
MsgBox Err.Description
Exit Sub ' Or Exit Function
End If
Related
Pretty much the question is the following - why in the immediate window I get this:
Application.EnableCancelKey = 2
?Application.EnableCancelKey
1
The last line should be 2 or am I missing something?
Thanks!
Edit:
The basis is that the enum xlErrorHandler states that "The interrupt is sent to the running procedure as an error, trappable by an error handler set up with an On Error GoTo statement.", you need an error handler to use that enum (xlErrorHandler or 2).
Since some statements are not possible within the immediate window, and On Error GoTo is one of these statements, you cannot have an error handler in the immediate window and thus change the value of the EnableCancelKey to 2. Hence Excel switches it automaticaly to 1, giving you the value 1 when you ask it to display the value.
The only solution would be to use a sub.
Original reply:
Ok, I used the code in the documentation provided on the MSDN and edited a few things to test it with the following code.
To explain shortly I stopped the execution by pressing just once the "ESC" button and thus preventing the textbox to be exited. You can watch in the Immediate Window that the last EnableCancelKey has changed in value normaly.
Sub Test1()
Debug.Print " Before execution result : " & Application.EnableCancelKey
On Error GoTo handleCancel
Application.EnableCancelKey = 2 'xlErrorHandler
Debug.Print " Regular execution result : " & Application.EnableCancelKey
For x = 1 To 10000 ' Do something 1,000,000 times (long!)
Debug.Print "Test"
Next x
handleCancel:
If Err = 18 Then
Debug.Print "Aborted macro result : " & Application.EnableCancelKey
MsgBox "You cancelled"
End If
End Sub
Hope this helps, I got the result expected.
You have to write an Error Handler to get the 2 value, else the code cannot catch the error, that's why you get the 1 every time you were executing the macro.
Since the description of the enum xlErrorHandler states that "The interrupt is sent to the running procedure as an error, trappable by an error handler set up with an On Error GoTo statement.", you need an error handler to use that enum.
With this it should work:
Sub test2()
On Error GoTo theEnd
Application.EnableCancelKey = 2
Debug.Print Application.EnableCancelKey
theEnd:
End Sub
In the below code Errorhandler correctly takes care of first error when I enter a workbook that is not open or any random string. But when I click on retry and again enter a random name I get "Subscript out of Range" error # Workbooks(workbookname). Activate.
Can anyone help me why it is happening and how can I make it work. I have tried a lot of things. But nothing is working. This code is part of a larger program.
Sub test()
Dim workbkname As String
On Error GoTo Errorhandler
Retry:
workbookname = InputBox("Enter workbook name:", _
"Name Enrty")
If StrPtr(workbookname) = 0 Then
MsgBox ("Aborting Program")
End
End If
Workbooks(workbookname).Activate
Exit Sub
Errorhandler:
Response = MsgBox("Workbook " & workbookname & " not found", vbRetryCancel)
If Response = 4 Then
GoTo Retry
End If
End Sub
The issue here is that the VBA Error Handler does not clear the error once given a directive like GoTo. As a result, the code thinks that it has encountered an error within your error handling routine and thus throws the error up the stack.
In order to clear the error, you must either call Resume with a place to resume (either Resume alone to run the erroneous code again, Resume Next to resume the line of code following the error, or Resume can be called followed by a label, as below:
Sub ErrTest
On Error Goto ErrHndl
For i = 0 to 5
a = 1/i
nextiLabel:
Next i
Exit Sub
ErrHndl:
Resume nextiLabel
End Sub
You can also use Err.Clear() to remove the error, but that is less recommended.
See here for more info: Error Handling in Excel
I have a very simple VBA code that should try to open a nonexistent file, send me to an error handler, then back to my code in an infinite loop (intentionally).
However, the compiler only catches the error the first time, then breaks on the second pass.
I have tried every combination of On Error statements to send it back on the second pass, but nothing seems to work.
Here is the code:
Sub TestError()
On Error GoTo errError
lblError:
On Error GoTo errError
'Code that should raise an error and send to errError
Excel.Application.Workbooks.Open ("lakdfjldkj")
Exit Sub
errError:
MsgBox "Code didn't break"
GoTo lblError
End Sub
Is there something I'm missing, or is this a bug?
Don't test this unless you are at peace with having to kill Excel, or add an extra condition for looping
Use Resume to... well... resume processing after the error handler.
Sub TestError()
On Error GoTo errError
'Code that should raise an error and send to errError
Excel.Application.Workbooks.Open "lakdfjldkj"
Exit Sub
errError:
MsgBox "Code didn't break"
Resume
End Sub
I have used code like this to access a certain worksheet, if it is not found then the error handler creates one with the correct name and then resumes the processing.
You need to clear the error message by using:
Err.Clear
Source: https://msdn.microsoft.com/en-us/library/hh2zczch(v=vs.90).aspx
Basically it still thinks you're handling the error, and hasn't reset the handling mechanism, so it doesn't re-trigger until you clear it.
(Resume also clears the Error as well, as you can note by the reference above).
I have tested, it is possible to type :
Resume label1 (line label)
Resume next
Resume 110 (line number)
Is a Resume always required after On Error handling ? Would it cause stack error to skip it by supressing the Resume line in the below example ?
Sub MySub
on error goto Hell
DoThis
DoThat
Otherstuff
Adios:
Exit Sub
Hell:
MsgBox Err.Description, vbCritical, "Error " & Err.Number
Resume Adios 'is this line required ?
Exit Sub
The Resume statement instructs VBA to resume execution at a specified point in the code. You can use Resume only in an error handling block; any other use will cause an error. Moreover, Resume is the only way, aside from exiting the procedure, to get out of an error handling block. Do not use the Goto statement to direct code execution out of an error handling block. Doing so will cause strange problems with the error handlers.
The Resume statement takes three syntactic form:
Resume
Resume Next
Resume <label>
Used alone, Resume causes execution to resume at the line of code that caused the error. In this case you must ensure that your error handling block fixed the problem that caused the initial error. Otherwise, your code will enter an endless loop, jumping between the line of code that caused the error and the error handling block. The following code attempts to activate a worksheet that does not exist. This causes an error (9 - Subscript Out Of Range), and the code jumps to the error handling block which creates the sheet, correcting the problem, and resumes execution at the line of code that caused the error.
On Error GoTo ErrHandler:
Worksheets("NewSheet").Activate
Exit Sub
ErrHandler:
If Err.Number = 9 Then
' sheet does not exist, so create it
Worksheets.Add.Name = "NewSheet"
' go back to the line of code that caused the problem
Resume
End If
The second form of Resume is Resume Next . This causes code execution to resume at the line immediately following the line which caused the error. The following code causes an error (11 - Division By Zero) when attempting to set the value of N. The error handling block assigns 1 to the variable N, and then causes execution to resume at the statement after the statement that caused the error.
On Error GoTo ErrHandler:
N = 1 / 0
Debug.Print N
Exit Sub
ErrHandler:
N = 1
' go back to the line following the error
Resume Next
The third form of Resume is Resume <label>: . This causes code execution to resume at a line label. This allows you to skip a section of code if an error occurs. For example,
On Error GoTo ErrHandler:
N = 1 / 0
code that is skipped if an error occurs
Label1:
more code to execute
Exit Sub
ErrHandler:
go back to the line at Label1:
Resume Label1:
All forms of the Resume clear or reset the Err object.
found this on
http://www.cpearson.com/excel/errorhandling.htm
Resume is not required you can call it if you like. Leaving it out of the example above will not cause any problems - the subroutine will just complete at the final Exit Sub.
I have writen some code in VBA (Excel) with error handling labels. It worked fine until I recently notice the error handling code gets executed everytime, not just when an error occurs. Does anybody know why this happens? Thanks.
Here's a trivial test case where both msgboxes would pop up.
Sub example()
On Error GoTo err_handle
MsgBox "OK!"
err_handle:
MsgBox "not OK"
End Sub
You want to add an Exit Sub to your routine:
Sub example()
On Error GoTo err_handle
MsgBox "OK!"
Exit Sub
err_handle:
MsgBox "not OK"
End Sub
Look here for a full explaination.
It's because you aren't returning out of the subroutine after the first message box the (OK) one. After that is shown the next line of code is executed which is the "not ok" message.
You could either exit the subroutine early before your error handler label (ExitSub) or goto the end of the subroutine on success (bypassing the "error" routine)
need to add exit sub else the program continues to execute the label as it is the part of the code
Just as a clarification to add some meat to the other answers.
"err_handle:" is only error handling code because you are using it as such. It isn't intrinsically an error handler like a catch block in other languages.
Technically "err_handle:" is just a label that facilitates a goto jump. In your case the goto just happens to be used with an error handler (on error goto)
The generally accepted pattern for error handling is to have an error handler and an exit procedure. A pretty standard code stump might look like this:
Public Function Example() As String
Dim strRtnVal As String 'Return value variable.
On Error GoTo Err_Hnd
'***************************************************************************
'Lock interface code here (hourglass, screenupdating etc.)
'***************************************************************************
'***************************************************************************
'Your code here.
'***************************************************************************
Exit_Proc:
'Prevents "Error Loops" caused by errors within the exit procedure:
On Error Resume Next
'***************************************************************************
'Restore Interface.
'***************************************************************************
Example = strRtnVal 'Set Return Value.
Exit Function
Err_Hnd:
'Display message, do some logging, whatever.
Resume Exit_Proc '<- Run exit procedure.
End Function