- •1. Наборы данных
- •Var I: integer;
- •1.1. Состояния наборов данных
- •If not CheckBoxl.Checked then Abort;
- •If not CheckBoxl.Checked then begin
- •If CheckBox2.Checked then
- •If CheckBox2.Checked then begin
- •1.2. Режимы наборов данных
- •Var n: integer;
- •1.3. Доступ к полям
- •Var X: integer;
- •Var X: integer;
- •1.4. Особенности набора данных Table
- •If OpenDialogl.Execute then begin
- •Var n: integer;
- •If Editl.CanFocus then Editl.SetFocus;
- •1.5. Особенности набора данных Query
- •Interface
- •Implementation
- •2. Объекты поля
- •2.1 Редактор полей
- •2.2. Операции с полями
- •Var X: integer;
- •Var s: string;
- •X: real;
- •Var s: string;
- •X: real;
- •If not Tablel.Fields[2].IsValidChar(Editl.Text[1]) then
- •If (TablelCode.Required) and (TablelCode.IsNull)
- •3. Источник данных
- •Var n: integer;
- •1. Отображение и редактирование значения логического поля
- •2. Отображение и выбор значения поля
- •3. Отображение и выбор значения поля из списка
- •3.1. Простой и комбинированный списки
- •3.2. Списки, сформированные по значениям поля набора данных
- •4. Представление записей в табличном виде
- •4.1 Характеристики сетки
- •Var r :tRect;
- •4.2. Столбцы сетки
- •Var c, n :integer;
- •4.3. Использование модифицированной сетки
- •5. Использование навигационного интерфейса
- •6. Вывод графических изображений
- •Interface
- •Implementat ion
- •If OpenPictureDialogl.Execute then
- •If SavePictureDialogl.Execute then
- •7. Построение диаграмм
- •Var n: integer;
Var X: integer;
. . .
Label1.Caption:=Table1.FieidByName('Name').AsString;
x:=Tablel.FieldByName('Number').AsInteger;
строковое значение поля Name отображается в надписи Labell, а переменной х присваивается целочисленное значение поля Number. Если же поле Number содержит значение, которое нельзя интерпретировать как целое число, то генерируется исключительная ситуация.
В рассмотренных примерах выполнялось чтение содержимого полей текущей записи. Аналогичным образом можно присваивать произвольному полю текущей записи новое значение, при этом набор данных должен находиться в режимах редактирования или вставки.
Например, с помощью следующих операторов:
Var X: integer;
. . .
// Перевод набора данных в режим редактирования
Table1.Edit;
// Изменение значений полей
Tablel.FieldByName('Name').AsString:=Editl.Text;
Tablel.FieldByName('Number').AsInteger:=x;
// Сохранение изменений
Table1.Post;
выполняется присвоение новых значений полям Name и Number текущей записи после того, как набор данных Table1 переведен в режим редактирования. Произведенные изменения сохраняются, а набор данных переводится в режим просмотра.
1.4. Особенности набора данных Table
Компонент Table представляет собой набор данных, который в текущий момент времени может быть связан только с одной таблицей БД. Этот набор данных формируется на базе навигационного способа доступа к данным, поэтому компонент Table рекомендуется использовать для локальных БД, таких как dBase или Paradox. При работе с удаленными БД следует использовать компонент Query. В дальнейшем при рассмотрении вопросов, связанных с локальными БД, мы обычно будем работать с компонентом Table.
Связь между таблицей и компонентом Table устанавливается через его свойство TableName типа TFileName, которое задает имя таблицы (и имя файла с данными таблицы). При задании свойства TableName указывается имя файла и расширение имени файла.
На этапе разработки приложения имена всех таблиц доступны в раскрывающемся списке Инспектора объектов. В этот список попадают таблицы, файлы которых расположены в каталоге, указанном свойством DatabaseName.
Замечание
При смене имени таблицы на этапе проектирования приложения свойству Active набора данных автоматически устанавливается значение False. При задании имени таблицы программным способом набор данных предварительно необходимо закрыть, установив его свойству Active значение False. В противном случае генерируется исключительная ситуация.
Приведем пример, иллюстрирующий, как задается имя таблицы БД:
procedure TForm1.Button1Click(Sender: TObject);
begin
If OpenDialogl.Execute then begin
Table1.Active:=false;
Table1.TableName: OpenDialog1.FileName;
Table1.Active:=true;
end;
end;
Здесь нажатие кнопки Button1 приводит к появлению диалогового окна выбора имени файла. При выборе файла таблицы его имя устанавливается в качестве значения свойства TableName. Набор данных Table1 предварительно закрывается и снова открывается уже после смены таблицы. Тип таблицы определяется автоматически по расширению имени файла. При наличии ошибок, например, связанных с нарушением структуры таблицы, выдается соответствующее сообщение, а набор данных остается закрытым.
Свойство TableType типа TTtableType определяет тип таблицы. Для локальных таблиц это свойство может принимать следующие значения:
ttDefauit — тип таблицы автоматически определяется по расширению файла;
ttParadox — таблица Paradox; '
ttDBase — таблица dBASE;
ttFoxPro — таблица FoxPro;
ttASCII — текстовый файл, содержащий данные в табличном виде (таблица ASCII).
Если свойство TableType имеет значение ttDefault (по умолчанию), то тип таблицы опреде-ляется по расширению файла:
DB или отсутствует — таблица Paradox;
DBF - таблица dBASE;
TXT — текстовый файл (таблица ASCII).
По умолчанию в состав набора данных Table попадают все записи связанной с ним таблицы. Для отбора записей, удовлетворяющих определенным условиям, используются фильтры.
Delphi через BDE автоматически поддерживает многопользовательский доступ,к локальным таблицам, при этом по умолчанию все пользовательские приложения имеют равные права и могут редактировать содержащиеся в таблицах данные. Чтобы запретить пользователям изменять содержание записей, можно использовать свойство Readonly типа Boolean. По умолчанию оно имеет значение False, что предоставляет пользователю право на модификацию записей.
Если приложению требуется получить к таблице монопольный доступ, то это можно осуществить через свойство Exclusive типа Boolean. По умолчанию свойство имеет значение False, и для таблицы, с которой связан набор данных, действует многопользовательский режим доступа. Если установить свойству Exclusive значение True, то приложение получает монопольный доступ к соответствующей таблице. При этом другим приложениям доступ к таблице запрещается. Перед установкой значения свойству Exclusive набор данных должен быть закрыт, т. е. разорвана его связь с таблицей. Если какое-либо приложение или набор данных этого же приложения уже взаимодействует с таблицей, то попытка установить к ней режим монопольного доступа вызовет исключительную ситуацию.
Монопольный режим доступа необходим при выполнении таких операций, как добавление или удаление индекса методами Addindex и Deleteindex или очистка таблицы методом EmptyTable.
Замечание
Такие приложения, как Delphi и Database Desktop, также могут осуществлять доступ к таблицам. Поэтому перед отладкой приложения, которое устанавливает монопольный доступ к таблице, необходимо проверить, не работают ли с этой таблицей Delphi и/или Database Desktop. В приложении Database Desktop таблицу нужно закрыть, а в среде Delphi достаточно через Инспектор объектов установить значение False свойству Active набора данных, связанного с таблицей.
В наборе данных Table возможно указание текущего индекса, требуемого для выполнения операций:
сортировки записей;
поиска записей;
установки связей между таблицами.
Текущий индекс устанавливается с помощью свойства IndexName или IndexFieldNames типа String. На этапе разработки приложения текущий индекс выбирается из списка индексов, заданных при создании таблицы. Все возможные значения свойств IndexName и IndexFieldNames содержатся в раскрывающихся списках, доступных через Инспектор объектов. Оба свойства во многом схожи, и их использование практически одинаково. Значением свойства indexName является имя индекса, заданное при создании таблицы, а значением свойства IndexFieldNames является имя поля, для которого был создан индекс. Если индекс состоит из нескольких полей, то для свойства IndexName по-прежнему задается имя этого индекса, а для свойства IndexFieldNames через точку с запятой перечисляются имена полей, входящие в этот индекс.
Вот как текущий индекс задается в программе:
Table1.IndexName:='indName';
Table2.IndexFieldNames:='Name';
Здесь компоненты Tablel и Tаblе2 связаны с одной таблицей, для поля Name которой определен индекс indName. Этот индекс устанавливается в качестве текущего для обоих наборов данных.
Для таблиц Paradox сделать текущим индексом ключ (главный индекс) можно только с помощью свойства IndexFieldNames, перечислив ключевые поля таблицы, т. к. ключ не имеет имени и поэтому недоступен через свойство IndexName.
Задать ключ в качестве текущего индекса можно так:
Tablel.IndexFieldNames:='Name;Post;BirthDay';
Для таблицы Paradox, с которой связан компонент Tablel, определен ключ, в который входят поля Name, Post и BirthDay. Этот ключ устанавливается в качестве текущего индекса таблицы.
Замечание
Свойства IndexName и IndexFieldNames взаимозависимы. При установке значения одного из них другое автоматически очищается.
Индекс, устанавливаемый текущим, должен существовать. Если индекс, задаваемый как значение свойства IndexName или IndexFieldNames, для таблицы не существует, то возникает исключительная ситуация.
При смене таблицы, с которой ассоциирован компонент Table, значения свойств IndexName и IndexFieldNames не изменяются автоматически, поэтому программист должен самостоятельно установить нужные значения.
Получить доступ к полям в составе текущего индекса можно с помощью свойств IndexFieldCount и IndexFields.
Свойство IndexFieldCount типа integer содержит число полей в текущем индексе и доступно для чтения при выполнении приложения.
Свойство IndexFields [Index: Integer] типа TField позволяет обращаться к полям текущего индекса, при этом переменная index задает номер индекса в массиве полей этого индекса (отсчет начинается с нуля). Класс TField представляет собой поле набора данных и имеет большое число свойств и методов.
Чаще всего индексы определяются при создании таблицы и в дальнейшем при работе с таблицей не изменяются. Однако программист имеет возможность изменять определенные для таблицы индексы динамически, т. е. в процессе выполнения приложения, с помощью методов Addlndex и Deletelndex.
Замечание
Изменять индексы допускается для таблицы, открытой в режиме монопольного доступа, когда свойство Exclusive имеет значение True.
Процедура Addlndex (const Name, Fields: String; Options: TIndexOptions) добавляет к таблице индекс, имя которого задано параметром Name. Входящие в состав индекса поля указываются в параметре Fields; если индекс состоит из нескольких полей, то они разделяются точкой с запятой. Указывать можно только поля, которые входят в структуру таблицы, в противном случае генерируется исключительная ситуация, а индекс не создается. Параметр options содержит параметры индекса. Он имеет множественный тип и может принимать комбинации следующих значений:
ixPrimary — первичный индекс;
ixUnique — уникальный индекс, для которого не допускается повторение значений полей в его составе;
ixDescending — индекс определяет сортировку в порядке убывания значений, по умолчанию строится индекс, определяющий сортировку по возрастанию;
ixExpression — индекс создается на основе выражения (только для таблиц dBase);
ixCaseInsensitive — индекс определяет сортировку независимо от регистра букв;
ixNonMaintained — индекс автоматически не модифицируется, если таблица открыта.
Приведем пример, демонстрирующий добавление индекса к таблице:
procedure TForml.Button3Click(Sender: TObject);
begin
// Перевод таблицы в режим монопольного доступа
Tablel.Close;
Tablel.Exclusive:=true;
Tablel.Open;
// Добавление индекса
Tablel.Addlndex('indPosition', 'Position', [ixDescending, ixCaselnsensitive]);
// Закрытие режима монопольного доступа к таблице
Tablel.Close;
Tablel.Exclusive:=false;
Tablel.Open;
end;
Здесь к таблице, с которой связан набор данных Tablel, добавляется индекс indPosition, построенный по полю Position. Для нового индекса определяется порядок сортировки по убыванию значений и независимо от регистра букв.
Процедура DeleteIndex (const Name: String) удаляет из таблицы индекс, имя которого задано параметром Name. При попытке удаления несуществующего индекса генерируется исключитель-ная ситуация.
В программе удаление индекса из таблицы может быть реализовано так:
Tablel.Deletelndex('indPosition') ;
Перед удалением индекса таблица должна быть переведена в режим монопольного доступа аналогично тому, как это происходило при добавлении индекса.
Для доступа к информации обо всех индексах, определенных для таблицы и, соответст-венно, для связанного с ней набора данных, можно использовать свойство indexDefs типа TindexDefs. Это свойство доступно как на этапе разработки, так и на этапе выполнения приложения. Класс TindexDefs в свою очередь также имеет полезные свойства и методы, которые мы сейчас и рассмотрим.
Перед работой с индексами всегда рекомендуется вызывать метод UpDate, который производит обновление информации об индексах так, чтобы значение свойства IndexDefs отражало реальное состояние с учетом сделанных изменений.
i
Свойство Items [Index: Integer] типа TindexDef представляет собой список, содержащий информацию обо всех индексах таблицы. Переменная Index указывает номер индекса в списке, отсчет начинается с нуля. Тип TindexDef (не путать с классом TindexDefs) является классом и, в свою очередь, также имеет свойства, основными из которых являются Name, Fields и Options.
Замечание
При доступе к информации об индексах можно опускать название свойства items. Например, для чтения в редактор Editl списка полей, составляющих второй индекс, можно использовать следующие эквивалентные по действию операторы:
Editl.Text:=Tablel.IndexDefs[1].Fields;
или
Edit1.Text:=Tablel.IndexDefs.Items[1].Fields;
Свойство Name типа String содержит имя индекса. Для индексов, построенных на основе выражений (таблицы dBase), и для главного индекса таблиц Paradox вместо названия возвращается пустая строка.
Свойство Fields типа String содержит названия полей, по которым построен индекс. Если в индексе используется несколько полей, то их названия разделяются точкой с запятой.
Свойство Options типа TIndexOption содержит параметры индекса, заданные при его создании.
Рассмотрим работу со списком индексов и индексных полей на конкретном примере.
На форме расположены следующие компоненты: сетка DBGrid, в которой отображаются записи таблицы БД, два списка ListBox с соответствующими надписями, а также две кнопки Button. При нажатии кнопки Button1 с названием Индексы в список ListBoxl загружается список индексов, определенных для набора данных Table1, а в список ListBox2 — список полей, образующих эти индексы (рис. 7.2). Так как компонент Tablel связан с таблицей Paradox, то название главного индекса, построенного по полю pcode, содержит пустую строку.
Обработчик события нажатия кнопки Button1 выглядит так:
procedure TForml.ButtonlClick(Sender: TObject);
