I need a simple error handling code for my small macro, I have search the web but have nothing simple, seems to be all very complicated.
I down load sales reports in .txt form on a weekly basis, I run separate macro to do stuff and then add to a master page. Not every week do sales reports download as there may not have been sales for that particular region.
I need a simple error handler so that if it does not find the report, it moves to the next sub.
Any help appreciated
Sub MXM_POS()
Workbooks.OpenText Filename:="C:\Users\903270\Documents\Excel\MXMPOS*.txt"
‘Run macro code
Run ("DLK_POS")
End Sub
Here is a simple basic structure that you can expand on as needed:
Sub MXM_POS()
On Error GoTo ErrHandler
' code here
ExitSub:
' shutdown code here
Exit Sub
ErrHandler:
If Err.Number <> 0 Then
Dim mbr As VbMsgBoxResult
mbr = MsgBox( _
"Error #" & Err.Number & ": " & Err.Description & vbNewLine & _
"Would you like to continue?", vbExclamation Or vbYesNo)
If mbr = vbYes Then Resume ExitSub
Application.Quit
End If
End Sub
When I desire a stack dump I construct that within the Source property of the Err object using concatenation with a newline, and then only display the MsgBox result at the top of the calling stack, usually either the Event Handler that launched the code or the top-level macro invoked by the user.
Related
I put together a VBA procedure that does the following:
opens a bunch of excel files (separately not at once) from a specific folder (user indicates the folder)
excel files are password protected so it inputs the password , opens the file , then unprotects a specific sheet (as sheets are also pass protected) and does some changes to the file.
My problem is that for the changes to be applied to each excel file the sheet has to be unprotected and there is unfortunately 3 different options for pass (dont ask me why). I know the pass options so i put it in my code as per below:
However the procedure still stops if the first pass option is incorrect and I have to manually drag the execution line to the next valid pass for the procedure to continue.
Essentially my questions are: is the code set up above ok and is there a way of making VBA to attempt another password to unprotect sheet if the first pass is not the correct one (and a third attempt if the 2nd pass is also incorrect)?
Uff, hope the above makes sense and thanks for reading
This should help. I haven't used any of your code as it's a picture that I can't copy/paste, but this should give you the idea.
Note:
Option Explicit should appear at the top of every module - forces you to declare variables.
the Public Const line must be at the top of a module before any procedures/functions.
Option Explicit
Public Const ERROR_SHEETPROTECTED As Long = vbObjectError + 513
Sub Test()
'Any errors should be handled by the error handler appearing after the Exit Sub.
On Error GoTo ERROR_HANDLER
Dim wrksht As Worksheet
With ThisWorkbook
Set wrksht = .Worksheets("Sheet1")
'Use each password and exit loop when correct one is found.
Dim PWDS As Variant
PWDS = Array("123", "456", "ABCD")
Dim PWD As Variant
For Each PWD In PWDS
On Error Resume Next 'Ignore any errors and move to next line.
wrksht.Unprotect PWD
On Error GoTo ERROR_HANDLER 'Reinstate correct error handling as soon as possible.
If Not wrksht.ProtectContents Then Exit For 'We found a match!
Next PWD
'Final check that at least one of the passwords worked.
If wrksht.ProtectContents Then
Err.Raise ERROR_SHEETPROTECTED, , "Password for sheet not found"
End If
End With
Exit Sub
'Error handling appears after the main body of code (Exit Sub) and before the end of the procedure (End Sub)
ERROR_HANDLER:
Select Case Err.Number
Case ERROR_SHEETPROTECTED
MsgBox Err.Number & vbCr & Err.Description, vbOKOnly + vbCritical
'Other code to sort the problem out.
Resume Next 'If problem is solved use this to jump back into the main code.
Case Else
MsgBox Err.Number & vbCr & Err.Description, vbOKOnly + vbCritical
End Select
End Sub
Raise method
With...End With Statement
On Error GoTo -1
There are a couple of misunderstandings in your code, because even if it succeeds first time it will run into the next error handler.
But the main error is a common misunderstanding in error handling when trying to handle multiple errors in a sequenz, missing the On Error GoTo -1 :
Option Explicit
Sub BadErrorHandlingSequenz()
Dim x As Integer
On Error GoTo Errhandler1
x = 3 / 0
Exit Sub
Errhandler1:
On Error GoTo errhandler2
x = 5 / 0 ' Error is not handled
Exit Sub
errhandler2:
MsgBox "Still Error"
End Sub
Sub GoodErrorHandlingSequenz()
Dim x As Integer
On Error GoTo Errhandler1
x = 3 / 0
Exit Sub
Errhandler1:
On Error GoTo -1 ' Reset Error handling
On Error GoTo errhandler2
x = 5 / 0 ' Error is handled
Exit Sub
errhandler2:
MsgBox "Still Error"
End Sub
Im working on building out a VBA-based app that will have around 150 users. They will all have their own data files, tables, custom views, etc. But I will need to regularly update the code behind the app. So Im using the two-workbook technique where their unique User Workbooks (call them the UWs) all pass control to a Code Workbook (call it CW) which contains all the code. That way, when I need to update, I update the CW, and everyone simply replaces the old CW in their folders with the new one and their UWs remain the same.
My problem is that I'd like the CW to essentially remain hidden and protected. But with macro security, when they open their UWs after the update and it immediately calls the startup subroutine in the new CW, it won't run. They have to first open the CW (which I don't want!) and make it a trusted document before opening their UWs will run the startup subroutine in the CW.
It shouldn't matter, but here is the only code in the UWs (note this is still in prototyping/early stages so everything is called 'Test'!):
Private Sub Workbook_BeforeClose(Cancel As Boolean)
On Error Resume Next
Workbooks("Test CW.xlsm").Close
End Sub
Private Sub Workbook_Open()
Application.ScreenUpdating = False
'Checks to see if TestCW is present next to Test UW
On Error Resume Next
X = Workbooks("Test CW.xlsm").Name 'Sets X to name of workbook; if its not there this will throw an error and Err <> 0
If Not (Err = 0) Then 'If there's no error
On Error GoTo CWFileError
Workbooks.Open Filename:=ThisWorkbook.Path & Application.PathSeparator & "Test CW.xlsm" 'Opens Test CW if in same folder
'Makes Test CW hidden
Workbooks("Test CW.xlsm").Windows(1).Visible = False
End If
On Error GoTo 0
'Runs test module in Test CW, then returns control to here
With Application
.ScreenUpdating = True
.Run "'Test CW.xlsm'!ThisWorkbook.TestStart" 'Uses ThisWorkbook.TestSTart as TestStart is a Workbook-level subroutine in the ThisWorkbook module
End With
ThisWorkbook.Activate
Exit Sub
CWFileError:
MsgBox "Your SVEDash application file named Test CW is not in this folder." _
& vbCrLf _
& "Please locate your current SVEDash application file and place it in this folder." _
& vbCrLf _
& "This file will close to prevent damage to your data."
On Error GoTo 0
ThisWorkbook.Close
End Sub
Any ideas on how I can bypass this security issue without the users having to change their security settings?
This seemed to only be an issue with the first 'Updte'. As I copied newer 'updated' CW into the folder, as long as I kept the name consistent the previous trusted status of the former file with that name was remembered. Hopefully thats an actual solution
We have a macro addin in our company that I cannot run on one computer (on another computers it runs correctly) with Automation error Exception occured. Can you please tell me where is the mistake ?
Sub importFromActiveSheet()
If ActiveSheet Is currDoc Then
MsgBox "You cannot import data from current document" & vbNewLine & vbNewLine & "Please select other file", vbCritical, "Wrong source data file"
Exit Sub
End If
....
Property Get currDoc() As Worksheet 'returns current document worksheet in tool
Set currDoc = ThisWorkbook.Sheets(1)
End Property
The error will pop up at the sentence :
Set currDoc = ThisWorkbook.Sheets(1)
After this the excel will fall down.
Can you help me please ?
I have the followin code. But the error does not get handled
Sub Some_sub()
Some code here
On Error GoTo resumeCode
If Workbooks("Some file.xlsm").ReadOnly Then
GoTo readOnlyError
End If
resumeCode:
On Error GoTo fileNotOpen
Workbooks("Some file.xlsm").Activate
some more code here
Exit Sub
fileNotOpen:
MsgBox "Error: Claims followup.xlsm is not open." & Chr(10) & Chr(10) &
"Open the file in read/write"
Exit Sub
End Sub
When I run debug mode it shows me this line: Workbooks("Some file.xlsm").Activate in yellow. Instead of handling the error and going to the label.
Within VBA under Tools -> Options -> General Tab: Break on Unhandled Errors active.
When I have the file open it runs the code like it should. When it is closed it does not handle the error.
What am I doing wrong?
Thanks in advance for your help
That's it. As I said in the comments, when an error occurs, and you handle it, you cannot setup a new On Error mechanism until you explicitly invoke the Resume keyword in any way.
One possible way to achieve it, if you dont want to change the flow of your routine, is just to add a label before your new On Error statement and Resume on it. Like this, for example:
Sub Some_sub()
' Some code ...
On Error GoTo resumeCode
If Workbooks("Some file.xlsm").ReadOnly Then
GoTo readOnlyError
End If
' Some more code ...
resumeCode:
Resume ResumeHere ' <---------------------------------------- Invoke Resume
ResumeHere: ' <------------------------------------- Add some label
On Error GoTo fileNotOpen
Workbooks("Some file.xlsm").Activate
Exit Sub
fileNotOpen:
msgBox "Error: Claims followup.xlsm is not open." & Chr(10) & Chr(10) & "Open the file in read/write"
Exit Sub
End Sub
You should be careful though, the keyword Resume will itself raise an error if the error status is blank and it is reached from normal flow, In that case you should put the error handling sections, each apart, in the end of your routine and resume at any labels within the normal flow from there. This is generally the usual approach.
I am running a macro on a remote PC which executes every 5 seconds throughout the day.
Now I want that if something goes wrong and the macro stops execution I should be informed or notified via an Email.
How can I do that?
Error handling.
Sub MySub()
On Error GoTo ErrorHandler
' Work done here...
' Screen for an expected error
If somethingWentWrong = True Then
Err.Raise Number:=myErrorNumber, Source:="MySub", _
Description:="This thing went wrong."
' Will now go to ErrorHandler
End If
' More work done here...
ExitProcedure:
On Error Resume Next
'Cleanup code goes here...
Exit Sub
ErrorHandler:
' If an error occurs (anticipated or not), the following will be executed.
Call SendEmailNotification( _
Recipient:="you#there.com", _
Subject:="Something went wrong.", _
Message:=Err.Number & vbCrLf & Err.Description & vbCrLf & Err.Source)
' Any other error handling goes here...
Resume ExitProcedure
End Sub
To send an e-mail, there are various solutions out there. Search for CDO, MAPI, Sockmail. Searching on those will give you examples for how to write your SendEmailNotification sub. Heads up: None of these are exactly straightforward.
You can add a mail send functionality within your error handling. If the machine the macro is being executed has Outlook properly set, I believe you can use ActiveWorkbook.SendMail.
If this PC doesn't have the Outlook set, you'll need to find out for a mail solution that fits your environment.
It would then looks like:
Sub MySub()
On Error GoTo ProcError
'Your stuff
ProcExit:
Exit Sub
ProcError:
ActiveWorkbook.SendMail "your.mail#yourdomain.com", "Application failed!"
Resume ProcExit
End Sub