Exiting gracefuly from an if statement?!

I have this following if statement:

procedure TForm1.Table2BeforePost(DataSet: TDataSet);
begin
  if StrToInt(DBEdit7.Text)<50 then
  begin
   ShowMessage('Value must be more than 50');
   Table2.Cancel;
  end;
end;

So after the message gets displayed, and the Table2 gets canceled I get an annoying: 'Access violation at address...Read od address FFFFFFFF.'

How do I workaround this?

Thanks, Blash
blashAsked:
Who is Participating?
 
kretzschmarCommented:
two possibilties

procedure TForm1.Table2BeforePost(DataSet: TDataSet);
begin
 if StrToInt(DBEdit7.Text)<50 then
 begin
  ShowMessage('Value must be more than 50');
  abort;  //silent exception
 end;
end;

or

procedure TForm1.Table2BeforePost(DataSet: TDataSet);
begin
 if StrToInt(DBEdit7.Text)<50 then
 begin
  Raise exception.create('Value must be more than 50');
 end;
end;

meikl ;-)
0
 
EpsylonCommented:
You can't cancel something that has not yet been committed.
0
 
comptebidon81Commented:
Could it be that you are trying to cancel an event that has not yet occured? I think you should try to put your validation in the afterPost event.
0
Get expert help—faster!

Need expert help—fast? Use the Help Bell for personalized assistance getting answers to your important questions.

 
JaymolCommented:
There's obviously a problem with the Cancel command, not the way it's been structured within the If statement.

If we could see some more code we may be able to help better.

John.
0
 
kretzschmarCommented:
just to say,

you must cancel the post process and not the edited data.

best way to abort the post process is to raise an (silent) exception.

the dataset is keeping in the editmode (after this, no data are posted)

meikl ;-)
0
 
StefaanCommented:
Hi,

Well, apparently what you should do in the BeforePost event is raise an excaption.  Your code should look like this :

 if StrToInt(DBEdit7.Text)<50 then
 begin
  Raise Exception.Create('Value must be more than 50');
 end;

By raising an exception the post will be aborted, thus you wont lose modifications and the dataset will still be in edit mode so the user can fix the problem.

Best regards,


Stefaan

0
 
StefaanCommented:
Oops, didn't notice it but Meikl already suggested the same thing.

Stefaan
0
 
pisceanCommented:
In the DBEdit's OnEnter event save the current value to a global variable then do your checking in the OnExit event.

var
  TempVal: String; {Global Variable}

OnDBEditEnter();
begin
  TempVal := DBEdit.Text;
end;

OnDBEditExit();
begin
  if StrToInt(DBEdit.Text) < 50 then
    begin
      DBEdit.Text := Temp
      ShowMessage('Value must be more than 50!');  
    end;

Hope this helps...
0
 
StefaanCommented:
Hi Piscean,

Not a good idea to use the OnEnter and OnExit events for this kind of thing.  If you have 5 different forms all showing the same dataset with that field, you will have to code this in the OnEnter and OnExit events of the DBEdit on 5 different forms ! ! ! This means that the code won't be easy to maintain.

If you really want to use validation on one field, you should use a Persistent Field and code your thing in the OnValidate event of that field.  Something like this :

procedure TdtmED_Opleidingsdossier.OnValidateField(
  Sender: TField);
begin
  { The Validation occurs of the F_DURATION Field }
  if ( Sender.FieldName = 'F_DURATION' ) then
  begin
    { Check if the Duration is between 6 and 24 }
    if ( Sender.AsInteger < 6 ) or ( Sender.AsInteger > 24 ) then
    begin
      { Raise an Exception if it isn't }
      Raise Exception.Create( 'The duration shoul be between 6 and 24' );
    end;
  end;
end;

The advantages of this approach are the following :

- Field validation is maintained in one place : On the datamodule ( in my case ) in the OnValidate event of the persistent field, which makes the code much more readable and maintaintable.  If the validation changes in the future, I only have to modify the code in one place.
- It doesn't matter what DB control I use, I could use an DBEdit, a Grid, or whatever data aware control, the validation will always be done.
- I dont have to do anything on my forms, even if I have 10 forms which all use this dataset, they will all have the same validation rule for that field, thus the User interface layer and the Database Layer are well seperated.


Well, just thought I could show you this.  If you code your field validations in this way instead of using the OnEnter and OnExit events of the data aware controls, your code will be easier to read and to maintain, which will make Code Reviewers ( like me ) a bit happier ;-)

Best regards,


Stefaan
0
 
blashAuthor Commented:
Thanks everyone,

Blash
0
 
pisceanCommented:
Stefaan,
Thanks for the tip man! (Though it took me a couple of minutes (maybe 3 ...) trying to find that event. Actually, I haven't used that trick before so I don't know where that event occurs. Most of the time, I use OnDataChange and OnEnter/OnExit and share the event handler so there's not much coding ...) Just noticed one thing ..., you don't have to check the field name (it's needed only if the event is shared within fields with common validation rules ...)
Anyway, thanks! I'll be using that one on my next project (Workstation Inventory).

piscean
0
 
StefaanCommented:
Hi Piscean,

Indeed you don't have to check the FieldName if you use the event handler for only one field.  But most of the time I put all FieldValidations into one method and use it as the event handler for all the fields which need some validation.  This way IMHO makes it easier to read.

Well, I didn't provide the answer to this question ( well I wasn't the first one to propose it ), but I helped out someone else ;-)

Best regards,


Stefaan
0
 
pisceanCommented:
;-)
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.