1 Лекция #5. Основные свойства компонента Table и

advertisement
Лекция #5.
Основные свойства компонента Table и простейшие приложения на его основе.
Автор: Пучкова Д.М.
План:
1.
2.
3.
4.
5.
6.
Установка связей между компонентами и БД, навигация по таблице.
Свойства полей.
Перенос полей на форму из редактора полей.
Ограничения вводимых значений.
Вычисляемые поля.
Фильтрация данных.
П.1. Установка связей между компонентами и БД, навигация по таблице.
Построим простое приложение, работающее с БД. Будем использовать таблицу Paradox T1,
которую ранее создали в базе данных с псевдонимом dbP.
В качестве набора данных будем использовать компонент Table. Откроем новое приложение
и перенесем на форму компонент «Table» со страницы «Data Access». Также разместим на
форме компонент «DataSource», который будет являться источником данных. Оба
компонента – невизуальные. В качестве компонента визуализации данных можно
использовать компонент DBGrid со страницы «Data Control». Это визуальный компонент,
поэтому его необходимо растянуть или в свойстве «Align» установить «alClient».
Теперь установим цепочку связей между этими компонентами, описанную ранее в Лекции
#4. Главное свойство DBGrid и других компонентов визуализации и управления данными –
DataSource. Выделим на форме компонент DBGrid1 и щелкнем на его свойстве «DataSource»
в Инспекторе Объектов. Увидем выпадающий список, в котором перечислены все
имеющиеся на форме источники данных. В нашем случае имеется только один источник
данных – DataSource1. Установить его в качестве значения DataSource. Далее установить
связь между источником данных и набором данных. Выделить компонент DataSource1 и
найти в Object Inspector его главное свойство: DataSet. Щелкнуть на этом свойстве и выбрать
Table1.
Осталось связать компонент Table1 с необходимой таблицей БД. Для этого служат два
свойства компонента Table: DataBaseName и TableName. Сначала установить DataBaseName.
В списке свойства можно увидеть все доступные BDE псевдонимы БД. Выбрать dbP. Если
его там нет, значит он не создан.
После этого можно установить значение свойства TableName. Выбрать таблицу T1 (ранее
созданную).
Соединение с БД осуществляется свойством Active. По умолчанию оно FALSE. Установим
его в TRUE. Если все выполнено верно, то в поле компонента DBGrid1 можно просмотреть
данные из таблицы T1.
Сохранить приложение, запустить его и убедиться, что с ним можно работать (изменять
данные, просматривать) (Лабораторная работа #1).
Отметим, что заранее выставлять для таблиц Active=TRUE допустимо только в процессе
настройки и отладки приложения, работающего с локальными БД.
1
*
В законченном приложении во всех таблицах сначала установлено Active=FALSE.
При событии формы OnCreate эти свойства могут быть TRUE, а при OnDestroy – FALSE. Это
исключает неоправданное поддержание связи с БД, которое занимает ресурсы, а при работе в
сети мешает доступу к БД других пользователей.
Разрешить пользователю просто так хранить редактируемые данные в таблице в
большинстве случаев недопустимо, т.к. могут возникнуть ошибки ввода данных.
Предотвратить редактирование данных можно следующим образом: установить свойство
Read Only компонента DBGrid1 в TRUE. Либо: установить в свойстве Options подсвойство
dgEditing в FALSE.
Ещё одно свойство компонента Table – Exclusive. Это свойство определяет доступ к
использованной таблице при одновременном обращении к ней нескольких приложений
(например, при работе в сети или в многозадачном режиме). Если ExclusiveTRUE, то
таблица будет закрыта для других приложений. Свойство можно изменять только при
Active=FALSE.
В спроектированном приложении можно добавить ещё один компонент, управляющий
работой с таблицей – навигатор DBNavigator, расположенный на странице Data Control
библиотеки компонентов. Изменить свойство Align компонента DBGrid1 на alBottom,
сдвинуть верхний край этого компонента немного вниз и на верх формы поместить
компонент DBNavigator. Это украсит таблицу и добавит к ней «пульт управления».
Компонент имеет ряд кнопок для управления данными. Перечислим их названия и
назначения, начиная с левой кнопки:
nbFirst – перемещение к первой записи;
nbSecond – перемещение к предыдущей записи;
nbNext – перемещение к следующей записи;
nbLast – перемещение к следующей записи;
nbInsert – вставить новую запись перед текущей;
nbDelete – удалить текущую запись;
nbEdit – редактировать текущую запись;
nbPost – послать отредактированную информацию;
nbCancel – отменить результат редактирования или добавления новой записи;
nbRefresh – очистить буфер, связанный с набором данных.
Пользуясь свойством клавиатуры VisibleButtons, можно убрать все ненужные в приложении
кнопки. Например, для запрета редактирования можно установить в FALSE кнопку nbInsert.
Чтобы приложение с навигатором работало, необходимо установить его основное свойство –
DataSource.
Ещё одно свойство навигатора – Hints. Это список строк типа TStrings, содержащий тексты
всплывающих ярлыков кнопок навигатора. По умолчанию эти тексты на английском языке.
Если щелкнуть на кнопке с многоточием около слова «Hints» в окне Инспектора Объектов,
то тексты можно перевести на русский. Целесообразно один раз осуществить подобный
перевод и далее сохранить навигатор в виде шаблона, который можно будет использовать в
последнем приложении.
Для грамотной работы приложения добавим в него соединения с БД в момент начала работы
и разрыв соединения в момент окончания работы.
procedure TForm1.TFormCreate(Sender: TObject);
2
begin
Table1.Active:=true;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
Table1.Active:=false;
end;
В компоненте Table1 необходимо установить active=FALSE, чтобы не занимать БД во время
проектирования.
Откомпилировать приложение и посмотреть его во время работы.
П.2. Свойства полей.
Приложение выглядит очень плохо. Во-первых, последовательность записей определяется
полем F1, а хотелось бы, чтобы записи были расположены по алфавиту или по отделам и
алфавиту.
F1 вообще не нужно, его пользователь видеть и не должен. Шапка таблицы должна
содержать русские имена.
Будем исправлять. Начнем с упорядочивания записей. Выделим на форме компонент Table1.
В Object Inspector увидим свойства IndexName и IndexFieldName.
Выпадающий
список индексов
Перечислены предусмотренные в индексах
комбинации. Можно выбрать любую
комбинацию.
если
выбрать
fio(F2,F3,F4), то
по ФИО. depfio –
по отделам, а
внутри отдела –
по ФИО.
Теперь займемся отдельными полями. Для их редактирования существует Редактор Полей.
Вызвать можно, дважды щелкнув на кнопке Table1. Сначала пустой. Щелкнув правой
кнопкой мыши выбрать «add fields». Далее можно добавить нужные нам поля. Эти поля
будут соответствовать колонкам таблицы. Некоторые поля могут быть невидимы. Можно
изменять последовательность полей. Выделите в списке некоторое поле и посмотрите его
свойства в Object Inspector. Каждое поле – это объект, его класс зависит от типа поля:
TStringField, TSamllintField, TBooleanField и т.д. Все эти классы являются производными от
TField – базового класса полей. Таким образом, каждое поле является объектом и обладает
множеством свойств. Рассмотрим основные свойства.
Alignment – выравнивание отображаемого текста внутри колонки таблицы (влево,
вправо, по центру).
DisplayLabel – соответствует заголовку столбца данного поля. Например, для поля F1
«DisplayLabel» может быть «Фамилия» и т.д.
DisplayWidth – определяет ширину колонки (число символов).
EditMask для строк и EditFormat для чисел определяют форматы отображения данных.
DisplayValue – для логических полей. Первым пишется значение, соответствующее
«TRUE». Например: пол (м/ж) м – «TRUE».
3
ReadOnly – если «TRUE», то пользователь не может вводить в это поле данные.
Visible – видимость поля (TRUE/FALSE).
П.3. Перенос полей на форму из Редактора Полей.
У Редактора Полей есть особенность – возможность перетаскивания из него поля на форму
при помощи мыши.
Начнем новое приложение. Поместим на форму компонент Table1 и свяжем его с T1 (dbP).
Сделаем двойной щелчок на Table1, щелкнем правой кнопкой мыши в окне Редактора Полей
и выберем из меню «Add all Fields». Затем установим свойства DisplayLabel, как ранее
делали с каждым полем. Выделим все поля и перетащим их на форму. Установим в «T1»
свойство ActiveTRUE, добавим навигатор. Распределим поля на форме как нам это нужно.
Приложение готово к работе.
На форме появились дополнительные компоненты: DataSource1, в оконном редакторе
DBEdit, отображающий F1…F6. В окнах будут отображаться значения соответствующих
полей текущей записи. Если изменить текст в окне, то это занесется в БД. Поизучайте
создавшиеся поля.
Это – упрощенный вариант создания приложения. Действительно удобное и грамотное
построение приложения можно создать только в результате целенаправленного
проектирования с использованием всех возможностей компонентов Delphi. Однако
упрощенный вариант может позволить просмотреть данные из таблиц.
П.4. Ограничения вводимых значений.
Несколько возможностей ограничения предоставляют свойства полей, которые можно
увидеть, кликнув два раза на Table1 и выделив в Редакторе Полей требуемое поле. Для
числовых полей имеются свойства MinValue и MaxValue, устанавливающие допустимые
пределы вводимых значений. Например, для поля год рождения MinValue=1970 и
MaxValue=1983. При нарушениях этих пределов будет генерироваться исключение
EDataBaseError, которое можно перехватить в приложении.
Другие возможные ограничения – использование свойств CustomConstraint и CustomError
Message. Оно содержит строку текста, который будет показан пользователю в случае, если
он вводит данные, выходящие за диапазон значений.
Ещё одна возможность проверять данные на уровне поля – использовать обработку события
поля OnValidate. Это событие возникает перед записью введенного значения поля в буфер
текущей записи. Тут можно предусмотреть любые проверки, при появлении недопустимых
данных выдать пользовательское сообщение и, например, сгенерировать исключение EAbort
функцией Abort. Если OK, то после события OnValidate возникает другое событие OnChange,
в обработчике которого также ещё не поздно генерировать исключение.
Описанные способы проверки данных относятся к конкретному полю. Имеется также
возможность осуществлять проверку на уровне записи, анализируя ее поля. Для этого
существует свойство Constraints компонента «Table». Щелкнуть мышью на этом свойстве, и
откроется окно, в которое можно заносить в свойство Constraints набор ограничений. Каждое
из них представляет собой самостоятельный объект. Выделив одно из ограничений, можно
увидеть в Object Inspector его свойства. «Custom Constraint» - строка SQL, определяющая
4
допустимые значения. «Error Message» определяет строку
предъявляться пользователю в случае нарушения ограничений.
текста, которая будет
Например, в свойстве «CustomConstraint»:
((F7=true) and (F6>1955)) or ((F7=false) and (F6>1965))
а в свойстве ErrorMessage: “Приглашаем только мужчин > 1955 г.р. и женщин > 1965
г.р.”
Для компенсации проверки данных можно также использовать различные события
компонента Table.
П.5. Вычисляемые поля.
Компонент Table позволяет не только отображать, редактировать и упорядочивать данные,
но и отфильтровать данные по определенным критериям. Фильтрация может задаваться
свойствами Filter, Filtered и FilterOptions компонента Table. Свойство Filtered вкл/выкл
использование фильтра. Сам фильтр записывается в свойство Filter в виде строки,
содержащей определенные ограничения на значения полей. Например, можно задать в
свойстве Filter F2=`Отдел1`, установить Filtered=TRUE и уже в процессе проектирования в
таблице отобразятся только те записи, в которых поле F2 имеет значение «Отдел1». В
условиях сравнения строк можно использовать символ «*», который обозначает «любое
количество символов». Например, фильтр F2=`Отдел*` приведет к отображению всех
записей, где F2 начинается со слова «Отдел».
В нашем примере будут отображены все записи, где F2=`Отдел1` или F2=`Отдел2`. Для этого
выберем в FilterOptions опцию foNoPartialCompare, запрещающей частичные совпадения при
сравнении. Другая опция в свойстве FilterOptions – foCaseSensitive делает сравнение строк
нечувствительным к регистру, в котором записано условие фильтра. При записи условий
можно использовать операции отношения: «=», «>», «>=», «<», «<=», «<>», а также
логические операции «and», «or» и «not». Например:
(F2=`Отдел1`) and (F6=1980)
Использовать в фильтре имена вычисляемых полей нельзя. Свойства, выпадающий фильтр
можно задавать также и программно. Рассмотрим наше приложение. Установить в DBGrid1
свойство Align равным alNone, перенести на форму группу радиокнопок RadioGroup (назвать
RGF), выпадающий список ComboBox (CBDep), два элемента SpinEdit со страницы `Samples`
(назовем SEmin и SEmax), кнопку «Обновить» и разместим компоненты так, как указано на
рис.1.
Компонент CBDep будет позволять выбрать подразделение, по которому проводится
фильтрация. В его свойство Items занести список подразделений в таблице. Компоненты
SEmin и SEmax будут задавать диапазон возраста при фильтрации по этому критерию.
Задать в них разумные значения свойств MaxValue, MinValue и Value. В группе радиокнопок
ввести соответствующие надписи (свойства Items и Caption), задать ItemIndex=0 и
Columns=2. Теперь зададим код модуля, обеспечивающего фильтрацию.
5
Рис.1. Размещение компонентов на форме.
implementation
{$R *.DFM}
var Year,Month,Day: Word;
procedure TForm1.Table1CalcFields(DataSet: TDataSet);
begin
Table1Age.Value:=Year-Table1F6.Value;
end;
procedure TForm1.RGFClick(Sender: TObject);
begin
Table1.IndexName:=`depfio`;
if (RGF.ItemIndex=0) then Table1.Filtered:=false
else
begin
if (RGF.Itemindex=2) then
Table1.Filter:=`dep`+CBDep.Text
else if (RGF.Itmindex=3) then
begin
Table1.Filter:=`(F6<=`+inttostr(Year-SEmin.Value)+`)
and(F6>=`+inttostr(year-SEmax.Value)+`)`;
Table1.IndexName:=`year`;
end
else
begin
Table1.Filter:=`(Dep=`+CBDep.Text+`)` and (F6<=`+inttostr(yearSEmin.Value)+`) and (F6>=`+inttostr(year-SEmax.Value)+`)`;
end;
Table1.Filtered:=true;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Table1.Active:=true;
6
CBDep.Itemindex:=0;
DecodeDate(Date,Year,Month,Day);
end;
procedure TForm1.FormDestroy(Sender:TObject);
begin
Table1.Active:=flase;
end;
end.
Здесь описаны три процесса.
1. Table1CalcFields ранее рассмотренные Day, Year, Month – глобальные.
2. RGFClick – осуществляющие фильтрацию и упорядочение данных. Обращение к этой
процедуре происходит при событии OnClick компонента RGF – группы радиокнопок
и кнопки «Обновить». Эта кнопка введена в приложение, чтобы можно было, не
переключая радиокнопки, обновлять отображение данных после изменения
пользователем имени подразделения или диапазона возраста. Можно также вызвать
эту процедуру при событии OnChange выпадающего списка отделов.
3. FormCreate – существует ещё один способ фильтрации – использовать обработку
события OnFilterRecord. Это событие происходит каждый раз при смене текущей
записи, если свойство Filtered=true. В обработчик события передается (как var)
параметр Accept булева типа. Если проверка полей показывает, что запись
удовлетворяет фильтру, то Accept должно быть присвоено значение FALSE.
Обработчик события OnFilterRecord, обеспечивающий те же функции, что и
процедура RGFClick в приведенном ранее примере, может иметь вид:
Accept:=(RGF.ItemIndex=0) or ((RGF.ItemIndex=2) and
(Table1F2.Value=CBDep.Text)) or ((RGF.ItemIndex=3) and
(Table1F6.Value<=(year-SEmin.Value)) and (Table1F6.Value>=(yearSEmax.Value))) or ((Table1F2.Value>=CBDep.Text) and
(Table1F6.Value<=(year-SEmin.Value)) and (Table1F6.Value>=(yearSEmax.Value)));
Приведенный оператор обеспечивает нужную фильтрацию. Чтобы он работал,
необходимо выполнить ещё два условия. Во-первых, установить в компонент Table1
значение Filtered=TRUE. Кроме того, надо обеспечить, чтобы при смене условий
отображения таблицы проводилась бы новая фильтрация. Иначе события
OnFilterRecord не будут происходить. Поэтому в обработчике RGFClick события
OnClick компонента RGF надо вставить операторы:
Table1.Filtered:=false;
Table1.Filtered:=true;
if (RGB.ItemIndex=3) then Table1.IndexName:=`Year` else
Table1.IndexName:=`depfio`;
На этот обработчик RGFClick надо сослаться и в событии OnClick кнопки
«Обновить».
7
Download