Jump to content
Sign in to follow this  
kzaveri19

Validate value entered in a DBGrid

Recommended Posts

Hello,
I want to validate a value entered in a TDBGrid. The values I want to check are 'Close Amount Per' and 'Benchmark Close Per' (Field #4 and #5 below) based on the value of 'Long Short' (Field #1). The validation if whether the value is positive (Long) or negative (short). Below is a screenshot of the form.

image.thumb.png.a116f528c73baa5ca7621b11bf8a48e5.png

image.thumb.png.f3a9f7088fd29f008dfe691db4adc3cd.png

I am using the TField.OnValidate event as below for these these two fields:

procedure TfrmClose.tbCloseAmtValidate(Sender: TField);
var
  bkMark: TBookmark;
begin
  if Sender = nil then
    exit
  else
    bkMark := sender.DataSet.GetBookmark;
  if (Sender.DataSet.FieldByName('Long Short').AsString = 'Long') then
  begin
    if (Sender.AsFloat < 0) then
    begin
      Sender.Clear;
      Sender.DataSet.Cancel;
      ShowMessage('Close value should be positive or zero');
    end;
  end
  else if (Sender.DataSet.FieldByName('Long Short').AsString = 'Short') then
  begin
    if (Sender.AsFloat > 0) then
    begin
      Sender.Clear;
      Sender.DataSet.Cancel;
      ShowMessage('Close value should be negative or zero');
    end;
  end;
end;

The issue is that the wrong value, while properly removed from the row being validated. The wrong value is posted to the row right below and an exception is thrown. See screenshots below

image.thumb.png.1291571b696a0913ea195aa429173f11.png

 

image.thumb.png.7ae321853249aa93fb12c88b31a014bb.png

 

Edited by kzaveri19

Share this post


Link to post

From the call stack it looks like Validate is called a little to late to modify the value. Documentation says also "To reject the current value of the field from the OnValidate event handler, raise an exception."

I would use Abort like this:

 

procedure TfrmClose.tbCloseAmtValidate(Sender: TField);
begin
  if Sender = nil then
    exit
  if (Sender.DataSet.FieldByName('Long Short').AsString = 'Long') then
  begin
    if (Sender.AsFloat < 0) then
    begin
      ShowMessage('Close value should be positive or zero');
      Abort;
    end;
  end
  else if (Sender.DataSet.FieldByName('Long Short').AsString = 'Short') then
  begin
    if (Sender.AsFloat > 0) then
    begin
      ShowMessage('Close value should be negative or zero');
      Abort;
    end;
  end;
end;

 

Share this post


Link to post

Hi Cristian, Thank you! How do I call it earlier? I am using the vanilla TDBGrid. I believe the OnValidate is triggered when I move the cursor to the next field or the cell below in the same field. I modified your code slightly as below: 

 

procedure TfrmClose.tbCloseAmtValidate(Sender: TField);
begin
  if Sender = nil then
    exit;
  try
    if (Sender.DataSet.FieldByName('Long Short').AsString = 'Long') then
    begin
      if (Sender.AsFloat < 0) then
      begin
        ShowMessage('Close value should be positive or zero');
        raise Exception.Create('Wrong value');
      end;
    end
    else if (Sender.DataSet.FieldByName('Long Short').AsString = 'Short') then
    begin
      if (Sender.AsFloat > 0) then
      begin
        ShowMessage('Close value should be negative or zero');
        raise Exception.Create('Wrong value');
      end;
    end;
  except
    on E : Exception do
    begin
      if E.Message = 'Wrong value' then
        Abort;
    end;
  end;
end;

The cursor stays in the same field (which I want), the the DBGrid copies the value across all records. This is fixed if I correct the value, but looks weird. 

When the error is caught, cursor stays in the same cell, but wrong value displayed across all records

image.thumb.png.43086933f97c544c83f55f0679fadad6.png

 

When the correct value is entered, the DBGrid updates properly and everything works

image.thumb.png.48cc245c12cd456c88db3f9202448f64.png

 

I'm just afraid about the problematic wrong value displayed when abort is called. Is there anyway to fix that? 

 

Thank you again Cristian. I am so glad I joined this group!

Edited by kzaveri19

Share this post


Link to post
5 hours ago, kzaveri19 said:

When the error is caught, cursor stays in the same cell, but wrong value displayed across all records

 

I can't reproduce this issue (the wrong value to be displayed across all records). What Delphi version do you use?

Try to do a minimal example to reproduce this and post here.

5 hours ago, kzaveri19 said:

I modified your code slightly

But why ?!? Your code is more convoluted and I don't see any benefit. Only trouble.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×