I am trying to create a high-quality ErrorHandler. I get run-time error 438:
Object doesn't support this property or method
Here's code:
Sub Function_asdf()
...
On Error GoTo ErrorHandler
...
ErrorHandler:
& vbNewLine & "Error" & Err.Number & Err.line & Err.Description
Like that, you're doing nothing. You're trying to start a chain of strings, but this starts with a join operator (&) which is not connecting to any "first" part, and even if it was it's neither assigned to a variable nor shown into a dialog box.
Start by showing that into a MsgBox :
MsgBox vbNewLine & "Error" & Err.Number & Err.line & Err.Description
or assigning it to a variable first:
Dim errMsg As String
errMsg = vbNewLine & "Error" & Err.Number & Err.line & Err.Description
and then printing it:
Debug.Print errMsg
or logging it into a cell
Range("A1") = errMsg
or in a MsgBox
MsgBox errMsg
... and don't forget to specify on which line you're raising the exception (here it's clear, but it's not always evident) cause it would be impossible for someone to debug without knowing in which point of your code the exception is thrown.
EDIT - I've finally run your code
So, I've run your code and the error is raised because the object Err (i.e. the exception thrown) does not have the property Line. It might have been deprecated, or just never existed.
If you wanted to return the line on which the error occurs, use the ERL property:
MsgBox vbNewLine & "Error" & Err.Number & Erl & Err.Description
Related
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
I have the following code working without any issues, but I can't seem to figure out how to make it work with an On Error
row_num2 = Evaluate("MATCH(1,('" & ws1.Name & "'!A:A=""" & variable1 & """)*('" & ws1.Name & "'!B:B=""" & variable2 & """)*('" & ws1.Name & "'!G:G=""" & variable3 & """),0)")
I've tired wrapping it with
On Error GoTo ErrMsg
ErrMsg:
MsgBox "error"
Exit Sub
This works fine if there is an error, but if it is correct then it still shows the "error" MsgBox and Exit's the Sub
The Application.Evaluate method does not throw an exception that you can catch with On Error … instead it returns an error value that can be tested with the IsError function.
If IsError(row_num2) Then
MsgBox "error in evaluate"
End If
As Mathieu suggested in his comment you can alternatively use
Application.WorksheetFunction.Match
which throws an exception that can be caught with On Error … or Application.Match that returns an error value for IsError.
See WorksheetFunction.Match method.
I have tried below code but i want to use MsgBox to display the error message (-2147217843)
Else
'Display errors..
For Each Err In objConn.Errors
Debug.Print Err.Description
Next
End If
Just use MsgBox function with vbCritical style.
Dim Msg, Style, Title
Style = vbOKOnly + vbCritical ' Define buttons.
Title = "Error" ' Define title.
Msg = "The following errors have been occurred:" ' Prepare message template.
' Build message.
For Each Err In objConn.Errors
Msg = Msg & vbNewLine & Chr(149) & " " & Err.Description
Next
Call MsgBox(Msg, Style, Title) ' Display error message
You could also use vbCrLf instead of vbNewLine new line character.
This is one google search away.
Msgbox(Err.Description)
Not sure how I can further enrich the answer with the current state of the question.
I have been figuring out how to pop up msg box if there is error. I have below code but this code does not jump to error handler if there is error and Exit the sub.
Sub Validate_Region()
Dim str_DEPARTMENT_NAME As String
On Error GoTo Reion_Error
If Left(Range("M4"), 2) = "As" Then
str_DEPARTMENT_NAME = "India"
ElseIf Left(Range("M4"), 2) = "ME" Then
str_DEPARTMENT_NAME = "Middle East"
End If
'Get value of region selected in Master File
str_regionvalue = Workbooks("Master Report").Sheets("Home").Range("T8")
If str_regionvalue = str_DEPARTMENT_NAME Then
MsgBox ("You have selected " & str_regionvalue & " region"), vbInformation
End If
Exit Sub
Reion_Error:
MsgBox ("Please select the correct Region.") & vbNewLine & vbNewLine & ("You have selected " & str_regionvalue & " region" & " In Home Sheet of Master Report and pulled the data for " & str_DEPARTMENT_NAME & " region"), vbCritical
ActiveWorkbook.Close
End Sub
I just copy/pasted your code and it works well for me:
I don't know from where this sub is called and what type of variable is used on str_regionvalue (seems like Variant)
So what can you do with this:
Get rid of Exit Sub on line #19.
Put Err.Number check in your error handler:
Reion_Error:
If Err.Number <> 0 Then
MsgBox ("Please select the correct Region.") & vbNewLine & vbNewLine & ("You have selected " & str_regionvalue & " region" & " In Home Sheet of Master Report and pulled the data for " & str_DEPARTMENT_NAME & " region"), vbCritical
'by the way, you can try to set ActiveWorkbook.Saved to True, to get rid from pop-ups on Close
ActiveWorkbook.Close
End If
Try to look for error number thru debugging (debug.print err.number or place some stop's to do this manually). Or add err.number to Watches and check Break when value changes so you can track where error raised and cleared (if raised).
Err object
P.S. You got some ridiculous MsgBoxes, if you really like parentheses, use them like this:
Call MsgBox("Please select the correct Region." & vbNewLine & vbNewLine & _
"You have selected " & str_regionvalue & " region" & " In Home Sheet of Master Report and pulled the data for " & str_DEPARTMENT_NAME & " region", vbCritical)
Under Tools >> Options in the VB Editor: on the General tab make sure you don't have "Error trapping" set to "Break on all errors"
Check your syntax, you have quite a few unnecessary brackets and commas in your msgbox statements. Try something like:
returnval = MsgBox ("Put message here" , vbInformation)
OR
MsgBox "another message " & vbnewline & "some more message", vbcritical
The code looks fine and compiles now but I think your error may be elsewhere. Possibly in:
str_regionvalue = Workbooks("Master report").Sheets("Home").Range("T8")
I'd suggest:
Leave the 'exit sub' in. It's correct.
Add 'Option Explicit' to the top of the code - it will force you to declare all variables (str_regionvalue isn't declared)
Set your Under Tools >> Options in the VB Editor: to 'Break on Unhandled Errors'.
Put in a breakpoint (Debug >> Add Watch) at the top of the code and run through it step by step using Debug >> Step Into.
I'm fixing the bellow error "datatable importsheet operation failed. Invalid file" using this way:
On error resume next
DataTable.ImportSheet Environment("STPFilePath"),Environment("TestScriptName"),"Action2"
If Err.Description = "The DataTable.ImportSheet operation failed. Invalid file." \n "Line (20): "DataTable.ImportSheet Environment("STPFilePath"),Environment("TestScriptName"),"Action2""." Then
list of instructions
end if
But I got this error:
The test run cannot continue due to a syntax error.
Expected 'Then'
Line (24): "If Err.Description = "The DataTable.ImportSheet operation failed. Invalid file." \n "Line (20): "DataTable.ImportSheet Environment("STPFilePath"),Environment("TestScriptName"),"Action2""." Then".
Everything looks right. Please any help ? where I'm wrong ?
I'm really struggling with what you are trying to do and your comments are not helping...
When using
On Error Resume Next
and you encounter an error while executing a statement the following things will happen;
The statement will be skipped and the script will move to the next statement and carry on execution.
The object Err will be populated with details of the error that caused the statement to be skipped.
The Err object is made up of a few key properties that describe the error that occurred;
Number - The Error Code of the error that was raised.
Source - The Source of the error that was raised, this can be 3rd party library, the VBScript Runtime etc.
Description - A free text description of the error.
If you want to check for error
The DataTable.ImportSheet operation failed. Invalid file.
when
DataTable.ImportSheet Environment("STPFilePath"),Environment("TestScriptName"),"Action2"
is executed you need to capture the Err.Number code that corresponds to that specific error.
Something like this;
On Error Resume Next
DataTable.ImportSheet Environment("STPFilePath"),Environment("TestScriptName"),"Action2"
'Check that an error occurs
If Err.Number <> 0 Then
'Identify specific error and deal with accordingly.
Select Case Err.Number
Case 20012 'Code for DataTable.ImportSheet operation failed
'List of instructions...
Case Else
'Unhandled error show to screen
MsgBox "Error: " & Err.Number & " (" & Err.Source & ") - " & Err.Description
End Select
'Finished handling the error
Call Err.Clear()
End If
What I find most confusing is the miss-information in this thread.
"I need the description and not the number and the problem is to use Err.Details and not Err.Description in my case. Now, it is working." - Ref
The Err object does not contain a property called Details unless this is something specific to QTP but so far I haven't been able to find anything with a quick Google Search. So how you can say "it is now working" is beyond me.
Basic rules:
Double Quotes (") are escaped by doubling ("")
No escapes like "\n" in VBScript string literals (concatenation (or replacement) needed)
The concatenation operator is &
Basic strategy: Simplify, Divide, and conquer:
>> s = "1" & vbCrLf & "-""pi""-"
>> t = "1" & vbCrLf & "-""pi""-"
>> WScript.Echo s
>> WScript.Echo t
>> If s = t Then
>> WScript.Echo "no surprise"
>> End If
>>
1
-"pi"-
1
-"pi"-
no surprise
>>
Added:
Applied to your string/error message:
's = "The DataTable.ImportSheet operation failed. Invalid file." \n "Line (20): "DataTable.ImportSheet Environment("STPFilePath"),Environment("TestScriptName"),"Action2""."
s = "1" & vbCrLf & "2: ""3(""4""),5(""6""),""7""."
WScript.Echo s
output:
cscript 39878005.vbs
1
2: "3("4"),5("6"),"7".
You are getting a syntax error because the double quotes in your if statement are not escaped.
I'm not sure what you are trying to do here and maybe using Err.Number makes more sense but if you want to avoid the syntax error then use this code:
If Err.Description = "The DataTable.ImportSheet operation failed. Invalid file."" \n ""Line (20): ""DataTable.ImportSheet Environment(""STPFilePath""),Environment(""TestScriptName""),""Action2""." Then
''' list of instructions
End If
Also, you cannot use \n if you want to compare 2 lines in if statement. Use CHR(13) or CHR(10) instead of \n. I.e.
If Err.Description = "The DataTable.ImportSheet operation failed. Invalid file."& CHR(13) &"Line (20): ""DataTable.ImportSheet Environment(""STPFilePath""),Environment(""TestScriptName""),""Action2""." Then
'''list of instructions
End If
Again: Using Err.Number will make more sense as any extra/missing space/newline in above If condition will fail the condition.
Try to Replace the Err.Description line with this
If Err.Description = "The DataTable.ImportSheet operation failed. Invalid file." & vbCrLf & "Line (20): DataTable.ImportSheet Environment(" & STPFilePath & "),Environment(" & TestScriptName & ")," & Action2 & "." Then
Good Luck.!