Here's a quick function I tried that resides in a standard module and returns
the .Text value for the passed control.
Public Function GetControlText(ByRef ctl As Control) As String
GetControlText = ctl.Text
End Function
This returns correctly when called from a command button on a form that
passes a control thats on the same form:
Private Sub Command1_Click
Me.ctlRequestID.Setfocus
MsgBox GetControlText(Me.ctlRequestID)
End Sub
I had to set the focus back on the control since I'm clicking a button, so
ActiveControl doesn't work here but should if you are trying to catch an
error. Dirk Goldgar advised the following line of code a few days ago, which
might prove handy to reference the previously selected control without having
to know it's name.
Screen.PreviousControl.SetFocus
Anyway, that should get your public function to get the text value of a
control (obviously add some handling for controls that don't have a text
value). As far as making this accessable to your handler, you could either
add it as another argument, or maybe into a public variable if you don't
expect to use it much.
The same seems to work for the recordsource:
Public Function GetFormRecordsource(ByRef frm As Form) As String
GetFormRecordsource = frm.RecordSource
End Function
(my test was a form based on a table, I didn't try a query)
On an entirely different approach, of late I've been considering the idea of
a global custom datatype to handle various data related to any given error.
That way you wouldn't have to worry about so many arguments (especially for
data that you only wish to track under certain circumstances) and it's
accessable from anywhere in the project. Something like this
Public Type dstERROR
erNumber As Long
erDescription As String
erModule As String
erProcedure As String
erActiveControlName As String
erActiveControlText As String
End Type
Public Function ErrorHandler() As Long
...
...
rst![FailedValue] = erActiveControlText
...
...
ErrorHandlerExit:
'Clean up the error data
Err.Clear
dstERROR.erNumber = 0
...
End Function
Private Sub SomeFormOp()
On Error Goto SomeFormOpError
...
SomeFormOpError:
dstERROR.erNumber = Err.Number
...
dstERROR.erActiveControlText = GetControlText(Me.ActiveControl)
ErrorHandler
Resume SomeFormOpExit
End Sub
I have been thinking that maybe the constant overhead of a public type with
many elements might be well worth the troubles that we run into trying to
track obscure data for an error...
hth
--
Jack Leach
www.tristatemachine.com
- "Success is the ability to go from one failure to another with no loss of
enthusiasm." - Sir Winston Churchill
gmazza via AccessMonster.com said:
Yes I have a module that is my global error handler. It has the error number
and description, etc but I don't know how to pass the data in the text field
that the user is entering.
Table name and Failed Value show as blank in my table, the rest show a value.
Here is my snipet from my module:
Function LogError(ByVal lngErrNumber As Long, ByVal strErrDescription As
String, _
strCallingProc As String, strFieldName As String, strTableName As String)
As Boolean
Dim strMsg As String ' String for display in MsgBox
Dim rst As DAO.Recordset ' The ErrorLog table
strMsg = "Error " & lngErrNumber & ": " & strErrDescription
MsgBox strMsg, vbExclamation, strCallingProc
Set rst = CurrentDb.OpenRecordset("ErrorLog", , dbAppendOnly)
rst.AddNew
rst![ErrNumber] = lngErrNumber
rst![ErrDescription] = Left$(strErrDescription, 255)
rst![ErrDate] = Now()
rst![CallingProc] = strCallingProc
rst![Username] = ap_GetUserName()
rst![FormName] = FormName()
rst![TableName] = strTableName
rst![FailedValue] = strFieldName
rst.Update
rst.Close
LogError = True
End Function
Here is the snipet from my form, calling this module:
Private Sub FirstName_AfterUpdate()
On Error GoTo Err_FirstName_AfterUpdate
Dim strFieldName As String
Dim strTableName As String
strTableName = Me.RecordSource
strFieldName = Me.ActiveControl.Name
Exit_FirstName_AfterUpdate:
Exit Sub
Err_FirstName_AfterUpdate:
Call LogError(Err.Number, Err.Description, "First Name", strFieldName,
strTableName)
Resume Exit_FirstName_AfterUpdate
End Sub
Ideally you should be calling on a global error handler. The arguments of
the error handler should be complete for all of the information that you wish
to pass to it. For example, I run a handler that has the Number,
Description, current Module, current Procedure, among others. All of these
are passed to the error handling function (module) and used from there.
To get the name of the control, I would think you can add a Optional
CurrentControl As String = "" as an argument. Then Me.ActiveControl can pass
that value for you. Or, you can use that to get the current control name,
and then reference the .Text property of the control and pass it to your
error handling function in a similar way.
For the tablename, Me.Recordsource will give you the table if the form
isn't based on a query. I'm not sure how to handle that with a query. The
recordsource property will return either the name of the saved query or the
SQL string associated with it.
For logins/password checks, I'll generally handle this with an unbound
control for the password, and run a quick check with something like dlookup
(or ELookup). Then you can handle the situation without having it turn into
an actual 'error'. Just a thought.
hth
Hi there,
I created a module to Log Errors on a form to an Error Log Table. I need to
[quoted text clipped - 12 lines]
I hope this makes sense and can anyone shed some light?
Thanks!