6. Работа с полями - компонент TField

6.1. Применение TField *

6.2. Использование редактора полей для организации компонентов TField и установки значений их свойств *

6.3. Типы полей *

6.4 Обращение к полям и их значениям *

6.5. Обращение к значению поля. Свойства Value и AsNNN *

6.6. Форматирование значений полей при их показе в визуальных компонентах во время выполнения *

6.6.1. Событие OnGetText *

6.6.2. Свойство DisplayFormat *

6.7. Форматирование полей во время их редактирования *

6.8. Проверка введенного в поле значения *

6.8.1. Свойство IsNull и обработчики событий OnSetText, On Validate, OnChange *

6.8.2. Значение поля по умолчанию и ограничения на значения поля *

6.9. Создание вычисляемых полей *

6.10. Создание полей выбора данных (lookup-полей) *

6.10.1. Поля выбора данных *

6.10.2. Поля выбора данных, использующиеся для занесения информации. Коды и семантически значимые поля *

6.10.3. Буфер значений полей выбора данных *

6.11. Обзор полей TxxxField *

6.12. Информация о типе поля *

6.13. Информация о виде поля *

6.14. Имя поля в SQL-запросах *

6.15. Проверка применимости символа в поле *

6. Работа с полями - компонент TField

6.1. Применение TField

Компонент TField позволяет обращаться к полям таблиц баз данных. Каждый набор данных - неважно, ТТаЫе или TQuery - состоит из записей, а те, в свою очередь, состоят из полей. Таким образом, в составе записи имеется минимум одно поле.

В Delphi имеется возможность использовать при работе с НД или все поля, определенные в данной ТБД на текущий момент, или использовать только часть существующих полей.

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

Существует два способа задания состава полей для НД.

Первый состоит в том, что после создания НД (компонент ТТаЫе или TQuery) не предпринимается никаких дополнительных действий по уточнению состава полей. Тогда:

для компонента TTable - будет разрешен доступ ко всем полям, определенным в данный момент в ТБД, связанной с компонентом ТТаЫе;

для компонента TQuery - будет разрешен доступ ко всем полям (в том числе и результатам выражений), указанным в списке возвращаемых полей в операторе SELECT. Хотя этот оператор в результате выполнения SQL-запроса может возвращать НД, составленный из нескольких физических ТБД, сами поля будут считаться принадлежащими к единому НД, образовавшемуся в результате выполнения SQL-запроса из свойства TQuery.SQL. К полю в этом случае можно обращаться с помощью метода FieldByName компонентов TTable и TQuery

function FieldByName(const FieldName: string): TField;

или через свойство указанных компонентов Fields [Index], которое возвращает указатель на тип TField. Подробнее об этом свойстве будет сказано ниже.

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

го, rt property DefaultFields: Boolean;

ЗАМЕЧАНИЕ. Аббревиатура го (read only) означает, что свойство доступно только для чтения; rt (run time) означает, что свойство доступно только во время выполнения приложения. Полный список принятых сокращений см. в начале книги. Значение True указывает, что используются поля по умолчанию; False -

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

Второй способ определения состава полей заключается в том, что для данного НД поля как компоненты TField добавляются в форму с помощью редактора полей Delphi. О нем будет сказано чуть ниже.

К таким полям можно обращаться через его имя, определяемое в свойстве Name компонента TField, соответствующего данному полю.

По умолчанию, при добавлении в форму компонента TField, его имя генерируется так: берется имя НД (т.е. значение свойства Name компонента TTable или TQuery, к которому принадлежит поле) и к нему добавляется имя поля, взятое из структуры ТБД (TTable) или из запроса (TQuery).

Так, поле с именем FIO, используемый в НД Students, при добавлении в форму средствами редактора полей, получит имя StudentsFIO.

ЗАМЕЧАНИЕ. Это имя будет относиться целиком к компоненту TField, а не только к значению (например, "Иванов И.И."), которое поле FIO содержит в текущей записи ТБД. Компонент TField, как будет показано ниже, обладает рядом свойств, методов и событий, обращаться к которым следует через указание имени компонента TField и имени свойства, метода или обработчика события, например:

StudentsFIO. Index := 5; // изменить порядковый номер поля StudentsFIO. Readonly := True; //запретить изменение значений поля

Таким образом, экземпляр StudentsFIO компонента TField трактуется не как конкретное значение, которое принимает поле FIO в конкретной строке ТБД, а как весь столбец набора данных, обладающий единым поведением, т.е. едиными свойствами, методами и событиями для всех записей набора данных. Значение поля для текущей записи доступно с помощью свойств Value, AsBoolean, AsString и т.д. Например:

IF StudentsFIO.AsString = 'Иванов' then ....

Итак, когда поле НД определено в форме в качестве экземпляра компонента TField, к нему можно обращаться по имени (содержащемуся в свойстве Name), а также через метод НД FieldByName и свойство Fields [Index].

Если хотя бы для одного поля НД создан компонент TField, первый принцип, т.е. принцип использования всех полей ТБД или результата SQL-запроса, отвергается. В НД будут считаться определенными только те поля, для которых созданы компоненты TField, а иные поля - отвергаться как несуществующие для данного НД (TTable или TQuery).

К "несуществующим" полям обратиться изданного НД нельзя никак. Такие попытки будут возбуждать исключительные ситуации с сообщением 'Field <имя> not found'.

Вновь вернуться к принципу использования всех полей ТБД или результата SQL-запроса можно, удалив в редакторе полей все определенные ранее TField или добавив с его помощью недостающие поля.

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

ЗАМЕЧАНИЕ. Если нужно иметь доступ к полю, но не показывать его значений в компонентах, визуализирующих данные (например, в компоненте TDBGrid), свойство Visible этого поля следует установить в состояние False.

6.2. Использование редактора полей для организации компонентов TField и установки значений их свойств

Для того, чтобы определить один или несколько компонентов TField, нужно:

1. Выбрать необходимый НД (компонент TTable или TQuery);

2. Нажать правую кнопку мыши;

3. Во всплывающем меню выбрать режим Field Editor (запуская тем самым редактор полей};

4. Вновь нажать правую кнопку мыши и во всплывающем меню выбрать Add Fields',

5. В появившемся списке полей ТБД (TTable) или полей, участвующих в запросе (TQuery), выбрать необходимые (рис. 6.1)

и нажать кнопку Ok. Для каждого из указанных полей будет создан компонент TField:

6. Если необходимо изменить свойства конкретного поля или написать обработчик для какого-либо события, необходимо в редакторе полей выбрать нужное поле и, используя инспектор объектов, установить значение в свойство или определить обработчик события.

6.3. Типы полей

Поля в таблицах баз данных различаются по типу - символьные, целочисленные, логические, blob-поля и т.д.

Соответственно, по типу различаются и компоненты TField, и собственно, TField есть родительский тип, определяющий базовые свойства и методы для своих потомков, типизированных полей. Иерархия компонентов- полей такова:

TField

TBIobField большой двоичный объект

TGraphicField графическое поле(работает с содержимым blob-поля как с графическим изображением)

TMemoField мемо-поле (интерпретирует BLOB-поле как большой текст)

TBooleanField логическое поле

TBinaryField нетипизированное двоичное поле

TBytesFieid поле для хранения байтовых значений фиксированной длины

TVarBytesField поле для хранения байтовых значений переменной длины

TDateTimeField поле для хранения даты и времени

TDateField поле для хранения только даты

TTimeField поле для хранения только времзни

TNumericField поле для хранения числовых значений

TBCDField BCD-значений

TFloaTField значений с плавающей точкой

TCurrencyField в том числе в денежном формате

TIntegerField целочисленных значений

TAutoIncField в том числе автоинкрементных

TSmallIntField в том числе коротких целых

TWordField в том числе в формате беззнакового длинного целого

TStringField поле для хранения строковых значений

Особенности каждого типа будут рассмотрены ниже, равно как и процедуры и функции Delphi, применяемые для работы с полями определенных типов. Покажем общие для всех этих типов свойства, методы и события.

6.4 Обращение к полям и их значениям

Как было сказано в п. 6.1, следует различать обращение к полю и обращение к его значению. Рассмотрим способы обращения к полям.

К полю можно обратиться, указав имя поля несколькими способами :

1. Если полю соответствует компонент TField - через имя данного компонента, которое определяется свойством Name. Повторим, что по умолчанию имя компонента TField устанавливается как результат сцепления имени TTable или TQuery и собственно имени поля в ТБД. Например, для поля FIO, определенного в ТБД, работа с которой происходит через Table 1, по умолчанию будет выбрано имя Table I FIO. Тогда использование поля происходит подобно приведенному ниже:

Table1FIO.AsString := 'Иванов'; // или

Table1FIO.Value := 'Иванов';

2. Используя метод FieldByName ('ИмяПоля ') набора данных, function FieldByName(const FieldName: string): TField;

Например,

Table1.FieldByName('FIO).AsString := 'Иванов'; //или

Table1.FieldByName('FIO).Value:= 'Иванов';

3. Используя свойство Fields[индекс] набора данных,

property Fields[Index: Integer]: TField;

Индекс является порядковым номером поля в определении ТБД. Отсчет идет от 0. Пусть поле Name определено в ТБД третьим по счету. Тогда его индекс равен 2 и использование поля может происходить так:

Table1.Fields[2].AsString := 'Иванов'; // или

Tablel.Fields[2].Value:= 'Иванов' ;

Если поле входит в индекс данного НД, свойство IsIndexField: Boolean;

возвращает во время выполнения значение True.

4. Используя свойство набора данных

property FieldValues|const FieldName: string]: Variant;

Это свойство позволяет обращаться к полю через его имя, указываемое как содержимое параметра FieldName, например: Tablel.FieldValues['FIO'] := 'Иванов';

Поскольку свойство FieldValues принимается для набора данных по умолчанию, его имя при обращении к полю можно опускать: Tablel['Name'] := 'Иванов' ;

ЗАМЕЧАНИЕ 1. Более предпочтительным считается обращение к полю через его имя или через метод FieldByName, поскольку в этом случае мы обращаемся к конкретному полю по его имени. Следовательно, к несуществующему полю обратиться нельзя.

Пусть поле FIO удалено из структуры ТБД. Тогда обращение к нему по имени из ассоциированного с данной ТБД НД приведет к ошибке.

Менее предпочтительным является обращение к полю через свойство набора данных Fields [индекс]. Если поле FIO было объявлено в ТБД вторым по счету (обращение Fields[l]), а затем удалено из структуры ТБД, обращение Fields[l] в программном коде будет воспринято как обращение к физически второму полю в ТБД. Этим полем будет третье поле, следовавшее за FIO перед тем, как FIO было удалено из структуры ТБД. После удаления FIO третье поле станет по счету вторым.

Налицо алгоритмическая ошибка, которая может быть не распознана, если FIO и поле, ставшее после удаления FIO вторым, имеют одинаковые или совместимые типы.

Такие ошибки очень трудно локализовать. Поэтому, если это возможно, следует воздержаться от обращения к полю через Fields [индекс].

ЗАМЕЧАНИЕ 2. Свойство Index компонента TField содержит порядковый номер поля:

• в ТБД, если для компонента TTable, ассоциированного с данной ТБД, не создано ни одного компонента TField;

• в списке компонентов TField, относящихся к данному НД - для компонента TTable, если для него определен хотя бы один TField, и всегда - для компонента TQuery.

Порядок следования полей важен, когда содержимое НД визуализируется посредством компонента TDBGrid. В этом случае номер столбца в компоненте TDBGrid соответствует номеру поля в списке TField. И наоборот, если изменить порядок столбца в компоненте TDBGrid (например, "перетащив" столбец на другое место), это приведет к изменению индекса и Fields[l] до перетаскивания будет относиться к другому полю, нежели Fields[l] после перетаскивания столбцов, поскольку свойство Index перетаскиваемого и некоторых других полей изменится.

Это относится как к случаю, когда TField для НД определены, так и к случаю, когда используются все поля ТБД. В последнем случае "перетаскивание" столбца в компоненте TDBGrid на новое место, конечно, не изменит физического порядка следования полей в структуре ТБД; однако с логической точки зрения его индекс (порядковый номер) для данного НД изменится.

Последствия, которые могут принести в структуру НД изменения свойства Index, делают обращения к полю через свойство Fields [индекс] набора данных нежелательными.

6.5. Обращение к значению поля. Свойства Value и AsNNN

К значению поля можно обратиться при помощи свойств Value и AsNNN. Свойство

property Value: Variant

возвращает значения следующих типов:

property Value Variant; // Все компоненты

property Value string; //TStringField, TBIobField

property Value Longint; //TAutoIncField, TIntegerField, TSmallintField,TWordField

property Value Double; //TBCDField, TCurrencyField, TFloatField

property Value Boolean; //TBooleanField

property Value TDateTime; //TDateField, TDateTimeField, TTimeField

Это дает возможность пользоваться свойствами приведения типов полей (AsString, Aslnteger и т.д.) в гораздо меньших масштабах. Тем не менее, обойтись без них удается далеко не всегда.

Аналогичные значения возвращает рассмотренное в предыдущем разделе свойство набора данных FieldValues.

Например,

var N : Integer;

N := TablelNumber.Value; // TablelNumber типа TIngereField

Обращение к значению поля через свойство AsNNN.

Существуют следующие свойства приведения типов полей:

property AsBoolean: Boolean;

property AsCurrency: Currency;

property AsDateTime: TDateTime;

property AsFloat: Double;

property Aslnteger: Integer;

property AsString: String;

property As Variant: Variant;

Каждое из этих свойств приводит значение поля к соответствующему типу данных, означенному в названии свойства. Например, если TablelNumber -компонент TIntegerField (поле, хранящее целочисленные значения), для приведения его к типу String можно воспользоваться свойством

Editl.Text := TablelNumber.AsString;

Несомненно, тип поля должен быть совместимым с типом данных, к которому приводится значение поля. Например, если TablelSumma - компонент TFloatField (поле, хранящее вещественные значения), попытка привести его к несовместимому типу Boolean, IF TablelSumma.AsBoolean THEN ...

приведет к ошибке компиляции.

В приводимой ниже таблице показана совместимость значений полей разных типов.

Обозначение:

= типы равнозначны;

+ преобразование возможно;

+ RI преобразование возможно, округление до ближайшего целого;

? преобразование происходит, если возможно; часто зависит от формата показа (свойство DisplayFormat);

х преобразование не разрешено;

Рассмотрим свойства семейства AsNNN более подробно:

property AsBoolean: Boolean; - числовые значения приводятся к типу Boolean, если содержат 0 (False) или 1 (True). Символьные значения - если содержат в качестве первого символа "Y", "у", "Т" или "t" (или "Yes" или "True"), и False во всех иных случаях.

property AsDateTime: TDateTime; - для приведения к типу TDateTime значений TDateField, TDateTimeField и TTimeField, хотя вместо этого лучше использовать свойство Value, а также для приведения к типу TDateTime строковых значений, находящихся в соответствующем формате.

property AsFloat: Double; - служит для приведения к типу Double значений полей TFloatField, TBCDField и TCurrencyField, AsFloat, хотя вместо этого лучше использовать свойство Value.

property Aslnteger: Longint; - служит для приведения к типу Longint полей типа TIntegerField, TSmallintField и TWordField, хотя вместо этого лучше использовать свойство Value.

Для полей типа TStringField преобразование к Longint выполняется, если оно возможно.

property AsCurrency: Currency; - служит для приведения к типу Currency. property AsString: string; - служит для приведения к типу String. property As Variant: Variant; - служит для приведения к типу Variant.

6.6. Форматирование значений полей при их показе в визуальных компонентах во время выполнения

6.6.1. Событие OnGetText

Пусть поле ТБД хранится не в том виде, в котором должно показываться. Тогда отформатировать его перед тем, как оно будет показано в визуальных компонентах, работающих с данными - TDBGrid, TDBEdit и т.д., можно, определив алгоритм форматирования в обработчике события OnGetText для данного компонента TField.

В процедуре-обработчике присутствуют такие параметры:

Text - отформатированное значение, показываемое в столбце компонента TDBGrid, в TDBEdit или других визуальных компонентах, связанных с БД;

Display Text - позволяет определить, произошло событие OnGetText при показе значения (значений) поля (True) или при модификации пользователем значения поля (False).

Пример. Пусть поле Company входит в состав ТБД, содержимое которой показывается в TDBGrid с использованием Table 1. Необходимо при показе содержимое данного поля заключать в кавычки (хотя оно хранится без кавычек). Если пользователь захочет изменить значение поля в какой-либо записи, нужно показывать содержимое поля, представленное заглавными буквами.

procedure TForm1.Table1CompanyGetText(Sender: TField; var

Text: OpenString;

DisplayText: Boolean);

begin

IF DisplayText THEN

Text := '"' + TablelCompany.AsString + '"'

ELSE

Text := AnsiUpperCase(TablelCompany.AsString);

end;

Когда происходит показ некоторой записи из Table 1 в TDBGrid, для нее возникает событие OnGetText и вызывается приведенный выше обработчик с DisplayText = True. В результате в компоненте TDBGrid весь столбец, соответствующий полю TablelCompany, будет содержать значения в кавычках.

Затем, если пользователь захочет в какой-либо записи изменить значение данного поля, оно будет выдано ему для редактирования заглавными буквами.

ОГРАНИЧЕНИЕ. Если для поля определен обработчик события OnGetText, игнорируются режимы форматирования, определенные в свойствах DisplayFormat и EditMask данного поля.

6.6.2. Свойство DisplayFormat

Свойство

property DisplayFormat: string;

применяется для форматирования при показе полей типа TDateField, TDateTimeField, TIntegerField, TSmallintField, TTimeField, TWordField.

Для форматирования полей типа TIntegerField, TSmallintField и TWordField может также применяться стандартная процедура procedure Str(X [: Width [: Decimals ]]; var S);

Для форматирования полей типа TDateField, TDateTimeField и TTimeField применяется функция function Date TimeToStr (Date Time: TDateTime): String;

Для форматирования полей типа TBCDField, TCurrencyField и TFloatField применяется функция function FloatToTextFmt(Buffer: PChar; Value: Extended:

Format: PChar): Integer;

Поддерживаются следующие спецификаторы форматов:

Спец-р

Что влечет

0

Число. Если незначащий разряд равен 0, показывать его.

#

Число. Если незначащий разряд равен 0, не показывать его.

 

Десятичная точка. Разделяет целую и дробную часть числа Принимается во внимание только первая точка, остальные игнорируются.

'

Разделитель тысяч. Каждая группа чисел из 3 разрядов в целой части отделяется от иных разрядов запятой.

'

Разделяет положительное, отрицательное и нулевое значение.

Е+

Научный формат действительных чисел

"XX' или 'XX'

Символы внутри двойных или одинарных парных кавычек не форматируются и выводятся как есть. Например, число 123.45 с форматом '#.# "рублей"' выведется как '123.5 рублей'

Примеры использования форматов.

Форматируемое число

987654.321

-987654.321

0.27

-0.27

0

не форматировано

987654.321

-987654.321

0.27

-0.27

0

0

987654

-987654

0

0

0

0.00

987654.32

-987654.32

0.27

0

0.00

#

987654

-987654

     

#.##

987654.32

-987654.32

.27

-.27

 

#,##0.00

987,654.32

-987,654.32

0.27

-0.27

0.00

#,##0.00; (#,##0.0)

987,654.32

(987,654.32)

0.27

(0.3)

0.00

#,##0.00;; Нолик

987,654.32

-987,654.32

0.27

-0.27

Нолик

О.ОООЕ+00

9.877Е+05

-9.877Е+0

2.700Е-01

-2.700E-01

0.000Е+00

#.###Е-0

9.877Е5

-9.877Е5

2.7Е-1

-2.7Е-1

0Е0

Пусть значение поля 3456.777. Тогда, если DisplayFormat := '#.##', то будет показано 3456.78.

ЗАМЕЧАНИЕ. Формат показа поля может быть динамически переназначен во время выполнения. Например, для заполнения данной таблицы мы воспользовались компонентами Edit1 и Button1 и производили динамическую замену формата поля Table I Salary так:

procedure TForm1.Button1Click(Sender: TObject);

begin

Table1Salary.DisplayFormat := Edit1.Text;

end;

DisplayFormat игнорируется, если определен обработчик для события OnGetText.

ЗАМЕЧАНИЕ. В случае, если поле, требующее обязательного ввода в него значения (свойство Required = True), на момент запоминания в таблице БД (т.е. на момент начала выполнения метода Post) содержит пустое или нулевое значение, возбуждается исключение EDBEditError.

6.7. Форматирование полей во время их редактирования

Свойство property EditMask: string;

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

Для строковых полей значение данного свойства может использоваться для форматирования не только входных, но и выходных значений вместе со свойством Display Text.

Маска представляет собой символьную строку. Она состоит из 3-х частей:

1. Собственно маска;

2. Символ, определяющий, будут ли литералы (символ после указателя '\') включаться в форматируемое значение как его часть (значение 1) или не будут(значение 0);

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

Символы, которые могут входить в маску:

!

Подавляет ведущие пробелы. В отсутствие этого символа в данных подавляются хвостовые пробелы

>

Все следующие символы будут на верхнем регистре, пока не встретится символ <

<

Все следующие символы будут на нижнем регистре, пока не встретится символ >

<>

Регистр не проверяется. Все остается на том регистре, как ввел пользователь

\

Следующий за ним символ является литералом, т.е. включается в форматируемое значение

L

В данной позиции должен появиться только символ алфавита

|

Аналогично L, но символ в данной позиции может и отсутствовать

А

В данной позиции должен появиться только символ алфавита или цифра

а

Аналогично А, но символ в данной позиции может и отсутствовать

С

В позиции обязателен любой символ

с

Аналогично С, но символ в данной позиции может отсутствовать

0

В данной позиции обязателен цифровой символ

9

В данной позиции должен появляться только цифровой символ или не появляться никакой

#

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

:

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

/

Разделитель месяца, дня и года в датах. Если в данной национальной кодировке для указанных целей используется иной символ, он используется вместо символа ':'

;

Разделитель частей маски

_

Заменитель пробела в маске

В модуле Mask имеются следующие константы, которые определяют некоторые компоненты маски по умолчанию

Имя константы

Нач.значение

Смысл

DetaultBlank

_

Обозначение пробела в маске

MaskFieldSeparator

,

Разделитель частей маски

MaskNoSave

0

Если 0, символы маски не будут включаться в значение; если 1,-будут.

Пример. Маска '!\(999\)000\-00\-00;1;_'. Введено '0952223344'. В период ввода представлялось на экране как '(095)222-33-44', запомнилось как '(095)222-33-44'. Если бы была использована маска '!\(999\)000\-00\-00;0;_', в период ввода представлялось на экране как '(095)222-33-44', запомнилось как '0952223344'.

Значение свойства Edit Mask игнорируется, если определен обработчик для события OnGelText.

Свойство го property EditMaskPtr: string;

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

Свойство property EditFormat: string;

применяется для форматирования значений полей типа TIntegerField, TSmallintField, TWordField перед их редактированием. Форматирование выполняется функцией Float To TextFmt.

Пример. Пусть значение поля 3456.777. Тогда если EditFormat := '#.#', то при редактировании значение поля первоначально будет показано как 3456.8.

Свойство property Text: string;

содержит строковое изображение значения поля в том виде, в котором оно показывается в визуальном компоненте, когда НД находится в режиме редактирования (dsEdit) . Свойство Display Text содержит строковое изображение значения поля, когда НД находится не в режиме редактирования.

6.8. Проверка введенного в поле значения

6.8.1. Свойство IsNull и обработчики событий OnSetText, On Validate, OnChange

Свойство IsNull: Boolean; во время выполнения возвращает True, если поле содержит пустое значение.

Проверить введенное в поле значение на его соответствие некоторым ограничениям или условиям можно в обработчике события OnValidate. Это событие наступает при изменении значения поля либо вручную, либо программно. Событие наступает до выполнения метода Post, который запоминает изменения БД. Поэтому, если полю присвоено неверное значение, выполнение метода Post можно предотвратить, выполнив метод Abort или возбудив исключительную ситуацию (raise Exception.Create}. Заметим, что для новых записей данное событие выставляется также, поскольку при занесении значений в поля пустые значения заменяются на непустые (т.е. модифи-цируются). Данный подход контроля правильности значений называется ориентированным на поля.

Существует и другой подход, ориентированный на записи. Он состоит в том, что в структуре ТБД при ее определении описываются ограничения на значения, которые может принимать данное поле. В этом случае контроль правильности ведется автоматически.

Пример. Пусть поле Table I Company не должно содержать символа '@'.

procedure TForm1.Table1CompanyValidate(Sender: TField) ;

begin

IF POS('@',TablelCompany.AsString) > 0 THEN

begin

ShowMessage('Обнаружен символ @!');

Abort;

end;

end;

или

procedure TForm1.Table1CompanyValidate(Sender: TField);

begin

IF POS('@',TablelCompany.AsString) > 0 THEN

raise Exception.Create('Неверное значение');

end;

Если символ '@' содержится в значении, присвоенном полю, метод Abort или принудительно возбужденная исключительная ситуация не позволят выполниться методу Post и запись с неверным полем не будет физически записана в БД НД останется в том состоянии, в котором он находился (режиме редактирования dsEdit или добавления новой записи dslnsert}.

Для проверки введенного значения может быть использовано и другое событие, OnSetText Подобно событию OnVahdate, оно возникает при изменении значения поля Однако на момент события новое значение полю не присвоено и, если этого не сделать программно в обработчике события, сделано никогда не будет.

Например, пусть в поле Table 1PUR_PRICE типа TFloatField было изменено значение с 10 на 200 Пусть новое значение не должно превышать 100 Тогда обработчик события будет выглядеть так

procedure TFormI.TablelPUR_PRICESetText(Sender: TField; const Text: String);

var Tmp : Real;

begin

Tmp := StrToFloat(Text);

IF Tmp > 100 THEN

ShowMessage('Ошибочное значение')

ELSE

TablelPUR_PRICE.Value := Tmp;

end;

что аналогично такому обработчику события OnVahdate.

procedure TFormI.TablelPUR_PRICEValidate(Sender: TField);

begin

IF TablelPUR_PRICE.Value > 100 THEN begin

ShowMessage('Ошибочное значение');

Abort;

END;//if

end;

Как видно, особенность события OnSetText состоит в том, что в обработчик передается константа-параметр Text, содержащая в текстовом виде новое значение, назначенное полю, в то время как действительное значение поля остается без изменения

Третье событие, OnChange, может быть использовано для тех же целей, что и On Validate

procedure TFormI.TablelPUR_PRICEChange(Sender: TField);

begin

IF TablelPUR_PRICE.Value > 100 THEN

raise Exception.Create('Ошибочное значение');

end;

Порядок вызова обработчиков событий OnSetText, On Validate, OnChange

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

1 OnSetText;

2 On Validate,

3 OnChange

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

Относительно события OnSetText известно, что если полю присвоено ошибочное значение, то нет нужды выполнять метод Abort или возбуждать исключительную ситуацию для предотвращения занесения этой записи в ТБД (поскольку новое значение в поле в этом случае еще не занесено) Наоборот, если поле удовлетворяет критериям правильности, в него программно нужно записать введенное пользователем новое значение (передаваемое в обработчик как параметр const Text String)

В обработчиках событий OnVahdate и OnChange, наоборот, в этом случае необходимо выполнять метол Abort или возбуждать исключительную ситуацию для предотвращения занесения этой записи в ТБД (поскольку новое значение в поле в этом случае уже занесено)

Однако следует помнить, что событие OnChange возникает только после события On Validate Поэтому, обработчик события OnChange может быть и не вызван, если обработчик On Validate выполняет метод Abort или возбуждает исключительную ситуацию для того, чтобы измененная запись с некорректным значением поля не была записана в ТБД

6.8.2. Значение поля по умолчанию и ограничения на значения поля

Значение поля по умолчанию можно установить при помощи свойства property DefaultExpression: string;

В случае указания значений, отличных от целочисленного, они должны заключаться в кавычки

В компоненте TField могут быть определены ограничения на значения этого или иных полей. Ограничение указывается при помощи SQL-подобного синтаксиса в свойстве

property CustomConstraint: string;

например,

TablelOklad.CustomConstraint :=' Oklad >= 300 and Oklad <= 2000';

Свойство property ConstraintErrorMessage: string;

позволяет указать сообщение об ошибке, выдаваемое пользователю в случае, если введенное значение поля не удовлетворяет ограничению, указанному в свойстве CustomConstraint, например

TablelOklad. ConstraintErrorMessage := ' Оклад должен быть в диапазоне 300...2000 ';

Свойство property ImportedConstraint: string;

содержит ограничения значения поля, "навязанные" сервером. Их не нужно переопределять; дополнительные ограничения можно наложить при помощи свойства CustomConstraint.

Свойство ro property HasConstraints: Boolean;

возвращает True, если для поля определены ограничения в свойствах CustomConstraint, ImportedConstraint или DefaultExpression. В противном случае свойство возвращает False.

6.9. Создание вычисляемых полей

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

1. В редакторе полей необходимо создать новое поле, пометив его как Calculated. Для этого нужно сделать текущим (при помощи мыши) необходимый НД, нажать правую кнопку мыши, выбрать в меню Field Editor и снова нажать правую кнопку мыши и выбрать в меню New Field. Затем в окне диалога необходимо указать имя поля, его тип и для строковых полей - длину (рис. 6.3).

Для нового поля будет создан компонент TField, доступ к которому отныне можно осуществлять редакторе полей. 2. Для компонента НД, к которому принадлежит вычисляемое поле,

необходимо определить обработчик события OnCalcFields. Например, для НД Table 1, ассоциированному с ТБД "Сотрудники", будем заносить в вычисляемое поле TablelVychis! значение 'Да', если в поле Table1inYaz (знание иностранных языков) этой записи содержится значение True. В противном случае в поле TablelVychis! будем заносить пустое значение (форма приложения показана на рис. 6.4.):

procedure TGridForm.TablelCalcFields(DataSet: TDataSet) ;

begin

IF Table1InYaz.Value THEN TablelVychos!.AsString := 'Да' ELSE

TablelVychosl.AsString := '';

end;

Событие OnCalcFields возникает всякий раз, когда курсор (указатель записи) перемещается в НД от записи к записи (например, после выполнения методов Next, Last и т.д., или при движении по записям в TDBGrid вручную). Это событие возникает и при инициализации НД (после открытия), а также после фильтрации записей в НД, что, впрочем также связано с изменением местоположения указателя записи.

Кроме того, если свойство набора данных AutoCalcFields установлено в True, событие OnCalcFields наступает также и при модификации значений невычисляемых полей в режимах dslnsert и dsEdit данного НД или НД, реляционно с ним связанного (когда установлены ограничения целостности в самой ТБД, а не тогда, когда они подразумеваются).

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

ЗАМЕЧАНИЕ. Иногда бывает необходимым присваивать вычисляемым полям значения, не содержащиеся в полях других таблиц. Иными словами, иногда бывает полезным записывать в вычисляемое поле значение некоторых переменных формы. Например, пусть мы добавляем записи в НД ТЫ, по некоторому алгоритму рассчитывая значения поля Summa. Пусть для расчета значения поля Summa используется переменная TekOstatok. И мы хотим значение TekOstatok для каждой записи занести в вычисляемое поле TbITO.

И здесь встречается одна сложность: занесение значения в вычисляемое поле производится в обработчике события OnCalcFields и это происходит в то время, когда значения локальной переменной TekOstatok уже утрачены.

В этой ситуации в процессе выполнения алгоритма, добавляющего записи в ТЬ1, приходится запоминать значения локальной переменной в каком-либо динамическом списке, а затем извлекать из него соответствующие элементы в обработчике события OnCalcFields, присваивая значения этих элементов полю TbITO.

6.10. Создание полей выбора данных (lookup-полей)

6.10.1. Поля выбора данных

Кроме обычных полей, связанных с полями ТБД, и вычисляемых полей, в Delphi имеется возможность создавать поля выбора данных (lookup).

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

Для определения поля набора данных необходимо создать новое поле в редакторе полей, сразу же установив радио-группу Field Type в значение Lookup (рис. 6.5.).

Затем устанавливаем значения свойств:

DataSet - Имя НД-источника значений для поля выбора данных;

Key Fields - Индексные поля набора данных-владельца поля выбора данных. По этим полям НД-владелец соединяется с НД-источником значений поля выбора данных. Если в индексе имеется несколько полей, они перечисляются через точку с запятой;

Lookup Fields - Индексные поля НД-источника значений для поля выбора. По значениям этих индексных полей устанавливается связь набора-источника со значениями индексных полей НД-владельца поля выбора (они указаны в параметре Key Fields). Если в индексе имеется несколько полей, они перечисляются через точку с запятой;

Result Field - Поле набора данных-источника, возвращаемое в качестве результата. Необходимо следить, чтобы тип вновь создаваемого поля и поля результата совпадали.

Указанным выше параметрам редактора полей соответствуют свойства компонента TField

property LookupDataSet: TDataSet;

property KeyFields: string;

property LookupKeyFields: string;

property LookupResultField: string;

Аналогичным по последствиям будет установка соответствующих свойств в инспекторе объектов для вновь добавляемого поля. Заметим, что свойство поля

property Lookup: Boolean;

должно быть установлено в True.

Разберем пример отношения "один-к-одному" Пусть существует ТБД 'Сотрудники", которая включает в себя поля "Табельный номер" (TabNum), "ФИО" (FIO), "Должность" (Doljnost) и "Ученая степень" (UchStepen) С ней ассоциирован НД Table 1 (рис 6 6)

и ТБД "Информация о сотрудниках", которая включает в себя ФИО сотрудника (поле FIO), год рождения (GodRojd) и семейное положение (SemPoloj). С ней ассоциирован НД DataModule1 Table1 (рис 6 7). ТБД "Сотрудники" и "Информация о сотрудниках" связаны по индексу, образованному полями FIO

Требуется при просмотре в ТБД "Сотрудники" выводить год рождения данного сотрудника ниже компонента TDBGrid, в DBTextl

Для этой цели для Tablel, связанной с НД "Сотрудники", входим в редактор почеи и создаем новое поле, сразу же установив радио-группу Field Type в значение Lookup (рис 6 8)

Затем устанавливаем значения свойств

DataSet НД DataModule Table1, который связан с ТБД "Информация о сотрудниках"),

Key Fields поле FIO НД Tablel (ТБД "Сотрудники"), которое отображается в TDBGrid),

Lookup Fields поле FIO НД DataModulel Table (ТБД "Информация о сотрудниках"),

Result Field поле GodRojd НД DataModulel Tablel (ТБД "Информация о сотрудниках")

Таким образом, нами определен новый компонент Table 1GR типа TField (а точнее, TStringField), источником данных для которого служит поле GodRojd ТБД "Информация о сотрудниках", из той ее записи, у которой значение поля FIO совпадает со значением поля FIO соответствующей записи ТБД "Сотрудники"

Далее размещаем в форме компоненты Label 1 и DBTextl (связанный с полем Table1GR) Тогда для текущей записи сотрудника в DBGndl в DBText1 отображается год рождения для данного сотрудника из ТБД "Информация о сотрудниках"(рис 6.9)

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

Поля выбора данных могут использоваться для автоматического занесения информации в данную ТБД из другой ТБД. Часто это очень удобно. Рассмотрим пример, для чего несколько модифицируем показанные выше ТБД.

Допустим имеется ТБД "Сотрудники" состоящая из полей: уникальное TabNum (табельный номер), FIO (ФИО), KodDol (код должности), и ТБД "Оклады", состоящая из полей уникальное KodDol (код должности), ОоЦпо$1(должность), Oklad (оклад). ТБД "Сотрудники" и "Оклады" состоят в связи "многие-к-одному" или, если смотреть со стороны ТБД "Оклады", "один-ко-многим". Полем связи является Doljnost.

Как видно, в ТБД "Сотрудники" может быть несколько записей с одним и тем же значением поля KodDol (например, 144), в то время как в ТБД "Оклады" конкретный код должности может встречаться только единожды.

Присвоение кодов каким-либо атрибутам таблиц БД является весьма распространенным приемом. Если по этим атрибутам для нескольких ТБД имеют место реляционные отношения, для хранения индексов по кодам (цифровым полям) и их использования для доступа к данным требуется много меньше дискового пространства и времени, нежели для хранения индексов по оригинальным значениям. В нашем примере это обосновано: лучше строить индекс по коду (слово), нежели по символьному значению поля Doljnost (рис. 6.10). Это особенно актуально, если символьное поле имеет большую длину (например, 200 символов). Индексы по таким полям получаются очень большими.

Другой выгодой от использования кодов является то, что в справочнике (lookup-ТБД) "Оклады" коды должности KodDol представляют собой автоинкрементное поле, т.е. поле, уникальное значение которого BDE устанавливает автоматически. В дальнейшем его менять нельзя. Это снимает необходимость каскадного изменения в дочерней ТБД "Сотрудники" при изменении значения поля связи (KodDol) в родительской ТБД "Оклады". ЗАМЕЧАНИЕ. Автоинкрементные поля более свойственны локальным СУБД. Для удаленных (серверных) СУБД автоинкрементные поля заменяются другими механизмами, например, генераторами (InterBase). Если бы связь между данными ТБД была установлена по полю Doljnost, a не KodDol, то при изменении значения должности с "приват-доцент" на "доцент" в ТБД "Оклады" на значение "доцент" должны были бы измениться значения всех записей в ТБД "Сотрудники", у которых поле Doljnost содержит значение "приват-доцент" (рис. 6.11, 6.12).

Однако поскольку мы используем для связи между названными таблицами код, в ТБД "Оклады" значение поля Doljnost можно менять сколь угодно много раз - на связь между ТБД это не окажет никакого влияния. Заметим, что по полю Doljnost в ТБД "Оклады" должен быть построен уникальный индекс, чтобы предотвратить возможность ввода двух одинаковых должностей с разными окладами. В данном примере кодом будет являться поле KodDol, a семантически значимым полем поле Doljnost. Более подробно с данным вопросом можно ознакомиться в разделе "Обеспечение ссылочной целостности"

Поставим задачу. Пусть при вводе данных в ТБД "Сотрудники" нам известна должность конкретного сотрудника, но кода ее, мы, разумеется, не помним. Поэтому нужно:

• обеспечить просмотр и выбор интересующей должности из справочника (lookup-ТБД) "Оклады";

• обеспечить занесение кода этой должности из поля KodDol ТБД "Оклады" в поле KodDol ТБД "Сотрудники".

В форме НД SotrTable соответствует ТБД "Сотрудники", а НД OkladyTable соответствует ТБД "Oklady".

Добавим в набор данных SotrTable поле выбора данных Lookupchik (рис. 6.13)

Значения параметров поля выбора, показанные на рис. 6.13, можно читать так "Исходя из реляционной связи по полю KodDol со стороны НД SotrTable (свойство Key Fields) и по полю KodDol (свойство LookupKeys) со стороны набора данных-источника значений поля выбора (набора данных OkladyTable, свойство DalaSel), заполнять поле реляционной связи в SotrTable значением, взятым из записи, которая будет выбрана в ниспадающем меню В ниспадающем меню показывать только поле Doljnost (параметр ResultField) НД OkladyTable "

6.10.3. Буфер значений полей выбора данных

Свойство

property LookupCache: Boolean;

определяет, будут ли значения полей выбора данных храниться в кэше (буфере) - значение True -, или нет (значение False).

Свойство

ro property LookupList: TLookupList;

содержит список значений из набора данных-источника для полей выбора данных, индексированных набором значений полей, список которых содержится в свойстве KeyFields. Метод ValueOfKey компонента TLookupList возвращает результирующее поле (значение поля выбора данных)

Value := LookupList.ValueOfKey(DataSet.FieldValues[KeyFields]) ;

Список полей выбора данных формируется после открытия НД или после обновления списка методом компонента Tfield procedure RefreshLookupList;

6.11. Обзор полей TxxxField

• TStringField - хранит строковое значение длиной до 255 символов. Строки большей длины нужно хранить в blob-полях (TMemoField).

Свойство property Transliterate: Boolean; указывает, следует ли производить преобразование символов в ANSI в том случае, если символьные поля в ТБД-источнике находятся не в ANSI-кодировке или содержат расширенные ASCII-символы. Когда свойство установлено в True, для

преобразования ASCII символов в иную кодировку используется функция AnsiToNative и функция NativeToAnsi для перевода в ANSI.

• целочисленные поля - применяются для хранения целых чисел различной длины:

TIntegerField- от -2,147,483,648 до 2,147,483,647

TSmallintField - от -32,768 до 32,767

TWordField - от 0 до 65,535

Свойства property MaxValue: Longint; и property MinValue: Longint; могут определять максимальное и минимальное значение поля.

• числовые поля с плавающей точкой - применяются для хранения целых чисел различной длины:

TFloatField - числа, чьи абсолютные значения - 5.0*10-324 to 1.7*10+308 до 15-16

TCurrencyField - аналогично TFloatField, но в денежном формате

TBCDField - вещественные десятичные числа с фиксированным числом разрядов после точки. До 18 символов. Диапазон представляемых чисел зависит от числа знаков. Применяется только для Paradox.

Свойство property Precision: Integer; позволяет указать число знаков после десятичной точки (по умолчанию 15).

Свойства property MaxValue: Longint; и property MinValue: Longint; могут определять максимальное и минимальное значение поля.

• TBooleanField - содержит значения True или False.

• поля даты и времени:

TDateTimeField - содержит значения даты и времени в формате TDateTime.

TDateField - значения даты в формате TDate

TTimeField - значения времени в формате TTime.

• поля для хранения значений произвольных форматов:

TBIobField - произвольное байтовое поле без ограничения длины.

Метод procedure LoadFromFile(const FileName: string); загружает содержимое поля из файла, метод procedure LoadFromStream(Stream: TStream); - из потока.

Метод procedure SaveToFile(const FileName: string); сохраняет содержимое поля в файле, метод procedure SaveToStream(Stream: TStream); - в потоке.

Свойство property BlobSize: Integer; содержит размер в байтах blob-поля данной записи.

Свойство property Transliterate: Boolean; указывает, следует ли производить преобразование символов в ANSI в том случае, если blob-поля в ТБД-источнике находятся не в ANSI-кодировке или содержат расширенные ASCII-символы. Когда свойство установлено в True, для преобразования ASCII символов в иную кодировку используется функция AnsiToNative и функция NativeToAnsi для перевода в ANSI.

Свойство property BlobType: TBIobType; возвращает тип blob-поля. Возможные значения: ftBlob, ftMemo, ftGraphic, ftFmtMemo, ftParadoxOle, ftDBaseOle, ftTypedBinary.

TBytesField - произвольное байтовое поле без ограничения длины. Не имеет методов LoadFromFile, LoadFromStream, SaveToFile, SaveToStream. Свойство

property DataSize: Word позволяет определить во время выполнения, сколько байт нужно для хранения поля в памяти.

TVarBytesFieId - произвольное байтовое поле длиной до 65,535 байт. Текущая длина может быть получена из первых двух байт поля.

TMemoField - строковое значение неопределенной длины (мемо-поле).

Метод procedure Clear; очищает мемо-поле.

Метод procedure LoadFromFile(const FileName: string); загружает содержимое поля из файла, метод procedure LoadFromStream(Stream: TStream); - из потока.

Метод procedure SaveToFile(const FileName: string); сохраняет содержимое поля в файле, метод procedure SaveToStream(Stream: TStream); - в потоке.

Свойство property BlobSize: Integer; содержит размер в байтах blob-поля данной записи.

Свойство property Transliterate: Boolean; указывает, следует ли производить преобразование символов в ANSI в том случае, если blob-поля в ТБД-источнике находятся не в ANSI-кодировке или содержат расширенные ASCII-символы. Когда свойство установлено в True, для преобразования ASCII символов в иную кодировку используется функция AnsiToNative и функция NativeToAnsi для перевода в ANSI.

Для работы с мемо-полями в БД Delphi предоставляет компонент TDBMemo. Его описание приводится в разделе "Компоненты для работы с текущей записью набора данных ".

TGraphicField - произвольное байтовое поле, трактуемое как графическое изображение.

6.12. Информация о типе поля

Свойство го property DataType: TFieldType;

возвращает информацию о типе данных поля.

Возможные значения:

ftUnknown неизвестный или неопределенный тип

ftString строковое или символьное поле

ftSmallint 16-битное целое

ftlnteger 32-битное целое

ftWord 16-битное беззнаковое

ftBoolean логическое поле

ftFloat числовое с плавающей точкой

ftCurrency поле в денежном формате

ftBCD двоично-десятичное поле

ftDate поле типа даты

ftTime поле типа времени

ftDateTime поле типа даты и времени

ftBytes фиксированное число байт в двоичном представлении

fiVarBytes переменное число байт в двоичном представлении

ftAutoInc автоинкрементное поле (автоматически увеличивающийся счетчик, 32-битное целое)

FtBlob большой двоичный объект

FtMemo текстовое мемо-поле

FtGraphic графическое поле

FtFmtMemo форматированное текстовое мемо-поле

FtParadoxOle поле Paradox OLE

FtDBaseOle поле dBASE OLE

FtTypedBinary типизированное двоичное поле

 

6.13. Информация о виде поля

Вид поля определяется свойством

property FieldKind: TFieldKind;

Возможны следующие значения:

fkData физическое поле в базе данных

fkCalculated вычисляемое поле

fkLookup поле, возвращающее значение (lookup-поле)

fkInternalCalc вычисляемое поле, значение которого можно хранить в наборе данных

ЗАМЕЧАНИЕ. Поле awssiflcInternalCalc есть вычисляемое поле, которое может записываться в набор данных. Однако не следует путать его с просто вычисляемым (fkCalculated) полем. Последнее определяется как вычисляемое в редакторе полей и алгоритм его расчета задается в обработчике события набора данных OnCalcFields. Просто вычисляемые поля не могут храниться в качестве полей НД.

Поле вида fkInternalCalc может храниться в НД, но оно не определяется как вычисляемое в редакторе полей, а вычисляется SQL-сервером или BDE и содержится в "живом" (то есть доступном для изменения) наборе данных, возвращаемом как результат выполнения SQL-запроса.

6.14. Имя поля в SQL-запросах

Пусть после выполнения запроса

SELECT TOVAR AS Т, ZENA AS Z FROM TOVARY WHERE ZENA > 100

получим набор данных, состоящий из полей Т и Z. Чтобы определить для такого поля, какое физическое поле в таблице послужило источником его формирования, используют свойство property Origin: string;

Однако, значение свойства Origin доступно в среде редактора полей и только для тех полей, для которых явно создан компонент TField в редакторе полей.

6.15. Проверка применимости символа в поле

Свойство function IsValidChar(InputChar: Char): Boolean; virtual;

возвращает True, если символ InputChar может быть записан в поле того или иного вида:

Тип поля

Верные символы

FtBoolean

все

FtSmallInt

числа 0 ..9, плюс (+), минус (-).

FtWord

числа 0 ..9, плюс (+), минус (-)

FtAutoInc

числа 0 ..9, плюс (+), минус (-)

FtDate

все

Ftlnteger

числа 0 ..9, плюс (+), минус (-)

FtTime

все

FtCurrency

числа 0 ..9, плюс (+), минус (-), буква Е или е и разделитель дробной и целой части (определяется текущими установками Windows на конкретном компьютере)

FtDateTime

все

ftFloat

числа 0 ..9, плюс (+), минус (-), буква Е или е и разделитель дробной и целой части (определяется текущими установками Windows на конкретном компьютере)

ftBCD

числа 0 ..9, плюс (+), минус (-), разделитель дробной и целой части (определяется текущими установками Windows на конкретном компьютере)

ftString

все

ftVarBytes

все

ftBytes

все

ftBlob

все

ftDBaseOle

все

ftFmtMemo

все

ftGraphic

все

ftMemo

все

ftParadoxOle

все

ftTypedBinary

все

ftUnknown

все