If (TablelCode.Required) and (TablelCode.isNull)

Begin

Begin

Begin

Begin

Begin

. . .

х:= Tablel.FieldByName('Date').FieidNo;

 

Для доступа к значению поля служат свойства Value и AsXXX. Свойство Value типа Variant представляет собой фактические данные в объекте типа TField.


При выполнении приложения это свойство используется для чтения и записи значений в поле. Если программист обращается к свойству Value, то он должен самостоятельно обеспечивать преобразование и согласование типов значений полей и читаемых или записываемых значений. В табл. 7.3 приводятся воз­можные типы свойства value для различных объектов типа TField.

 

Таблица 7.3

Возможные типы свойства value

Тип объекта поля Тип свойства Value
TFieid Variant
TStringField, TBLOBField String
TIntegerField, TSmalIntField, TWordField, TAutoincField Longint
TBCDField, TFloatField, TCurrencyField Double
TBooleanField Boolean
TDateTimeField, TDateField, TTimeField TDateTime

 

Рассмотрим пример, в котором доступ к значению поля осуществляется с по­мощью свойства Value:

procedure TForml.ButtonlClick(Sender: TObject);

var s: string;

x: real;

// Доступ к полю по его имени в наборе данных

s:=Tablel.FieldByName('Salary').Value;

x:=Tablel.FieldByName('Salary').Value;

Label1.Caption:=s;

Label2.Caption:=FloatToStr(x);

// Доступ к полю как к отдельному компоненту

х:=TablelSalary.Value;

Label3.Caption:=FloatToStr(x);

// Поле вещественного типа,

// в связи с чем следующий оператор присваивания недопустим

// s:=TablelSalary.Value;

end;

 

Здесь чтение значения поля Salary текущей записи набора данных Tablel вы­полняется несколькими способами. При доступе к полю по имени в наборе данных значение вещественного поля Salary можно читать и использовать и как строковое, и как вещественное значение. При доступе к полю как к отдельному компоненту тип переменной, в данном случае х, должен соответствовать типу поля.


Замечание

Доступ к полю по имени объекта типа TField, например, Tableisalary, возмо­жен только для статических полей, которые существуют на этапе разработки приложения. Попытка использовать имя объекта динамического поля приводит к ошибке при компиляции, т. к. объект поля еще не создан.

Поскольку при доступе к полю с помощью свойства Value программист должен обеспечивать преобразование и согласование типов значений, то часто более удобно использовать варианты свойства AsXXX:

· AsVariant типа Variant;

· AsString типа String;

· As Integer типа Longint;

· AsFloat типа Double;

· AsCurrency типа Currency;

· AsBoolean типа Boolean;

· AsDateTime типа TdateTime.

При использовании любого из этих свойств выполняется автоматическое преоб­разование типа значения поля к типу, соответствующему названию свойства. При этом преобразование должно быть допустимо, в противном случае возни­кает ошибка компиляции по несоответствию типов, например, при попытке прочитать логическое значение как целочисленное.

Приведем теперь пример, где доступ к значению поля происходит с помощью свойств AsXXX:

procedure TForml.Button2Click(Sender: TObject);

var s: string;

x: real;

// Доступ к полю по его имени в наборе данных

s:=Tablel.FieldByName('Salary').AsString;

x:=Tablel.FieldByName('Salary').AsFloat;

Label1.Caption:=s; Label2.Caption:=FloatToStr(x) ;

// Доступ к полю как к отдельному компоненту

s:=TablelSalary.AsString;

х:=TablelSalary.AsFloat;

Label3.Caption:=s;

Label4.Caption:=FloatToStr(x);

end;

Как и в предыдущем примере, чтение значения поля Salary осуществляется не­сколькими способами. Доступ к полю выполняется по имени поля и по имени объекта поля, а значение поля интерпретируется как строковое или как вещест­венное.


Замечание

Для того чтобы записать значение в поле, оно должно допускать модифика­цию, а набор данных должен находиться в соответствующем режиме, напри­мер, редактирования или вставки.

При необходимости программист может запретить модификацию поля, а также скрыть его, используя свойства ReadOnly и Visible типа Boolean. Сама возмож­ность модификации данных в отдельном поле определяется значением свойства CanModify типа Boolean. Напомним, что свойства ReadOnly и CanModify есть также и у набора данных: они определяют возможность модификации набора данных (всех его полей) в целом.

Замечание

Даже если набор данных является модифицируемым и его свойство CanModify имеет значение True, для отдельных полей этого набора редактирование мо­жет быть запрещено, и любая попытка изменить значение такого поля вызовет исключительную ситуацию.

Если поле является невидимым (свойство Visible установлено в False), но разрешено для редактирования (свойство ReadOnly стоит в False), то можно изменить значения этого поля программно.

 

Рассмотрим управление видимостью поля и возможностью его модификации на примере:

Tablel.FieldByName('Number').ReadOnly:=true;

Tablel.FieldByName('Salary').Visible:=false;

 

Здесь для поля Number запрещаются любые изменения, а поле salary скрывает­ся, однако для него по-прежнему допускаются чтение и изменение значения.

Для полей, имеющих типы TBLOBField (BLOB-объект), TGraphicField (графи­ческое изображение) и TMemoField (текст), доступ к их содержимому выполняет­ся обычными для объектов данного типа способами. Например, для загрузки содержимого из файла можно использовать метод LoadFromFile.

Проверка типа и значения поля

При выполнении программы можно выяснить тип данных конкретного поля. Это удобно делать в случае, когда, например, типы данных полей таблиц БД заранее неизвестны.

Тип данных поля таблицы определяет свойство DataType типа TFieldType, при­нимающее следующие значения:

ftUnknown — тип неизвестен или неопределен;

ftString — короткая строка длиной не более 255 символов;

ftSmallInt — короткое целое число;

ftInteger — целое число;


ftWord — целое число без знака;

ftBoolean — логическое значение;

ftFloat — вещественное число;

ftCurrency — денежное значение;

ftBCD — число в формате BCD (двоично-десятичный формат);

ftDate — дата;

ftTime — время;

ftDateTime — дата и время;

ftBytes — байтовое значение фиксированной длины;

ftVarBytes — байтовое значение переменной длины;

ftAutoInc — автоинкрементное значение;

ftBlob — BLOB-объект (Binary Large Object — большой двоичный объект);

ftMemo — текст (Memo);

ftGraphic — графический объект;

ftFmtMemo — форматированный текст (Memo);

ftParadoxoie — поле OLE для таблицы Paradox;

ftDBaseOle — поле OLE для таблицы dBASE;

f tTypedBinary — типированное двоичное значение;

ftCursor — курсор для хранимой процедуры Oracle;

ftFixedChar — фиксированное количество символов;

ftWideString — строка;

ftLargeInt — длинное целое число;

ftADT — значение абстрактного типа;

ftArray — массив;

ftReference — REF-поле;

ftDataSet — DataSet-поле.

 

Программист с помощью специальных свойств может задать ограничения для вводимых в поля значений, а также проверить введенные значения.

Набор символов, допускаемых при вводе значений поля, зависит от типа дан­ных поля:

  • ftBoolean — все символы;

· ftSmallInt — цифры 0 . . . 9, знаки + и -;

· ftWord — цифры 0 . . . 9, знаки + и -;

  • ftAutoInc — цифры 0 . . . 9, знаки + и -;

· ftDate — все символы;

· ftInteger — цифры 0 . . . 9, знаки + и -;

· ftTime — все символы;

· ftCurrency — цифры 0 . . . 9, знаки + и -, символы E или е, разделитель раз­рядов целой и дробной части;

· ftDateTiine — все символы;

· ftFloat — цифры 0 . . . 9, знаки + и -, символы E или е, разделитель разрядов целой и дробной части;

· ftBCD — цифры 0 . . . 9, знаки + и -, символы E или е, разделитель разрядов целой и дробной части;

· ftString, ftVarBytes, ftBytes, ftBlob, ftDBaseOle, ftFmtMemo, ftGraphic, ftMemo, ftParadoxOle, ftTypedBinary, ftUnknown И ftCursor — все символы.

 

Отметим, что разделитель разрядов целой и дробной части числа (десятичный разделитель) зависит от установок Windows, выполненных через панель управ­ления.

Набор допустимых для поля символов содержит свойство validChars типа TFieldChars, который описан как множество символов:

type TFieldChars = set of Char;

 

Для проверки, разрешен ли символ для ввода в качестве значения поля, удобно использовать метод IsValidChar (InputChar: Char): Boolean. Он возвращает зна­чение True, если заданный параметром InputChar символ является для данного поля допустимым, и False — если символ не допускается.

Вот как осуществляется проверка допустимости символа впрограмме:

if not Tablel.Fields[2].IsValidChar(Editl.Text[1]) then

MessageDlg('Символ "'+Editl.Text[1]+'" не допустим!',

mtError, [mbOK], 0);

 

Если первый символ текста, введенного в компонент Editl, не является допус­тимым для поля (третьего в списке полей) набора данных Tablel, то выдается сообщение об ошибке.

Замечание

Проверка на корректность символа не гарантирует отсутствие ошибок при вво­де значений полей. Например, для числового поля ™na.TintegerFieid не по­дойдет значение 12++3, хотя каждый символ является допустимым.

Для полей числовых типов, например, объектов типа TIntegerField и TFloatField свойства MinValue и MaxValue позволяют установить минимально и максимально возможные значения, которые могут быть введены в соответст­вующее поле. Тип этих свойств определяется конкретным объектом типа TField.


Так устанавливается ограничение вводимых значений в программе:

TablelPrice.MinValue:=0;

TablelPrice.MaxValue:=9999.99;

TablelNumber.MinValue:=0;

TablelNumber.MaxValue:=1000;

 

Здесь для поля цены (вещественный тип) устанавливается допустимый диапазон О .. 9999.99, а для поля количества (целый тип) — диапазон 0 .. 1000.

Ограничения на вводимые значения можно определить также с помощью свой­ства customConstraint типа string. В этом свойстве допустимый диапазон зада­ется с помощью конструкций, похожих на команды SQL или фильтры для отбо­ра данных. Отличие заключается в том, что команды SQL и фильтры действуют при формировании наборов данных, а конструкция свойства CustomConstraint — при задании ограничений на вводимые значения. Например:

TablelPrice.CustomConstraint:='Price >= 0 and Price <= 9999.99';

TablelNumber.CustomConstraint:='Number >= 0 and Number <= 1000';

Здесь для полей цены и количества устанавливаются те же диапазоны допусти­мых значений, что и в предыдущем примере.

Если для поля некоторым способом задан диапазон допустимых значений, то при любой попытке установить полю значение, выходящее за границы этого диапазона, вызывается исключительная ситуация. При этом пользователю выда­ется соответствующее сообщение (рис. 7.13), а значение отвергается. Контроль значений относится не только к вводу со стороны пользователя, он также дей­ствует и при изменении значения поля программным способом.


 
 

 

 

Рис. 7.13. Сообщение о выходе значения за допустимый диапазон

С помощью свойства ConstraintErrorMessage типа String разработчик при желании может определить свое собственное сообщение, которое будет выдаваться при нарушении границ диапазона, например:

TablelNumber.CustomConstraint:='Number >= 0 and Number <= 10';

TablelNumber.ConstraintErrorMessage:=

'Количество должно находиться в диапазоне 0 .. 10';

 

Разработчик может не только ограничивать значения, вводимые в поля, но и задавать через свойство DefaultExpression типа string значение по умолчанию, которое автоматически заносится в поле при добавлении новой записи. От­метим, что это свойство строкового типа, поэтому его значения заключаются в кавычки.


 

Пример установки значения по умолчанию:

TablelNumber.DefaultExpression:='100' ;

 

Для проверки, действуют ли для поля ограничения, заданные в свойствах CustomConstraint, DefaultExpression, а также В ImportedConstraint (ограничения, налагаемые сервером), предназначено свойство HasConstraints типа Boolean. Это свойство, действующее во время выполнения приложения, прини­мает значение True, если установлено хотя бы одно из перечисленных ограни­чений.

Кроме проверки выхода за границы допустимых значений, программист мо­жет выполнить и более сложную проверку, используя обработчики собы­тий OnSetText типа TFieldSetTextEvent, OnValidate и OnChange типа TFieldNotifyEvent, которые возникают в перечисленном порядке при изменении значения поля. Типы этих событий описаны следующим образом:

type TFieldSetTextEvent = procedure (Sender: TField; const Text: string) of object;

type TFieldNotifyEvent = procedure (Sender: TField) of object;

 

Все упомянутые события возникают до изменения значения поля, поэтому программист может в необходимых случаях отказаться от внесения изменения. Отказ от изменения значения поля для этих событий выполняется различными способами. При использовании событий OnValidate и OnChange программист возбуждает исключение, в результате чего записи значения в поле не происхо­дит. Если исключение не генерируется, то новое значение заносится в поле. Так как обработчик не получает нового значения поля, то для доступа к нему нужно использовать свойства value или AsXXX. Следует иметь в виду, что эти свойства возвращают новое (предлагаемое для утверждения) значения поля, которое мо­жет быть и не принято, в этом случае происходит возврат к старому значению.

При редактировании поля пользователем события OnValidate и onchange не вы­зываются до тех пор, пока не будет выполнена попытка сохранить изменения, например, нажатием клавиши <Enter>.

Рассмотрим на примере, как осуществляется проверка вводимых значений.

В поле code запрещается ввод значений 1 и 3, которые зарезервированы для специальных целей. При попытке ввода неправильных значений после соответ­ствующей проверки генерируется "тихое" исключение (посредством вызова про­цедуры Abort). В результате попытка ввода отвергается, при этом пользователю никаких сообщений не выдается.

procedure TForml.TablelNumberValidate(Sender: TField);

if (Tablel.FieldByName('Code').AsString = '1') or

(Tablel.FieldByName('Code').AsString = '3')

then Abort;

end;

 

Для выдачи сообщения о возникшей ситуации в дополнение к процедуре Abort можно использовать, например, функцию MessageDig, выводящую диалоговое окно. Кроме того, вместо вызова с помощью Abort "тихого" исключения можно вызвать обычное исключение, например, следующим образом:

Raise Exception.Create('Код не может равняться значениям 1 и 3!');

 

Для события OnSetText действует противоположный порядок принятия измене­ний и отказа от них. Параметр Text обработчика этого события содержит новое значение, которое предложено для занесения в поле, однако запись этого зна­чения автоматически не осуществляется. Поэтому программист должен "вруч­ную" занести предложенное значение в поле: если этого не сделать, то поле ос­тается без изменений. Таким образом, по умолчанию в обработчике события OnSetText новое значение отвергается.

Вот еще один пример, в котором происходит проверка вводимых значений:

procedure TForml.TablelNumberSetText(Sender: TField; const Text: String);

if not ((Text = '1') or (Text = '3'))

then Tablel.FieldByName('Code').AsString:=Text;

end;

 

Ряд полей, например, индексное поле, не могут быть пустыми, в этом случае у поля свойство Required типа Boolean имеет значение True. Для проверки по­лей, содержат ли они отличное от пустого значение, используется свойство IsNull типа Boolean. Это свойство возвращает значение True, если значение по­ля не задано, и значение False — в противном случае. Свойство isNuil можно использовать, например, в обработчиках событий OnSetText, onvaiidate и OnChange.

Например:

procedure TForml.TablelCodeValidate(Sender: TField);

then Raise Exception.Create('Поле кода не может быть пустым!');

end;

 

Иногда перед занесением значения в некоторое поле необходимо проверить, является ли символ допустимым. Для этого можно использовать метод isvaiidchar, проверяющий допустимость заданного символа, и свойство ValidChars, возвращающее набор допустимых для данного поля символов.

Отметим, что некоторые из описанных ограничений на значения полей также могут быть заданы и при создании таблицы БД (запрет пустого значения и за­дание диапазона допустимых значений). В этом случае ограничения действуют на физическом уровне и не могут быть отменены.

Форматирование значения поля

То, как выглядит значение поля в визуальных компонентах, зависит от типа по­ля, а также от системных установок Windows и BDE. Часто возникает необходимость изменить этот вид при отображении значений или их редактировании. Для этого используется форматирование выводимой информации.

Замечание

Названное форматирование относится только к отображению значений в визу­альных компонентах и не затрагивает вид и размещение данных в таблице БД.

 

Свойство DispiayFormat типа string управляет отображением значений полей в визуальных компонентах, например, DBGrid и DBEdit. Это свойство действует для числовых полей, а также для полей даты и времени. В качестве значения свойства DisplayFormat задается маска, определяющая формат отображения поля.

Эта маска состоит из трех секций, разделенных символом ;. Секции задают форму отображения положительных, отрицательных и нулевых значений, соот­ветственно. Если задана только одна секция, то она применяется для вывода всех значений. В маске можно использовать следующие управляющие символы:

0 — цифра числа, незначащие нули отображаются;

# — цифра числа, незначащие нули гасятся;

. — разделитель целой и дробной части числа;

, — разделитель тысяч;

е+ или е+ — разделитель мантиссы и порядка для чисел в форме с плаваю­щей точкой, отображаются положительный и отрицательный знаки порядка;

е- или е- — разделитель мантиссы и порядка для чисел в форме с плаваю­щей точкой, отображается только отрицательный знак порядка;

"хх" и 'хх' — символы, выводимые без изменений; символы, заключенные в кавычки (одиночные или двойные), включаются в отображаемое значение;

; — разделитель секций маски для положительных, отрицательных и нулевых значений.

 

Приведем примеры масок:

000Е-00 или 000Е+00 — для чисел в форме с плавающей точкой;

#####0.00 или 000000.00 — для чисел в форме с фиксированной точкой;

#####0.00' рублей' — для денежных сумм;

####0; -####0; 0 — отдельно для положительных, отрицательных и нулевых значений.

 

Свойство EditFormat типа String задает маску, используемую при форматиро­вании значения числового поля перед его отображением для редактирования в визуальном компоненте. Формирование этой маски не отличается от форми­рования маски, задаваемой в свойстве DisplayFormat.

Свойство EditMask типа string задает маску, используемую при редактировании значения в визуальном компоненте. Маска позволяет ограничить число вводи­мых пользователем символов и тип вводимых символов (алфавитный, цифровой и т. д.). Кроме того, во вводимую информацию можно вставить дополнительные символы (разделители при вводе даты, времени и т. п.). С помощью свойства EditMask удобно вводить телефонные номера, даты, почтовые индексы и другую информацию подобного рода, имеющую заранее определенный формат.

Способы задания маски, содержащейся в свойстве EditMask, рассмотрены в лекции, посвященной визуальным компонентам.

Приведенные свойства DisplayFormat и EditMask независимо друг от друга управляют форматированием значения поля при отображении и при редактиро­вании. Кроме них, для объекта типа TFieid существует событие OnGetText типа TFieldGetTextEvent, в обработчике которого на программном уровне можно од­новременно управлять форматом данных и при отображении, и при редактирова­нии. Это событие генерируется при каждом обращении к свойствам DisplayText и Text. Тип события OnGetText описан следующим образом:

type TFieldGetTextEvent = procedure (Sender: TFieid; var Text: string;

DisplayText: Boolean) of object;

 

Параметр Text содержит значение, которое выводится в визуальном ком­поненте. Программист должен задать это значение. Логический параметр DisplayText указывает, для каких целей выводится значение: для отображения

(DisplayText = True) или для редактирования (DispiayText = False).

Рассмотрим пример, в котором используется форматирование отображаемых и редактируемых значений:

procedure TForml.TablelNameGetText(Sender: TFieid; var Text: String;

DispiayText: Boolean);