-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathErrorHandler.bas
More file actions
178 lines (168 loc) · 7 KB
/
ErrorHandler.bas
File metadata and controls
178 lines (168 loc) · 7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
Attribute VB_Name = "ErrorHandler"
'<include MailToProxy.bas>
Option Explicit
' =============================================================================
' Module: ErrorHandler
' Author: Mark Uildriks, codevba.com
' Description: Centralized error handling function VBA projects.
' Comment: Involves user interaction, so primarily to be used in top level procedures
' Office version 2016 and higher
' Dependencies: MailToProxy module
' License: MIT License
' Version 1.0
' Repository: https://github.com/codevba-com/vba-errorhandler
' =============================================================================
Private Const mcMailAddressTo As String = "support@codevba.com" 'replace by your preferred support email
Private Const mcErrorTitle As String = "Error" 'title of error dialog and email, you can make this more informative
Public Enum ErrorFeedbackType
eftReportableMessage = 0
eftSimpleMessage = 1
eftNone = 2 'user does not notice things have gone wrong, use sparingly!
eftDefault = 3
End Enum
Public Enum ErrorLoggingType
elNone = 0
elImmediateWindow = 1
elErrorLogFile = 2
End Enum
Private Const mceftDefaultErrorFeedbackType As Long = eftReportableMessage 'change to eftSimpleMessage if that suits you better
Private eftErrorFeedbackType As ErrorFeedbackType
Private eltErrorLoggingType As ErrorLoggingType
Private strErrorLogFile As String
Private strErrorTitle As String
Private strErrorTitleSimple As String
Public Function HandleError(Err As ErrObject, Optional FeedbackType As ErrorFeedbackType = eftDefault, _
Optional Module As String, Optional Procedure As String, _
Optional ExtraInfo As String, Optional ErrLine As Long, Optional AddCancelButton As Boolean = False) As Boolean
'If the user presses Cancel HandleError returns False, meaning 'don't continue'
HandleError = True
Dim MessageShort As String
Dim MessageLong As String
Dim strSource As String
Dim lngErrNumber As Long
With Err
strSource = .Source
lngErrNumber = .Number
MessageShort = "Error " & lngErrNumber & ": " & .Description
End With
If Len(ExtraInfo) > 0 Then MessageShort = MessageShort & vbNewLine & vbNewLine & ExtraInfo
If FeedbackType = eftDefault Then FeedbackType = ErrorFeedbackType
If Len(strSource) > 0 Then MessageLong = MessageShort & vbNewLine & vbNewLine & strSource 'source generally returns VBAProject
If Len(Module) > 0 Then MessageLong = MessageLong & " " & Module
If Len(Procedure) > 0 Then MessageLong = MessageLong & " " & Procedure
If ErrLine > 0 Then MessageLong = MessageLong & " line " & ErrLine
Select Case lngErrNumber
Case 2424 'The expression you entered has a field, control, or property name that Microsoft Access can’t find.
'risky to have: MsgBox may reset Access form state, so log instead
GoTo ErrorLogging
End Select
Select Case FeedbackType
Case eftReportableMessage, eftDefault
Select Case MsgBox(MessageShort & vbCrLf & vbCrLf & _
DoYouWantToReportTheProblem, IIf(AddCancelButton, vbYesNoCancel, vbYesNo) + vbCritical + vbDefaultButton2, ErrorTitle)
Case vbYes
MailToProxy.CreateEmail mcMailAddressTo, ErrorTitle, MessageLong
Case vbCancel
HandleError = False
End Select
Case eftSimpleMessage
If AddCancelButton Then
If vbCancel = MsgBox(MessageShort, vbInformation + vbCancel, ErrorTitleSimple) Then HandleError = False
Else
MsgBox MessageShort, vbInformation, ErrorTitleSimple
End If
End Select
ErrorLogging:
Select Case ErrorLoggingType
Case elImmediateWindow
Debug.Print MessageLong
Case elErrorLogFile
Dim iFile As Integer: iFile = FreeFile
Open ErrorLogFile For Append As #iFile
Print #iFile, FormatDateTime(Now) & " " & Replace(MessageLong, vbNewLine, " ")
Close #iFile
End Select
End Function
'Use this to specify default FeedbackType
Property Let ErrorFeedbackType(Value As ErrorFeedbackType)
eftErrorFeedbackType = Value
End Property
Property Get ErrorFeedbackType() As ErrorFeedbackType
If eftErrorFeedbackType = eftDefault Then
ErrorFeedbackType = mceftDefaultErrorFeedbackType
Else
ErrorFeedbackType = eftErrorFeedbackType
End If
End Property
Property Get ErrorLoggingType() As ErrorLoggingType
ErrorLoggingType = eltErrorLoggingType
End Property
Property Let ErrorLoggingType(Value As ErrorLoggingType)
eltErrorLoggingType = Value
End Property
Property Get ErrorLogFile() As String
If (Len(strErrorLogFile) > 0) Then
ErrorLogFile = strErrorLogFile
Else
Dim strDocumentFolder As String
strDocumentFolder = DocumentFolder
strErrorLogFile = strDocumentFolder & "\" & "ErrorLog.txt"
End If
ErrorLogFile = strErrorLogFile
End Property
Property Let ErrorLogFile(Value As String)
strErrorLogFile = Value
End Property
Property Get ErrorTitle() As String
If (Len(strErrorTitle) > 0) Then
ErrorTitle = strErrorTitle
Else
ErrorTitle = mcErrorTitle & " in " & DocumentName
End If
End Property
Property Let ErrorTitle(Value As String)
strErrorTitle = Value
End Property
Property Get ErrorTitleSimple() As String
If (Len(strErrorTitle) > 0) Then
ErrorTitleSimple = strErrorTitleSimple
Else
ErrorTitleSimple = DocumentName
End If
End Property
Property Let ErrorTitleSimple(Value As String)
strErrorTitleSimple = Value
End Property
Private Function DoYouWantToReportTheProblem() As String
DoYouWantToReportTheProblem = "Do you want to report the problem?"
End Function
Private Function DocumentFolder() As String
'returns without \
Dim objApplication As Object: Set objApplication = Application
On Error Resume Next
Select Case Right$(Application.Name, Len(Application.Name) - 10)
Case "Access"
DocumentFolder = objApplication.CurrentProject.Path
Case "Excel"
DocumentFolder = objApplication.ActiveWorkbook.Path
Case "Word"
DocumentFolder = objApplication.ActiveDocument.Path
Case "PowerPoint"
DocumentFolder = objApplication.ActivePresentation.Path
End Select
End Function
Private Function DocumentName() As String
Dim objApplication As Object: Set objApplication = Application
On Error Resume Next
Select Case Right$(Application.Name, Len(Application.Name) - 10)
Case "Access"
Dim strCurrentDbName As String: strCurrentDbName = objApplication.CurrentDb.Name
DocumentName = Right$(strCurrentDbName, Len(strCurrentDbName) - InStrRev(strCurrentDbName, "\"))
Case "Excel"
DocumentName = objApplication.ActiveWorkbook.Name
Case "Word"
DocumentName = objApplication.ActiveDocument.Name
Case "PowerPoint"
DocumentName = objApplication.ActivePresentation.Name
End Select
End Function