I have a code block as follow and need to change it to try catch.
Private test(a as String)
On Error GoTo ErrorHandler
Dim index as String
Statement1
Statement2
Done:
On Error Resume Next
Exit Sub
ErrorHandler:
If (a.equals("a")) Then
Resume
Else
Resume Done
End If
End Function
I looked through the official documentation
https://learn.microsoft.com/en-us/dotnet/visual-basic/language-reference/statements/resume-statement and was able to figure out that this can be written as :
Try
Dim index as String
Statement1
Statement2
Catch
If (a.equals("a")) Then
Resume (How do we replace this)
End If
End Try
Can someone guide me how do I replace the Resume statement?
Related
I need to write code that goes to a specific path and imports data from it,
then goes to another path and do the same.
I need that if path num 1 does not exist, it will jump direct to path num 2.
I wrote a sub for each path. there is a way to do something like:
if error goto sub ___ ?
Thanks in advance
Not directly, but you can do something like
On Error Goto error_sub1
and at the bottom of your function, write
error_sub1:
'ToDo - put your calling code here.
Elsewhere in you function you can switch the error handler to a different label:
On Error Goto error_sub2
and so on.
Try this:
Sub testSO()
On Error GoTo err
I=5/0
Exit Sub
err:
<your sub procedure here>
End Sub
Remember to include Exit Sub or else it will still run even without error!
Would it not be better to avoid the error in the first place and check whether the file exists before attempting to open it?
Sub Test()
Dim sFile1 As String
Dim sFile2 As String
Dim wrkBk As Workbook
On Error GoTo Error_Handler
sFile1 = "C:\Users\Desktop\MyFile1.xls"
sFile2 = "C:\Users\Desktop\MyFile2.xls"
If FileExists(sFile1) Then
Set wrkBk = Workbooks.Open(sFile1)
ElseIf FileExists(sFile2) Then
Set wrkBk = Workbooks.Open(sFile2)
Else
Err.Raise 513, , "File Not Found."
End If
wrkBk.Worksheets(1).Range("A1") = "Opened this file."
On Error GoTo 0
Fast_Exit:
'Any tidying up that needs doing.
Exit Sub
Error_Handler:
MsgBox Err.Description, vbExclamation + vbOKCancel, _
"Error: " & CStr(Err.Number)
Err.Clear
Resume Fast_Exit
End Sub
Public Function FileExists(ByVal FileName As String) As Boolean
Dim oFSO As Object
Set oFSO = CreateObject("Scripting.FileSystemObject")
FileExists = oFSO.FileExists(FileName)
End Function
Why does this not suppress errors?
For i = 1 To Last_row
On Error GoTo errorhandler1
Set wkb = Workbooks.Open(Filename:=l)
'' my code
errorhandler1:
next I
This is what I get:
Before we begin, your code is not set up properly for error handling.
I found that once the GoTo errohandler1 had been executed in the first instance, future calls were ignored so that's when the errors were thrown.
You current code is set up to ignore errors when opening workbooks, you can achieve this using Resume Next, and then GoTo 0 to reset the error handling method.
For i = 1 To Last_row
On Error Resume Next
Set wkb = Workbooks.Open(Filename:=l)
On Error GoTo 0
If Not wkb Is Nothing Then
'' my code
End If
next I
If you want to actually deal with errors -- rather than ignore them, you should do so outside of your loop (strongly encouraged!)
For i = 1 To Last_row
On Error GoTo CleanFail
Set wkb = Workbooks.Open(Filename:=l)
'' my code
next I
Exit Sub
CleanFail:
'deal with error
On Error GoTo is more than just some kind of conditional GoTo jump.
When the runtime encounters an error, it is in an error state that you need to clear up.
An error-handling subroutine isn't just a label code jumps to in case of error - it's where you handle runtime errors.
By jumping to the Next statement you make that next iteration occur in a runtime error state, because you didn't Clear the error state ...so execution resumes and all the while, as far as VBA runtime is concerned, the loop body itself becomes the error-handling subroutine: VBA is waiting for Err.Clear, or Resume Next, or any other statement that tells it "all good, error is handled, move along, nothing to see here".
errorhandler1:
Err.Clear
On Error GoTo 0
next i
That would fix the immediate problem, but still leave you with a quite convoluted spaghettish piece of code. Best extract the error-handling clean out of the "happy path".
Not sure why you can't bypass a file not found error...
Try using a sub function to return the open file (if found) instead?
Function GetWorkBook(ByVal sFullName As String, Optional ReadOnly As Boolean) As Workbook
Dim sFile As String: sFile = Dir(sFullName)
On Error Resume Next
Set GetWorkBook = Workbooks(sFile)
If GetWorkBook Is Nothing Then Set GetWorkBook = Workbooks.Open(sFullName, ReadOnly:=ReadOnly)
End Function
I am using below code, When user click on cancel button in the input box, the error is being handled by the error handler.
But if there is error again in the error handler then that error is not getting handled by the error handler.
Sub calculateroot()
Dim msg As String, t as Integer
On Error GoTo myhandle
Dim inp As Integer, sql As Single
inp = InputBox("Enter the number to find the square root")
sql = Sqr(inp)
Exit Sub
myhandle:
t = InputBox("Is this recursive ?")
End Sub
What changes should I make in the code to handle the error generated in error handler ?
You have to reset the error handler and then set a new one:
Sub calculateroot()
Dim msg As String, t As Integer
On Error GoTo myhandle
Dim inp As Integer, sql As Single
inp = inputbox("Enter the number to find the square root")
sql = Sqr(inp)
Exit Sub
myhandle:
On Error GoTo -1
On Error GoTo myhandle2
t = inputbox("Is this recursive ?")
MsgBox t
Exit Sub
myhandle2:
MsgBox "myhandle2"
End Sub
If you need to resume, this disgusting code works:
On Error Resume Next
parm = "bla"
DoSomething(parm)
If Err.Number > 0 Then
Err.Clear
parm = "oldbla"
DoSomething(parm)
End If
If Err.Number > 0 Then
Err.Clear
parm = "evenolderbla"
DoSomething(parm)
End If
I have a class c1 that calls another class c2's methods. I want an error generated by c2 to be caught and handled by c1, which will add the error's description to a collection. Code for the relevant functions as follows:
c1:
Private Function doSomething(ByRef rs As DAO.Recordset) As Collection
Dim errors as Collection
Set errors = New Collection
On Error GoTo logError
Do While Not rs.EOF
c2.doSomethingElse rs!someValue
GoTo continueLoop
logError:
errors.Add (Err.Description)
continueLoop:
rs.MoveNext
Loop
Set doSomething = errors
End Function
c2:
Public Sub doSomethingElse(someValue as string)
If Not xyz(someValue) Then
Err.Raise 516, "doSomethingElse", "xyz: " & someValue
Else
DoOtherThings
End Sub
When I have set Error Trapping to "Break on Unhandled Errors", sometimes the Err.Raise in doSomethingElse will raise the error up to doSomething, but sometimes it will just halt execution with a run-time error as though doSomething doesn't have an On Error condition. The first record in rs will usually result in the error being raised to doSomething, but the second one always results in a run-time error. Sometimes the first record also throws a run-time error.
Is something happening after my first iteration of the Do While loop in doSomething that turns off error handling?
Error handling will only do one error.
When rs.movenext sends the routine back through the loop, the error will not work anymore.
Put Resume continueLoop after your error handling.
The following code works for me.
Private Sub Command1_Click()
doSomething
End Sub
Private Function doSomething() As Collection
Dim errors As Collection
Set errors = New Collection
On Error GoTo logError
Do
doSomethingElse ("someValue")
GoTo continueLoop
logError:
errors.Add (Err.Description)
Resume continueLoop
continueLoop:
Loop
Set doSomething = errors
End Function
Public Sub doSomethingElse(someValue As String)
Err.Raise 516, "doSomethingElse", "xyz: " & someValue
End Sub
Be sure to mark this as the right answer if it works for you.
For example, the following function is used for checking whether a workbook is open:
Function BookOpen(Bk As String) As Boolean
Dim T As Excel.Workbook
Err.Clear
On Error Resume Next
Set T = Application.Workbooks(Bk)
BookOpen = Not T Is Nothing
Err.Clear
On Error GoTo 0
End Function
Are these two Err.Clear statements necessary?
In this example
Function BookOpen(Bk As String) As Boolean
Dim T As Excel.Workbook
Err.Clear
On Error Resume Next
Set T = Application.Workbooks(Bk)
BookOpen = Not T Is Nothing
Err.Clear
On Error GoTo 0
End Function
none of the uses is appropriate, because On Error resets the last error, so Err.Clear is redundant.
It's appropriate after actually handling a failed statement.
Function BookOpen(Bk As String) As Boolean
Dim T As Excel.Workbook
On Error Resume Next
Set T = Application.Workbooks(Bk) ' this can fail...
' so handle a possible failure
If Err.Number <> 0 Then
MsgBox "The workbook named """ & Bk & """ does not exist."
Err.Clear
End If
BookOpen = Not T Is Nothing
End Function
If you have On Error Resume Next in effect, the program will continue after an error as if nothing had happened. There is no exception thrown, there is no warning, this is not structured error handling (i.e. it's nothing like try/catch blocks). Your program might end up in a very weird state if you don't do rigorous error checks.
This means you must check errors after. every. statement. that. can. fail. Be prepared to write a lot of If Err.Number <> 0 Then checks. Note that this is harder to get right than it seems.
Better is: Avoid long sections of code that have On Error Resume Next in effect like the plague. Break up operations into smaller functions/subs that do only one thing instead of writing a big function that does it all but can fail halfway through.
In short: Err.Clear makes your program behave predictably after a failed statement in an On Error Resume Next block. It marks the error as handled. That's its purpose.
Of course in your sample it's easy to avoid error handling by using the commonly accepted way of checking whether a workbook (i.e. member of a collection) exists.
Function BookOpen(Bk As String) As Boolean
Dim wb As Variant
BookOpen = False ' not really necessary, VB inits Booleans to False anyway
For Each wb In Application.Workbooks
If LCase(wb.Name) = LCase(Bk) Then
BookOpen = True
Exit For
End If
Next
End Function