Предотвратить несоответствие даты
Я использую cxGrid, в котором у меня есть два поля даты (start_date и end_date), которые получают свои результаты из запроса. Я пытаюсь запретить пользователю вводить неправильный диапазон дат при вводе данных в сетке. Я пытаюсь запретить пользователю вводить конечную дату ниже начальной. Я старался:
procedure TForm1.ABSQuery1BeforePost(DataSet: TDataSet);
begin
if (ABSQuery1.FieldByName('end_DATE').AsDateTime < ABSQuery1.FieldByName('start_DATE').AsDateTime) then
showmessage('end date cant be lower than start date ');
ABSQuery1.Cancel;
end;
Я получаю сообщение об ошибке: набор данных не находится в режиме вставки или редактирования. Как я могу это исправить или есть лучший способ сделать это?
2 ответа
Ваш код неверен: вы вызываете метод Cancel из своей конструкции if, поэтому вы также вызываете его для действительных записей, но не вызываете метод Cancel внутри ваших процедур проверки.
В этом случае cxGrid отвечает за редактирование набора данных, поэтому, если вы действительно хотите запретить пользователям вводить неправильные даты:
Контракт заключается в создании исключения, если вы обнаружите что-то, что не проверяется, поэтому вы можете изменить свой код на что-то вроде этого:
procedure TForm1.ABSQuery1BeforePost(DataSet: TDataSet);
begin
if (ABSQuery1.FieldByName('end_DATE').AsDateTime < ABSQuery1.FieldByName('start_DATE').AsDateTime) then
raise Exception.Create('end date can''t be lower than start date');
end;
Было бы лучше, если бы вы определили свой собственный класс Exception, чтобы не вызывать (слишком) универсальный экземпляр Exception, например:
type
EInputValidationError = class(Exception)
end;
procedure TForm1.ABSQuery1BeforePost(DataSet: TDataSet);
begin
if (ABSQuery1.FieldByName('end_DATE').AsDateTime < ABSQuery1.FieldByName('start_DATE').AsDateTime) then
raise EInputValidationError.Create('end date can''t be lower than start date');
end;
Таким образом, в будущем вы сможете отличить ошибки проверки входных данных от других типов исключений, возникающих в вашей программе.
Я бы предпочел использование OnValidate из полей end_date
а также start_date
, так как это будет повышаться при настройке значений полей, что произойдет задолго до публикации. Это может быть интересно, если нужно ввести много полей и, например, пользователь редактирует на третьей вкладке при публикации, в то время как ввод дат находится на первой вкладке.
procedure TForm5.DateSpanValidateValidate(Sender: TField);
begin
if not Sender.DataSet.FieldByName('end_DATE')
.IsNull and not Sender.DataSet.FieldByName('start_DATE').IsNull then
if (Sender.DataSet.FieldByName('end_DATE')
.AsDateTime < Sender.DataSet.FieldByName('start_DATE').AsDateTime) then
raise EYourValidationError.Create(
'end date can''t be lower than start date');
end;