I have implemented an editable DBGrid. If a field is not filled correctly an exception is thrown and a message is shown, for example:
'08:00::00' is not a valid time
How can I catch those exceptions so that I can show messages written by me instead of the automatically generated ones? I would be thankful for any help.
As @teran pointed in his comment, the exception is raised by the TDataSet
(or one of it's components) that is bind to the TDBGrid
, or by the DB engine itself.
You can try to handle the TDataSet.OnPostError
(see also OnUpdateError
and OnEditError
):
TDataSet.OnPostError: Occurs when an application attempts to modify or insert a record and an exception is raised. Write an OnPostError event handler to handle exceptions that occur when an attempt to post a record fails.
Note that you could always use Application.OnException
global event handler to catch any EDBxxx exceptions in your application.
EDIT: The EConvertError
exception is raised before any actual data modifications, or any Post operation by the TDateTimeField
field i.e.:
0045af91 +085 Project1.exe SysUtils StrToDateTime <- EConvertError
004ab76a +042 Project1.exe Db TDateTimeField.SetAsString
004a9827 +007 Project1.exe Db TField.SetText
004a95d9 +029 Project1.exe Db TField.SetEditText
004d6448 +014 Project1.exe DBGrids TCustomDBGrid.UpdateData
004d087f +02b Project1.exe DBGrids TGridDataLink.UpdateData
004d599a +01a Project1.exe DBGrids TCustomDBGrid.MoveCol
StrToDateTime
is throwing the exception inside TDateTimeField.SetAsString
, not touching the data, and
the TDataSet.OnxxxError
event handlers will not be fired at all.
So your choices are (test the application in release mode):
1.Intercept and handle EConvertError
via Application.OnException
.
2.Use TField.EditMask
to restrict user input to a valid time format e.g. !90:00;1;_
or use inplace DateTimePicker editor inside your Grid. (and avoid catching this exception).
3.Override TDateTimeField
: use persistent fields with your TDataSet
and create an inter-poser class as such:
type
TDateTimeField = class(Db.TDateTimeField)
protected
procedure SetAsString(const Value: string); override;
end;
TForm1 = class(TForm)
...
procedure TDateTimeField.SetAsString(const Value: string);
begin
try
inherited SetAsString(Value);
except
on E: EConvertError do
begin
ShowMessage(E.Message);
Abort;
end;
end;
end;