Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
Home
Discussion GroupsFormsForms ProgrammingQueriesModules / DAO / VBAReports / PrintingMacrosDatabase DesignSecurityConversionImporting / LinkingSQL Server / ADPMultiuser / NetworkingReplicationSetup / ConfigurationDeveloper ToolkitsActiveX ControlsNew UsersGeneral 1General 2
Access DirectoryToolsTutorialsUser Groups
Related Topics
SQL ServerOther DB ProductsMS OfficeMore Topics ...

MS Access Forum / Forms Programming / October 2008

Tip: Looking for answers? Try searching our database.

Problems with input-validation

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Volker Neurath - 07 Oct 2008 09:21 GMT
Hi all,

i\'m not sure whether i\'m right here with my problem or not, but i try.

Situation:

I have a table with just one field \"myfield\" date-type is \"LONG\"

I also have a form with just one textbox. The form ist bound to the
table an the text box is bound to that one table-field.
There are no validation-rules defined within the field-definiton in the
table or the definiton of the form-control.

Now i try to handle user -input-errors. Because the table-field
only can take numbers i want to check the user\'s input if it is numeric
-
if it\'s not, the user should get a message.

The user should also get a message if he tries to leave the field
without typing in anything, i.e. leaving the field empty.

Problem:
i cannot figure out, how to do this.

Using the Form_Error Event i can check for runtime-error 2113 of
course - but i\'m not able to chekt if this error was fired because
of leaving the field empty or because the user tried to type in
non-numeric values.

This is my procedure in Form_Error:

------------------
Private Sub Form_Error(DataErr As Integer, Response As Integer)
   Dim ctl As Control
   Set ctl = Screen.ActiveControl

  If DataErr = 2113 Then

    If IsNull(Me!Text0) then
    MsgBox \"field must have a value!\"
   ELSE
       If Not (IsNumeric(Me!Text0)) Then
          MsgBox \"Only numerical input allowed in \" & ctl.Name
           Response = acDataErrContinue
        Else
          MsgBox \"Incorrect input in field \" & ctl.name
         Response = acDataErrContinue
        End If
    End If
 end if
End Sub

but: it doesn\'t work.It will allways run into the last \"ELSE\".

I also tried changing the table-field into a text-field and placed the
above code into the control\'s \"BeforeUpdate\"-Event (without the Err
2113-check of course)
--  no change in behaviour.

What am i doing wrong or better:

how can i do a working validation of user-input?

The above is \"only\" testing vor the validation of my actual project;
there i have a small database with
8 fields that have to be tested on many conditions such as:

- left empty?
- numeric?
- numeric and > 0?
- numeric, >0 and integer? (It\'s simply not possible to sell 0.5
printers ;) )
- date?
- is the value (date or quotationnumber) > (or <) than the date (or
quotationnumber)
 in another field on the same form?

The Access-verion is Access 2003

Volker

Signature

If it's raining lemons from the sky -- learn how to make lemonade.

Douglas J. Steele - 07 Oct 2008 12:07 GMT
As code in the BeforeUpdate event, I would expect something like the
following to work:

Private Sub Text0_BeforeUpdate(Cancel As Integer)

 If IsNull(Me!Text0) = True Then
   MsgBox "Text0 must have a value!"
   Cancel = True
 ElseIf IsNumeric(Me!Text0) = False Then
   MsgBox "Only numerical input allowed in Text0"
   Cancel = True
 End If

End Sub

Signature

Doug Steele, Microsoft Access MVP
http://I.Am/DougSteele
(no e-mails, please!)

> Hi all,
>
[quoted text clipped - 75 lines]
>
> Volker
Volker Neurath - 07 Oct 2008 15:47 GMT
Hi Douglas,

sorry, for being late with my answer but programming (and therefore
checking newsgorups) is not the main part of my job ;)

> As code in the BeforeUpdate event, I would expect something like the
> following to work:

> Private Sub Text0_BeforeUpdate(Cancel As Integer)

>   If IsNull(Me!Text0) = True Then
>     MsgBox "Text0 must have a value!"
[quoted text clipped - 3 lines]
>     Cancel = True
>   End If

I've tried this before and found it doesn't work.
The Form_error will fire before the control's BeforeUpdate.

Tomorrow il try again replacing "Me!Text0" (what is: Me!Text0.Value) by
Me!Text0.Text and see what happens.

Volker

Signature

Wenn es vom Himmel Zitronen regnet -- lerne, Limonade zu machen.

Douglas J. Steele - 08 Oct 2008 00:44 GMT
What does "doesn't work" mean? Did you get an error? If so, what was the
error? If you didn't get an error, what did you get, and what did you expect
to get instead?

Presumably you remembered to remove the code from the Form_Error event...

Signature

Doug Steele, Microsoft Access MVP
http://I.Am/DougSteele
(no private e-mails, please)

> Hi Douglas,
>
[quoted text clipped - 21 lines]
>
> Volker
Volker Neurath - 08 Oct 2008 08:45 GMT
> What does "doesn't work" mean? Did you get an error?

Difficult to explain.

Text0 is bound to a table-field - so JET will fire ERR2113 and, as a
result, Form_Error will be fired before "Text0"'s "BeforeUpdate" is
fired.

In the moment I have some further ideas how to get around - i will check
these and cry here again ;) if the won't do.(Then i'll come with
detailed description)

Volker

Signature

Wenn es vom Himmel Zitronen regnet -- lerne, Limonade zu machen.

Douglas J. Steele - 08 Oct 2008 11:58 GMT
That makes no sense. The BeforeUpdate event of the control fires before the
value is written to the table. Even the form's BeforeUpdate event fires
before the table knows anything about the value.

Signature

Doug Steele, Microsoft Access MVP
http://I.Am/DougSteele
(no e-mails, please!)

>> What does "doesn't work" mean? Did you get an error?
>
[quoted text clipped - 8 lines]
>
> Volker
Volker Neurath - 08 Oct 2008 12:40 GMT
> That makes no sense. The BeforeUpdate event of the control fires before the
> value is written to the table. Even the form's BeforeUpdate event fires
> before the table knows anything about the value.

I only can tell you, what I've learned during my tests. An a very simple
one was that simple one from my start-post.

And: i have a book here; the author says the same;

Quote from the book:

"With the technique above (rem:that is what you recommended) you cannot
catch all input errors. If limitations from the tabledesign are ignored
during input or when the Record is stored, the messages produced by this
are displayed /before the "BeforeUpdate" eventprocedures of controls and
forms are  fired/.
*This is e.g. the case when you try to store a text in a date-field*

But - i now have a solution that runs.
I think that, in addition, i will fill the controls "keyDown" event with
a sub that prevents not allowed keys from writing into the field.
(i.e. suppress letter-keys in a field where only numbers are allowed)

Volker

Signature

Wenn es vom Himmel Zitronen regnet -- lerne, Limonade zu machen.

Volker Neurath - 09 Oct 2008 13:53 GMT
Hello again,

now i did several test and the more i'm testing the more i think access
behaves weired.

Table: just one field, named "Eingabe"

Type: long
Required: yes

Form:
one field too an a button for crating a new record.

field-name: txtEingabe

Code in txtEingabe_BeforeUpdate:
   Dim ctl As Control, erg As Boolean
   Set ctl = Screen.ActiveControl

   erg = Len(Trim$(Nz(Me!txtEingabe.Text, "")))

 If IsNull(Me!txtEingabe.Text) Or _
   Len(Trim$(Nz(Me!txtEingabe.Text, ""))) = 0 Then
   MsgBox "Field " & ctl.Controls(0).Caption & "is mandatory!"
   Cancel = True
 Else
   If Not (IsNumeric(Me!txtEingabe)) Then
       MsgBox "Only numerical values!"
       Cancel = True
   End If
 End If

Code in Form_Error:

   Dim ctl As Control
   Set ctl = Screen.ActiveControl

   Debug.Print "Form_Error"
   Debug.Print DataErr

  Select Case DataErr
       Case 2113
         If Not IsNumeric(ctl.Text) Then
           Response = acDataErrContinue
           MsgBox "Numbers only!"

         Else
           Response = acDataErrContinue
           MsgBox "input " & ctl.Controls(0).Caption & " incorrect!"

          End If
       Case 3314
           Response = acDataErrContinue
           MsgBox "Field " & ctl.Controls(0).Caption _
           & " is mandatory."
       Case 2279
           Response = acDataErrContinue
           MsgBox "Number must be 9-digit."
   End Select

Problem:

That works perfectly.

But:

when i change the table-field settings to:

type  TEXT
required YES
AllowZeroLength NO

My code stops working properly.
When i try to create a new record without typing anything into
txtEingabe - nothing happens (it shoul fire "Field.... ist mandatory!"

When i type in an alphanumeric value it fires "Numbers only" (as
expected, but in addition to that it fires the err 2116-message.

Why?

And: any ideas how to make it working properly?

Volker

Signature

Wenn es vom Himmel Zitronen regnet -- lerne, Limonade zu machen.

Douglas J. Steele - 09 Oct 2008 14:05 GMT
"When i try to create a new record without typing anything into txtEingabe".
How are you trying to create a new record? If you've only got a single text
box on the form and you don't type anything into it, the BeforeUpdate event
won't fire, as the form isn't dirty.

I'll make a couple of comments on your code, if you don't mind.

First, you shouldn't be referring to the Text property. Text only works if
the control has focus. It may work in this situation, but when you've got
more than one text box, or when they click on the button, it won't.

For the same reason, relying on ctl.Controls(0).Caption for the error
message isn't a good idea.

Signature

Doug Steele, Microsoft Access MVP
http://I.Am/DougSteele
(no e-mails, please!)

> Hello again,
>
[quoted text clipped - 80 lines]
>
> Volker
Volker Neurath - 09 Oct 2008 14:32 GMT
> "When i try to create a new record without typing anything into txtEingabe".
> How are you trying to create a new record?

I created a button by using the wizard.

The code the wizard created is:

On Error GoTo Err_cmdNewRec_Click
   Me!txtEingabe.SetFocus
   'Me!txtEingabe.Value = Null

   DoCmd.GoToRecord , , acNewRec

Exit_cmdNewRec_Click:
   Exit Sub

Err_cmdNewRec_Click:
   MsgBox Err.Description
   Resume Exit_cmdNewRec_Click

> If you've only got a single text
> box on the form and you don't type anything into it, the BeforeUpdate event
> won't fire, as the form isn't dirty.

OK. But there is the Form_error event and the Form_BeforeUpdate event
too.
And the related tablefield is set to .required=yes.
Why is .required=yes ignored in this case?

> I'll make a couple of comments on your code, if you don't mind.

That would be great.

> First, you shouldn't be referring to the Text property.

value won't work.

> For the same reason, relying on ctl.Controls(0).Caption for the error
> message isn't a good idea.

I want to give the user the Field-Name he sees on the form. With the
tech-name, I guess that the user can't do anything with and i didn't
want hardcoding the names.

Volker,
now working for 2 weeks on input-validation and getting frustrated

Signature

Wenn es vom Himmel Zitronen regnet -- lerne, Limonade zu machen.

Douglas J. Steele - 09 Oct 2008 14:53 GMT
>> "When i try to create a new record without typing anything into
>> txtEingabe". How are you trying to create a new record?
[quoted text clipped - 15 lines]
>    MsgBox Err.Description
>    Resume Exit_cmdNewRec_Click

That's fine, but all it does is create a new record.

>> If you've only got a single text box on the form and you don't type
>> anything into it, the BeforeUpdate event won't fire, as the form isn't
[quoted text clipped - 3 lines]
> And the related tablefield is set to .required=yes.
> Why is .required=yes ignored in this case?

Since the current record has not been modified in any way, there's nothing
to save. Why would you expect the validation to work? (Or are you saying
that a record with invalid data is being created?

>> I'll make a couple of comments on your code, if you don't mind.
>
[quoted text clipped - 3 lines]
>
> value won't work.

What happens when you try? Do you get an error? If so, what's the error? If
you don't get an error, what do you get? (Incidentally, you don't need to
put .Value: it's the default property)

>> For the same reason, relying on ctl.Controls(0).Caption for the error
>> message isn't a good idea.
>
> I want to give the user the Field-Name he sees on the form. With the
> tech-name, I guess that the user can't do anything with and i didn't want
> hardcoding the names.

But you don't know which control is the active one! The active control
doesn't change simply because you're examining the value in a particular
control. I believe you need something like:

If Len(Trim$(Me!txtEingabe & vbNullString)) = 0 Then
 MsgBox "Field " & Me!txtEingabe.Caption & " is mandatory!"
 Cancel = True
ElseIf Not (IsNumeric(Me!txtEingabe)) Then
 MsgBox "Only numerical values!"
 Cancel = True
End If

Having

If IsNull(Me!txtEingabe.Text) Or _
   Len(Trim$(Nz(Me!txtEingabe.Text, ""))) = 0 Then

really is redundant, and using vbNullString is (marginally) more efficient
than using "".

Signature

Doug Steele, Microsoft Access MVP
http://I.Am/DougSteele
(no e-mails, please!)

Volker Neurath - 09 Oct 2008 15:37 GMT
> That's fine, but all it does is create a new record.

That's what it is expected to. Ok, there's another button, created by
the wizard too. It's name is "Save record".

Here's it's code:

Private Sub cmdSaveData_Click()
On Error GoTo Err_Befehl5_Click

   DoCmd.DoMenuItem acFormBar, acRecordsMenu, acSaveRecord, ,
acMenuVer70

Exit_Befehl5_Click:
   Exit Sub

Err_Befehl5_Click:
   MsgBox Err.Description
   Resume Exit_Befehl5_Click

End Sub

> Since the current record has not been modified in any way, there's nothing
> to save. Why would you expect the validation to work? (Or are you saying
> that a record with invalid data is being created?

As I said before, the field is not allowed to be empty.

>>> I'll make a couple of comments on your code, if you don't mind.
>>
[quoted text clipped - 3 lines]
>>
>> value won't work.

> What happens when you try? Do you get an error? If so, what's the error? If
> you don't get an error, what do you get?

sorry, but I just don't understand why you're asking this.
When the _BeforeUpdate Event of a control ist fired, there is *nothing*
in .Value, the Value, the user typed in is in .Text.

Of course I could now change my code and test what happens.

But: i've leisure-time in less than 25 minutes ;)

> (Incidentally, you don't need to  put .Value: it's the default property)

I know but nevertheless I do so - now and in future.
In my opinion, the code gets more readable.

>>> For the same reason, relying on ctl.Controls(0).Caption for the error
>>> message isn't a good idea.
>>
>> I want to give the user the Field-Name he sees on the form. With the
>> tech-name, I guess that the user can't do anything with and i didn't want
>> hardcoding the names.

> But you don't know which control is the active one!

In Form_Error and Form_BeforeUpdate you're right

The active control
> doesn't change simply because you're examining the value in a particular
> control. I believe you need something like:

> If Len(Trim$(Me!txtEingabe & vbNullString)) = 0 Then
>   MsgBox "Field " & Me!txtEingabe.Caption & " is mandatory!"
[quoted text clipped - 3 lines]
>   Cancel = True
> End If

As i said i don't want the user to see the tech-names becoause he can't
do anything with it.

What about something like:

Dim ctl as control

set ctl = Screen.ActiveControl

[..]
MsgBox "Field " & ctl.Controls(0).Caption & " is mandatory!"

Volker

Signature

Wenn es vom Himmel Zitronen regnet -- lerne, Limonade zu machen.

Douglas J. Steele - 09 Oct 2008 20:16 GMT
> That's what it is expected to. Ok, there's another button, created by the
> wizard too. It's name is "Save record".
[quoted text clipped - 14 lines]
>
> End Sub

Much simpler is

Private Sub cmdSaveData_Click()
On Error GoTo Err_Befehl5_Click

 Me.Dirty = False

Exit_Befehl5_Click:
 Exit Sub

Err_Befehl5_Click:
 MsgBox Err.Description
 Resume Exit_Befehl5_Click

End Sub

> sorry, but I just don't understand why you're asking this.
> When the _BeforeUpdate Event of a control ist fired, there is *nothing*
> in .Value, the Value, the user typed in is in .Text.

Hold on. The BeforeUpdate event of a control? I believe I said to use the
BeforeUpdate event of the form. (Using Text is fine in the BeforeUpdate
event of a control, since the control will have focus)

> In Form_Error and Form_BeforeUpdate you're right
>
[quoted text clipped - 21 lines]
> [..]
> MsgBox "Field " & ctl.Controls(0).Caption & " is mandatory!"

Ah. I believe I see what you're trying to do: use the caption of the
associated label. Yes, what you have will work in the control's BeforeUpdate
event, but in the form's BeforeUpdate event, you can't be sure it will. Use

Me!txtEingabe.Controls(0).Caption

Signature

Doug Steele, Microsoft Access MVP
http://I.Am/DougSteele
(no e-mails, please!)

Volker Neurath - 10 Oct 2008 07:48 GMT
Hi Douglas,

> Much simpler is

> Private Sub cmdSaveData_Click()
> On Error GoTo Err_Befehl5_Click

>   Me.Dirty = False

> Exit_Befehl5_Click:
>   Exit Sub

> Err_Befehl5_Click:
>   MsgBox Err.Description
>   Resume Exit_Befehl5_Click

> End Sub

THX. the above code is what the wizard created ;)
We're talking about my test-form.

>> sorry, but I just don't understand why you're asking this.
>> When the _BeforeUpdate Event of a control ist fired, there is *nothing*
>> in .Value, the Value, the user typed in is in .Text.

> Hold on. The BeforeUpdate event of a control? I believe I said to use the
> BeforeUpdate event of the form.

My tests are confusing me. It seems that some events will be caught in
the control's .BeforeUpdate but not in From_BeforeUpdate.

And, please: keep in mind, that i'm working with bound form and bound
controls ;)

> (Using Text is fine in the BeforeUpdate
> event of a control, since the control will have focus)

Just what I said ;)

>> As i said i don't want the user to see the tech-names becoause he can't do
>> anything with it.
[quoted text clipped - 7 lines]
>> [..]
>> MsgBox "Field " & ctl.Controls(0).Caption & " is mandatory!"

> Ah. I believe I see what you're trying to do: use the caption of the
> associated label.

You've got it ;)

Yes, what you have will work in the control's BeforeUpdate
> event, but in the form's BeforeUpdate event, you can't be sure it will. Use

> Me!txtEingabe.Controls(0).Caption

Won't the above work?
Screen.ActiveControl should give me the at error-time active control i
suppose.

Volker

Signature

Wenn es vom Himmel Zitronen regnet -- lerne, Limonade zu machen.

Volker Neurath - 10 Oct 2008 08:24 GMT
Hi again,

some thoughts i forgot...

There's one point which is driving me crazy;  in txtEingabe_BeforeUpdate
i have the following piece of code:

> If Not (IsNumeric(Me!txtEingabe)) Then
>   MsgBox "Only numerical values!"
>   Cancel = True
>   Exit Sub
> End If

It will do what it is expected to: throwing a message when the user
types in anything but numbers.
But, and that's what is driving me crazy: when the box is confirmed by
klicking its OK button, Acces will immediatly throw the internal ERR2116
message.

so i have to handle this too - and that doesn't make any sense to me.

How can i get around this?

Besides - I think I have to think about the whole part "input
validation" again. The most important questions will be:

where is the best place for testing user-input (valid/invalid input)
where is the best place to catch Access Errors, including such resulting
from invalid user-input.

Volker

PS: thanks for your patience

Signature

Wenn es vom Himmel Zitronen regnet -- lerne, Limonade zu machen.

Douglas J. Steele - 10 Oct 2008 12:23 GMT
If Access is raising unusual errors, you might consider decompiling your
application. Tony Toews has information about how to do that at
http://www.granite.ab.ca/access/decompile.htm

Incidentally, you might be surprised by some of what gets passed by the
IsNumeric function. From the Immediate window:

?IsNumeric("235a3")
False
?IsNumeric("235e3")
True
?IsNumeric("235d3")
True

I personally prefer putting all of my validations into the
Form_BeforeUpdate, but there's no reason why you can't use the
control_BeforeUpdate event for some checks. I've never used the Form_Error
event for anything.

Signature

Doug Steele, Microsoft Access MVP
http://I.Am/DougSteele
(no private e-mails, please)

> Hi again,
>
[quoted text clipped - 25 lines]
> where is the best place to catch Access Errors, including such resulting
> from invalid user-input.
Volker Neurath - 10 Oct 2008 12:55 GMT
> ?IsNumeric("235e3")
> True

that is logical anyway...

> ?IsNumeric("235d3")
> True

but this is not...

> I personally prefer putting all of my validations into the
> Form_BeforeUpdate,

ok.

> I've never used the Form_Error
> event for anything.

and how do you catch errors, risen by rules on table-design oder caused
by integrity-faults?

For instance, how do you catch an Unique-Index error(3022)?

Volker

Signature

Wenn es vom Himmel Zitronen regnet -- lerne, Limonade zu machen.

Douglas J. Steele - 10 Oct 2008 16:30 GMT
>> ?IsNumeric("235e3")
>> True
[quoted text clipped - 5 lines]
>
> but this is not...

Actually, it is. In many languages, both e3 and d3 indicate 10**3, with e
being single precision and d being double precision.

>> I personally prefer putting all of my validations into the
>> Form_BeforeUpdate,
[quoted text clipped - 7 lines]
>
> For instance, how do you catch an Unique-Index error(3022)?

I don't rely on catching the Unique-Index error. While it may be redundant,
if I'm going to do validation, I'll check whether it's a duplicate in the
form's BeforeUpdate event.

Signature

Doug Steele, Microsoft Access MVP
http://I.Am/DougSteele
(no e-mails, please!)

Volker Neurath - 10 Oct 2008 17:29 GMT
> "Volker Neurath" <neanderix@expires-31-10-2008.news-group.org> wrote in
>>> ?IsNumeric("235d3")
[quoted text clipped - 4 lines]
> Actually, it is. In many languages, both e3 and d3 indicate 10**3, with e
> being single precision and d being double precision.

I see.

>> For instance, how do you catch an Unique-Index error(3022)?
>
> I don't rely on catching the Unique-Index error. While it may be
> redundant, if I'm going to do validation, I'll check whether it's a
> duplicate in the form's BeforeUpdate event.

Ok, but that is only one example.

Volker
Signature

Im übrigen bin ich der Meinung, dass TCPA/TCG verhindert werden muss

Wenn es vom Himmel Zitronen regnet, dann lerne, wie man Limonade macht

 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.