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);