Passing form values to module

  • Thread starter gmazza via AccessMonster.com
  • Start date
G

gmazza via AccessMonster.com

Hi there,
I created a module to Log Errors on a form to an Error Log Table. I need to
pass the following to the module, so it can be written to the Error Log Table:

1. The table name the form is associated with.
2. The Value the user typed into the field when it errored(assuming it
errored on something the user typed in)

The reason is I have a certain field that in order to update the user has to
put in their password, so if their password is wrong it will error, and I
need it to return the table, and the value they tried to type in.

I can't reference the form name or the field name directly because I need
this module to work with a number of forms.
I hope this makes sense and can anyone shed some light?
Thanks!
 
D

dymondjack

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

--
Jack Leach
www.tristatemachine.com

- "Success is the ability to go from one failure to another with no loss of
enthusiasm." - Sir Winston Churchill
 
G

gmazza via AccessMonster.com

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!
 
D

dymondjack

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!
 
D

dymondjack

Quick correction in the Type example
...
rst![FailedValue] = erActiveControlText
...
...
ErrorHandlerExit:
'Clean up the error data
Err.Clear
dstERROR.erNumber = 0
...

rst![FailedValue] = erActiveControlText
s/b
rst![FailedValue] = dstERROR.erActiveControlText


--
Jack Leach
www.tristatemachine.com

- "Success is the ability to go from one failure to another with no loss of
enthusiasm." - Sir Winston Churchill


dymondjack said:
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!
 
G

gmazza via AccessMonster.com

Thanks for your reply!
Sorry if I'm slow here but I don't understand a few things.
Do I put this Function in my form code? Also, I don't use a command button,
the code is in my After Update even, does that make a difference?
What do I pass when I call my Error routine, FirstName?

I am doing this right now:
Screen.PreviousControl.SetFocus
MsgBox Screen.PreviousControl

and its spitting out my new change through the MsgBox which is good, thanks.
Can I get what it originally was as well?

As for the table name, I created the function you gave me, in my form code,
but I don't know what to put in my After Update Event for this, and I also
don't know what value to pass to my Error routine.

As for the TYPE, sounds good to try and implement, after I get this working
it is a good start to better tracking, like you say.

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
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
[quoted text clipped - 77 lines]
 
D

dymondjack

Unfortunately I only have a vague idea of what it is you're actually trying
to do here. From what I gather, you want to trap an error that might arise
from typing a wrong value into a textbox control? the control's BeforeUpdate
event will let you work with the previous value, and the AfterUpdate event
will let you work with the new value. However, if there is an error in the
value, BeforeUpdate may fire, but never complete, thus AfterUpdate won't fire
because the control won't get updated.

The real question I have though, is: How do you expect to trap an error
when it is typed in? I think there are relatively few errors that will arise
from the user entering a value in a textbox. I'm afraid I'm a bit lost as
far as how you are attempting to go about doing this.

If you can give an example of what error you come across when the user types
in a wrong value (in the password field? I'm not sure how you're doing this
one either...), I might be able to offer some more info on how to handle it.
At this point any advice I would give may do more harm than good.

Oh, and just for the record, the Type is strictly a concept for me at the
moment. I played around with it a little bit but I have no idea at the
moment if this is a good route to go or not. It's my first attempt at using
a custom type, and I don't know what kinds of problems I might run into.
Anyway, it might be a great idea, it might be a terrible one (I was actually
hoping someone with more experience might step in and offer some advice on
that...).

--
Jack Leach
www.tristatemachine.com

- "Success is the ability to go from one failure to another with no loss of
enthusiasm." - Sir Winston Churchill
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top