Error Handling section codes execution in VBA - excel

I'm Writing a macro program, in that I need to show custom error message if error occurs, I'm facing a problem here. Error handing is working correctly. but the codes in error handling section are executing even though the error not occurred
On Error GoTo ErrorHandling
Source_File_Path = "G:\" & Source_File_name & ".csv"
Open Source_File_Path For Input As #1
On Error GoTo 0
.
.
.
ErrorHandling:
Worksheets("REPORT_VIEW").Activate
MsgBox "FILE NOT FOUND"
I'm seeing the "FILE NOT FOUND" Error on every time.
Help Me., Cheers...

You need to add an Exit sub statement (or Exit Function if you code is from a function). for instance:
sub MySub()
On Error GoTo ErrorHandling
Source_File_Path = "G:\" & Source_File_name & ".csv"
Open Source_File_Path For Input As #1
On Error GoTo 0
.
.
Exit sub
ErrorHandling:
Worksheets("REPORT_VIEW").Activate
MsgBox "FILE NOT FOUND"
end sub

Related

Skip macro if it is not present in Excel using VB script [duplicate]

I want to use VBScript to catch errors and log them (ie on error "log something") then resume the next line of the script.
For example,
On Error Resume Next
'Do Step 1
'Do Step 2
'Do Step 3
When an error occurs on step 1, I want it to log that error (or perform other custom functions with it) then resume at step 2. Is this possible? and how can I implement it?
EDIT: Can I do something like this?
On Error Resume myErrCatch
'Do step 1
'Do step 2
'Do step 3
myErrCatch:
'log error
Resume Next
VBScript has no notion of throwing or catching exceptions, but the runtime provides a global Err object that contains the results of the last operation performed. You have to explicitly check whether the Err.Number property is non-zero after each operation.
On Error Resume Next
DoStep1
If Err.Number <> 0 Then
WScript.Echo "Error in DoStep1: " & Err.Description
Err.Clear
End If
DoStep2
If Err.Number <> 0 Then
WScript.Echo "Error in DoStop2:" & Err.Description
Err.Clear
End If
'If you no longer want to continue following an error after that block's completed,
'call this.
On Error Goto 0
The "On Error Goto [label]" syntax is supported by Visual Basic and Visual Basic for Applications (VBA), but VBScript doesn't support this language feature so you have to use On Error Resume Next as described above.
Note that On Error Resume Next is not set globally. You can put your unsafe part of code eg into a function, which will interrupted immediately if error occurs, and call this function from sub containing precedent OERN statement.
ErrCatch()
Sub ErrCatch()
Dim Res, CurrentStep
On Error Resume Next
Res = UnSafeCode(20, CurrentStep)
MsgBox "ErrStep " & CurrentStep & vbCrLf & Err.Description
End Sub
Function UnSafeCode(Arg, ErrStep)
ErrStep = 1
UnSafeCode = 1 / (Arg - 10)
ErrStep = 2
UnSafeCode = 1 / (Arg - 20)
ErrStep = 3
UnSafeCode = 1 / (Arg - 30)
ErrStep = 0
End Function
You can regroup your steps functions calls in a facade function :
sub facade()
call step1()
call step2()
call step3()
call step4()
call step5()
end sub
Then, let your error handling be in an upper function that calls the facade :
sub main()
On error resume next
call facade()
If Err.Number <> 0 Then
' MsgBox or whatever. You may want to display or log your error there
msgbox Err.Description
Err.Clear
End If
On Error Goto 0
end sub
Now, let's suppose step3() raises an error. Since facade() doesn't handle errors (there is no On error resume next in facade()), the error will be returned to main() and step4() and step5() won't be executed.
Your error handling is now refactored in 1 code block
I'm exceptionally new to VBScript, so this may not be considered best practice or there may be a reason it shouldn't be done this that way I'm not yet aware of, but this is the solution I came up with to trim down the amount of error logging code in my main code block.
Dim oConn, connStr
Set oConn = Server.CreateObject("ADODB.Connection")
connStr = "Provider=SQLOLEDB;Server=XX;UID=XX;PWD=XX;Databse=XX"
ON ERROR RESUME NEXT
oConn.Open connStr
If err.Number <> 0 Then : showError() : End If
Sub ShowError()
'You could write the error details to the console...
errDetail = "<script>" & _
"console.log('Description: " & err.Description & "');" & _
"console.log('Error number: " & err.Number & "');" & _
"console.log('Error source: " & err.Source & "');" & _
"</script>"
Response.Write(errDetail)
'...you could display the error info directly in the page...
Response.Write("Error Description: " & err.Description)
Response.Write("Error Source: " & err.Source)
Response.Write("Error Number: " & err.Number)
'...or you could execute additional code when an error is thrown...
'Insert error handling code here
err.clear
End Sub
What #cid provided is a great answer. I took the liberty to extend it to next level by adding custom throw handler (like in javascript). Hope someone finds its useful.
option Explicit
Dim ErrorCodes
Set ErrorCodes = CreateObject("Scripting.Dictionary")
ErrorCodes.Add "100", "a should not be 1"
ErrorCodes.Add "110", "a should not be 2 either."
ErrorCodes.Add "120", "a should not be anything at all."
Sub throw(iNum)
Err.Clear
Dim key
key = CStr(iNum)
If ErrorCodes.Exists(key) Then
Err.Description = ErrorCodes(key)
Else
Err.Description = "Error description missing."
End If
Err.Source = "Dummy stage"
Err.Raise iNum 'raise a user-defined error
End Sub
Sub facade(a)
if a=1 then
throw 100
end if
if a = 2 then
throw 110
end if
throw 120
End Sub
Sub Main
on error resume next
facade(3)
if err.number <> 0 then
Wscript.Echo Err.Number, Err.Description
end if
on error goto 0
End Sub
Main

Indentation of Error Handler in Excel VBA

This is a very fussy question: I am inserting an Error Handler in a For To loop in Excel VBA; I want the content of the loop indented, such that:
For i = 0 to n
On Error GoTo ErrorHandler:
'~~> code here
ErrorHandler:
'~~> code here
Resume NextLoop
NextLoop:
Next
However, Excel VBA automatically cancels indentation of Error Handlers:
For i = 0 to n
On Error GoTo ErrorHandler:
'~~> code here
ErrorHandler:
'~~> code here
Resume NextLoop
NextLoop:
Next
I have tried to unselect option "Auto Indent" in "Tools" > "Options" > "Editor" but this hasn't worked.
How can I avoid this?
Edit There was a careless mistake in the original code. Thank you user2426679 for giving me the opportunity to fix it.
Original post
Code that uses GoTo Label can be a nightmare to understand and get error free. The only situation I know off in which GoTo Label might be appropriate is a fatal error exit where there is no intention to return. Jumping out of an error and trying to jump back is very difficult to get right and very difficult to understand when you return to it in a few months.
Is there more than one statement in your code that can throw an error? If so, how does the error handler know which error it is handling?
I favour:
On Error Resume Next ' Suspend normal error handling
Statement that might throw an error
On Error GoTo 0 ' Restore normal error handling
If Err.Number <> 0 then
' Code to handle error
End If
The value of Err.Number and Err.Description will tell what the error is and allow to write specific error handling code.
Some argue that taking error handling out of the main code keeps the main code clean. There is some merit in this argument. If there are dozens of potential errors, the analysis can become complicated and make the normal path difficult to isolate. But, in my experience, this is very unusual. Perhaps, you have a list of files some of which might not open. There are lots of reasons why a file does open but your code can do nothing about them. All it can do is display Err.Description and move onto the next file.
New text and code
Apart from the mistake in the code there is nothing in my original post that I now consider incorrect. However, I do not think the original post was as complete as it should be.
If you search for “VBA Err.Number” you will find sites that list VBA’s error handling codes. Since these sites come and go, I will not recommend my favourite. However, I try to generate errors to see what happens. Consider this code:
Option Explicit
Sub DemoErrorHandling()
Dim ErrDesc As String
Dim ErrNum As Long
Dim FileNum As Long
Dim PathFile As Variant
FileNum = FreeFile
For Each PathFile In Array("", "X:", "C:\Program Files\Common Files\Intel\" & _
"WirelessCommon\libeay32.dll")
On Error Resume Next
Open PathFile For Input As FileNum
ErrNum = Err.Number
ErrDesc = Err.Description
Close FileNum
On Error GoTo 0
Debug.Print """" & PathFile & """ gives error:"
Debug.Print " A " & Err.Number & " " & Err.Description
Debug.Print " B " & ErrNum & " " & ErrDesc
Next
End Sub
Which, on my system, outputs:
"" gives error:
A 0
B 75 Path/File access error
"X:" gives error:
A 0
B 76 Path not found
"C:\Program Files\Common Files\Intel\WirelessCommon\libeay32.dll" gives error:
A 0
B 0
Note, as user2426679 pointed out, On Error GoTo 0has cleared Err.Number and Err.Description. Only by saving these values in variables are they available for testing. Note, attempting to open an empty file name and a non-existent disc give different errors.
My code demonstrates that you can loop trying different files until one opens successfully. You could keep asking the user for a file until one opened without an error.

vbscript runs in excel but not in notepad

Following script runs successfully in excel but throws syntax error when executed through .vbs file or in winautomation. I'm new to vb, please help.
Sub Test()
sUser = "TheUserName"
sDN = "uid=" & sUser & ",o=users,dc=MyDomain,dc=it"
sRoot = "LDAP://MyLDAPServer/o=users,dc=MyDomain,dc=it"
Dim oDS: Set oDS = GetObject("LDAP:")
On Error GoTo AuthError
Dim oAuth: Set oAuth = oDS.OpenDSObject(sRoot, sDN, "ThePassword", &H200)
On Error GoTo 0
MsgBox "Login Successful"
Exit Sub
AuthError:
If Err.Number = -2147023570 Then
MsgBox "Wrong Username or password !!!"
End If
On Error GoTo 0
End Sub
From Handling Errors in VBScript.
There is little difference between the methods used in Visual Basic and those used with VBScript. The primary difference is that VBScript does not support the concept of error handling by continuing execution at a label. In other words, you cannot use On Error GoTo in VBScript. Instead, use On Error Resume Next and then check both Err.Number and the Count property of the Errors collection, as shown in the following example: (example not provided here - use link for example)
So you will require your own error handling code section.
On Error Resume Next
Dim oAuth: Set oAuth = oDS.OpenDSObject(sRoot, sDN, "ThePassword", &H200)
Select Case Err.Number
Case 0:
'ERROR_SUCCESS - do nothing
Case -2147023570
MsgBox Err.Number & ": " & Err.Description &Chr(10) & "Wrong Username or password !!!"
Err.Clear
Exit Sub
Case Else
'deal with other errors
MsgBox Err.Number & ": " & Err.Description
Err.Clear
Exit Sub
End Select
More on getting error information at Information.Err Method.

Error Handling doesn't handle

I have written an excel VBA script which refers to another open excel document for some of it's data. Recently it has come to my attention that if this secondary document is closed unexpectedly by the user, the primary script ceases to work. Obviously, I need to check to be sure it is open before I search it.
Below is the code I came up with to verify that the workbook is open. If it is, I format it. If it isn't, I open it (which triggers it's own formatting). The problem comes in because my error handler catches the "Object required" error number 424. I try to take care of that by instructing it to just resume next when this happens. Unfortunately it seems to want to pick case else rather than case 424 and stops the script.
On Error GoTo searchGridsError
GridName = Workbooks(SALTname).Sheets(2).Range("B3").value
If Verify.FirstOption.value = True Then
Set Verify.groupGrid = Workbooks(GridName)
If Verify.groupGrid Is Nothing Then
Verify.checkForGrids
Else
formatWorkbook
End If
End If
Below is my error handler:
searchGridsError:
Select Case Err
Case 18
Verify.clearData
Exit Function
Case 424
Resume Next
Case Else
MsgBox "An error has occurred while searching the customer number grid. Please try again or search manually."
Module1.ReportError Err.Number, Erl, Err.Description, "searchGrids", Verify.Address1Box & "," & Verify.Address2Box & "," & Verify.CityBox & "," & Verify.StateBox & "," & Verify.ZipBox & "," & Verify.ContractBox & "," & Verify.PBPBox & "," & Verify.CountyBox
Verify.clearData
Exit Function
End Select
End Function
Does anyone have any ideas about why this is happening? It has to be in the error handler but I have seen many, many examples that look just like mine.
As guitarthrower stated in the comments, simply putting Resume Next in your error handling does not resume your macro back where the error occurred. To do that you would need to put another placeholder after your On Error GoTo searchGridsError line like RestartHere: where you want to jump back to and then replace Resume Next with:
On Error Resume Next
GoTo RestartHere
However, this will bypass your error handling once Error 424 is encountered, so you should be wary of how it is used.
Probably a better solution would be to put your error handling right in your code where you expect the error to occur. You can leave your code mostly as-is. However, right before the line that is throwing Error 424, you add On Error Resume Next. Then after the line in question, you add the following:
If Err.Number = 424 Then
Err.Clear
End If
On Error GoTo searchGridsError

VBA: Displaying the standard run-time error handler

I have a question about the correct way to handle errors in VBA in Excel. If a specific error, say xxxxxxx, occurs, then a MsgBox should be displayed. If another error occurs the standard run-time error handler should pop up. How can this be accomplished? Here is the example code:
On Error Resume Next
'Line of code that causes an error here.
If Err.Number = xxxxxxx Then
MsgBox "Specific error message."
ElseIf Err.Number = 0 Then
Do nothing
Else 'Some error other than xxxxxxx.
'This is the problem. Here I would like to display standard run-time error
'handler without causing the error again.
End If
On Error GoTo 0
You can get a message box that looks very much like the standard error message by putting this into your "Else" block:
MsgBox "Run-time error '" & Err.Number & "':" & _
vbNewLine & vbNewLine & _
Error(Err.Number), vbExclamation + vbOKOnly, _
"YourProjectNameHere"
But this is just a facsimile. It's not the actual error message dialog that VB6 puts up; it's just formatted to look like it. Error handling is still disabled by the "On Error Resume Next" statement at this point.
But if you really, really want to invoke the standard error handling code, you can put this in the "Else" block:
Dim SaveError As Long
SaveError = Err.Number
On Error Goto 0
Error (SaveError)
This code saves the error number, re-enables error handling, and then re-raises the error. You invoke the VB runtime's true error handling machinery this way. But beware: if this error isn't caught with an active error handler somewhere higher in the call chain, it will terminate your program after the user clicks on the "OK" button.
Note that you'll also lose the ability to get the actual line number where the error occurs using" Erl" in that error handler because you are re-generating the runtime error with the "Error (SaveError)" statement. But that probably won't matter because most VB code doesn't actually use any line numbers, so Erl just returns 0 anyway.
Replace On Error Resume Next with
On Error Goto SomePlaceInCodeToHandleErrors
SomePlaceInCodeToHandleErrors:
If Err.Number = XXXX Then
MSGBOX "Message"
End If
Check out this Stack Overflow thread for some more information and example code.
In your VBA options, select "Break on unhandled errors".
To enable handling use on error goto SomeLabel or on error resume next.
To stop error handling use on error goto 0.
Your question is contradictory in this context. If you enable error handling, well, you disable the standard error handling.
As DaMartyr suggests, you can still use something like msgbox err.description.
So to follow up on JeffK's new suggestion the code below seems to work fine with VBA, and what's more I can't see the danger in using it. To terminate Excel is critical as that could lose a lot of work, but since the code always checks that the error is there how could that happen?
Thank you JeffK for this intriguing idea.
Dim savedNumber As Long
On Error Resume Next
'Line of code that causes an error.
If Err.Number = XXXXXXX Then
'Specific error message.
ElseIf Err.Number <> 0 Then
savedNumber = Err.Number
On Error GoTo 0
Error savedNumber
End If
Err.Clear
On Error GoTo 0

Resources