Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

мет_BD Delphi

.pdf
Скачиваний:
18
Добавлен:
26.02.2016
Размер:
702.49 Кб
Скачать

begin {свойство Value позволяет обратиться к значению поля}

ShowMessage ('Количество не может быть отрицательным!');

Abort;

end;

3Запустить приложение и попробовать изменить значение поля «Kolvo» одной из записей на отрицательное.

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

Использование события OnSetText позволяет игнорировать неверные значения и не создавать исключительную ситуацию. В обработчике этого события программа должна присвоить полю новое значение или оставить поле без изменения.

4 В окне кода приложения в разделе TYPE удалите имя процедуры procedure TForm1.ADOTable2KolvoValidate (Sender: TField).

5В окне кода приложения в разделе IMPLEMENTATION удалить созданный ранее обработчик события OnValidate.

6Для компонента ADOTable2 открыть редактор полей и в списке полей выделить поле «Kolvo».

7В инспекторе объектов на странице «Events» удалить имя обработчика для со-

бытия OnValidate.

8Создать обработчик события OnSetText, дважды щелкнув в поле строки «OnSetText» на странице «Events» инспектора объектов и набрав код обработчика:

if StrToInt(Text) < 0 then

ShowMessage (‘Количество не может быть отрицательным!’) else ADOTable2Kolvo.Value := StrToInt(Text);

9Сохранить изменения, запустить приложение и попробовать изменить значение поля «Kolvo» одной из записей на отрицательное.

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

1.7 Установка активного индекса

Отсортируем записи в наборе данных ADOTable2 по дате прихода товара.

1В инспекторе объектов для ADOTable2 в свойстве IndexFieldNames ввести зна-

чение Tovar; DataPrih.

2Сохранить внесенные изменения и запустить приложение на выполнение.

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

Как видно, набор данных ADOTable2, ассоциированный с таблицей «Prihod», в приложении отсортирован по наименованию товара, а внутри каждой группы товара − по дате прихода.

3 Аналогичным образом отсортировать записи в наборе данных ADOTable2 по товару и по количеству товара.

11

1.8 Реализация связи между наборами данных

Таблицы базы данных «Tovary» и «Prihod» находятся в отношении «один-ко- многим». Можно сделать так, чтобы при установке указателя на запись в наборе данных ADOTable1, ассоциированном с таблицей «Tovary», в наборе данных ADOTable2, ассоциированном с таблицей с «Prihod», показывались только записи прихода товара, выделенного в ADOTable1. Это реализуется через механизм связи

«Master-Detail» наборов данных.

1Сохранить форму приложения как «app4.pas», а проект − как «proba4.dpr».

2В редакторе столбцов DBGrid2 при необходимости сделать столбец, соответствующий полю «Tovar», первым по счету в DBGrid2.

3В инспекторе объектов для компонента ADOTable2 установить значение свой-

ства MasterSource в «DataSource1».

4Переместиться на значение свойства MasterFields и нажмите кнопку .

5В появившемся окне «Field Link Designer» установить параметры связи:

в списке «Detail Fields» выбрать поле «Tovar»;

в списке «Master Fields» выбрать поле «Tovar» и нажать кнопку Add. В поле «Joined Fields» будет сформировано выражение «Tovar -> Tovar» (рисунок

14).

нажать кнопку OK.

6Выполнить приложение.

Рисунок 14 – Установление связи между таблицами

Теперь в наборе данных ADOTable2 показываются только записи по приходу товара, текущего в наборе данных ADOTable1. Мало того, при добавлении записи в набор данных ADOTable2 значение поля «Tovar» по умолчанию берется равным значению поля «Tovar» из текущей записи в наборе данных ADOTable1.

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

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

12

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

Создадим в таблице «Приход» поле для вычисления стоимости товаров.

1У компонента ADOTable2 установить свойство Active в значение False.

2Щелкнуть правой кнопкой мыши по компоненту ADOTable2 и выбрать команду

Fields Editor.

3В окне редактора полей нажать правую кнопку мыши и во всплывающем меню выбрать команду New Field.

4В появившемся окне ввести в строку «Name» название поля «Summa», в списке

«Туре» выбрать денежный тип (Currency), выбрать переключатель Calculated (рисунок 15) и закрыть окно щелчком на кнопке ОК.

Рисунок 15 – Создание вычисляемого поля «Summa»

5Закрыть редактор полей.

6У компонента ADOTable2 установить свойство Active в значение True.

7Открыть редактор столбцов компонента DBGrid2, щелкнув правой кнопкой мыши на компоненте и выбрав команду Columns Editor.

8В редакторе столбцов щелкнуть правой кнопкой мыши и выбрать команду Add. Появится компонент TColumn – это новый безымянный столбец (рисунок 16).

Рисунок 16 – Создание нового столбца

9Для связи нового столбца с созданным ранее полем «Summa» выделить компонент TColumn и установить для него свойства: FieldName − Summa (выбрать из списка), Title.Caption − Сумма. Затем закрыть редактор столбцов.

10Для выполнения вычислений для компонента ADOTable2 создать обработчик события OnCalcFields (двойной щелчок по полю строки «OnCalcFields» на странице «Events» окна инспектора объектов):

procedure TForm1.ADOTable2CalcFields(DataSet: TDataSet);

13

begin

ADOTable2Summa.Value := ADOTable1Zena_ed.AsFloat * ADOTable2Kolvo.AsInteger;

end;

Для обращения к полю «Summa» использовано свойство Value. Свойство AsInteger приводит значения полей «Zena_ed» и «Kolvo» к соответствующему типу данных, означенному в названии свойства, в данном случае к целочисленному типу.

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

11У компонента ADOTable2 установить свойство AutoCalcFields в значение True, чтобы событие OnCalcFields наступало также и при модификации значений невычисляемых полей набора данных.

12Сохранить изменения (File\Save all) и запустить приложение. Добавить в таблицу «Приход товара» три новые записи и понаблюдать за работой вычисляемого поля.

ЛАБОРАТОРНАЯ РАБОТА 2 Визуальные компоненты для работы с полями

Большинство визуальных компонентов для работы с данными похожи на соответствующие компоненты для обычных приложений. Основное отличие заключается в том, что компоненты для работы с базами данных содержат свойства, позволяющие указать источник данных (DataSource) и поле, из которого компонент получает данные (DataField).

Большинство компонентов предназначено для отображения текущего значе-

ния одного поля: DBEdit, DBCheckBox, DBRadioGroup, DBText и др. Для вывода и редактирования данных поля Мемо используются компоненты DBMemo и DBRichEdit. Компоненты DBNavigator, DBLookupComboBox и DBLookupListBox

используются для синхронного просмотра данных из связанных таблиц.

2.1 Создание приложения

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

1Создайть новый проект (File\ New\ Application). Сохранить форму приложения как «app5.pas», а проект − как «proba5.dpr».

2Разместить на форме два компонента TADOTable и два компонента TDataSource

изадать для них свойства, указанные в таблице 6.

Таблица 6 − Свойства компонентов

Компонент

Свойства

 

ADOTable1

ConnectionString − Sklad.mdb; TableName – Tovary;

Active − True

DataSource1

DataSet − ADOTable1

 

ADOTable2

ConnectionString − Sklad.mdb; TableName – Prihod;

Active − True

DataSource2

DataSet − ADOTable2

 

14

3Для создания объектов-полей щелкнуть правой кнопкой мыши на компоненте ADOTable1, выбрать команду Fields Editor. В редакторе полей нажать правую кнопку мыши и выбрать команду Add all Fields для добавления всех полей таблицы «Tovary». Закрыть редактор полей.

4Аналогичным образом создать объекты-поля для ADOTable2.

5В качестве поясняющих надписей для визуальных компонентов поместить на форму пять компонентов TLabel (страница Standard) и изменить содержимое свойства Caption на соответствующий текст («Товар», «Единица измерения», «Количество», «Цена», «Дата прихода») (рисунок 17).

Рисунок 17 – Визуальные компоненты для работы с полями

6Для доступа к полю «Tovar» нужен компонент, который позволял бы вводить в

поле «Tovar» таблицы «Prihod» значения поля «Tovar» из таблицы «Tovary» и никакие другие значения. Для этой цели разместить на форме компонент

TDBLookupComboBox (страница Data Controls) с именем по умолчанию DBLookupComboBox1. Установить свойства этого компонента: DataSource

DataSource2; DataField – Tovar; ListSource − DataSource1; ListField – Tovar; KeyField – Tovar.

7Добавить в форму четыре компонента TDBEdit (страница DataControls). Установить для компонентов свойства, указанные в таблице 7.

Таблица 7 − Свойства компонентов TDBEdit

Компонент

Свойства

DBEdit1

DataSource − DataSource1; DataField − Ed_Izm; ReadOnly − True

DBEdit2

DataSource − DataSource2; DataField − Kolvo

DBEdit3

DataSource − DataSource1; DataField − Zena_Ed

DBEdit4

DataSource − DataSource2; DataField − DataPrih

8 Добавить в приложение компонент TDBNavigator (страница Data Controls) и связать его с таблицей «Prihod», установив свойство DataSource в DataSource2.

9 Т.к. TDBNavigator будет использоваться только для просмотра записей базы данных, нужно убрать с компонента часть кнопок. Для этого открыть список элементов свойства VisibleButtons и оставить значение True только у элементов nbFirst, nbPrior, nbNext и nbLast (для остальных элементов – False).

10 Добавить в приложение пять компонентов-кнопок TButton (страница Standard). 11 Изменить имена кнопок TButton (свойство Name) соответственно на

15

«InsertButton», «EditButton», «DeleteButton», «PostButton», «CancelButton».

12Изменить заголовки кнопок (свойство Caption) соответственно на «Добавить», «Изменить», «Удалить», «Запомнить», «Отменить» (рисунок 17).

13Для создания обработчика нажатия кнопки InsertButton два раза щелкнуть по ней мышью и ввести следующий код:

IF ADOTable2.State = dsBrowse THEN ADOTable2.Insert;

14Определить обработчик нажатия кнопки EditButton со следующим кодом:

IF ADOTable2.State = dsBrowse THEN ADOTable2.Edit;

15Определить обработчик нажатия кнопки DeleteButton со следующим кодом:

IF ADOTable2.State = dsBrowse THEN

IF MessageDlg ('Подтвердите удаление записи', mtConfirmation,[mbYes, mbNo],0) = mrYes THEN

ADOTable2.Delete;

16Определить обработчик нажатия кнопки PostButton со следующим кодом:

IF ADOTable2.State in [dsInsert, dsEdit] THEN ADOTable2.Post;

17Определить обработчик нажатия кнопки CancelButton со следующим кодом:

IF ADOTable2.State in [dsInsert, dsEdit] THEN ADOTable2.Cancel;

18Добавить в приложение еще один компонент TButton, установив значения свойств Name в «CloseButton», Caption в «Закрыть приложение».

19Определить обработчик нажатия кнопки CloseButton с кодом: Close;

20Запустить приложение на выполнение.

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

2.2 Самостоятельная работа 1

Для ввода и редактирования даты прихода товара вместо TDBEdit можно использовать компонент TDateTimePicker (страница Win32), определив для него обработчик события OnChange со следующим кодом:

ADOTable2DataPrih.Value:=DateTimePicker1.Date;

1Изменить проект так, чтобы в режимах добавления и изменения данных для работы с полем «Дата прихода» использовался компонент TDateTimePicker, а в остальных случаях использовался компонент TDBEdit.

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

ЛАБОРАТОРНАЯ РАБОТА 3 Фильтрация записей

Фильтрация данных позволяет отобразить только те записи набора данных, которые удовлетворяют условиям фильтра, остальные записи становятся скрытыми. Возможны два варианта определения условий фильтрации:

строковое значение в свойстве Filter;

условие фильтрации, описанное в обработчике события OnFilterRecord. Набор данных будет отфильтрован, как только его свойство Filtered станет

равным True.

16

При создании текста фильтра для свойства Filter используются имена полей соответствующей таблицы базы данных и литералы (явно заданные значения), а для задания отношений применяются все операторы сравнения (>, >=, <, <=, =, <>) и логические операторы AND, OR, NOT.

Примеры условий фильтрации:

Field1>100 AND Field2=20 ([Doljnost]='доцент') AND ([TabNum]>300000)

Замечание. Сравнивать между собой два поля нельзя.

3.1 Создание приложения

Требуется разработать приложение, позволяющее просматривать информацию только по определенному наименованию товара или по определенной дате прихода товара.

Создайте согласно рисунку 18 заготовку проекта для изучения способов фильтрации записей в наборе данных.

Рисунок 18 – Вид формы для проекта Proba_Filter.dpr

1Создать новый проект (File\ New\ Application). Сохранить форму приложения как «unit_filter.pas», а проект − как «proect_filter.dpr».

2Разместить на форме компонент ADOTable и компонент TDataSource и задать для них свойства согласно таблицы 8.

Таблица 8 − Свойства компонентов TADOTable и TDataSource

Компонент

Свойства

ADOTable1

ConnectionString − Sklad.mdb; TableName – Prihod; Active – True

DataSource1

DataSet − ADOTable1

3 Разместить на форме компонент TDBGrid и установить для него свойство

DataSource в значение DataSource1.

4Разместить на форме два компонента TLabel, в свойстве Caption задав соответствующие пояснительные надписи согласно рисунку 18.

5Рядом с пояснительными надписями разместить компоненты TDateTimePicker и TEdit.

6Поместить на форму компонент TRadioGroup. В его свойстве Items ввести стро-

17

ки «по дате прихода товара» и «по наименованию товара», а в свойстве Caption ввести «Фильтровать».

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

Caption: для Button1 – «Filter», для Button2 – «OnFilterRecord», для Button3 – «Отменить фильтрацию», для Button4 – « Закрыть приложение».

8Создать обработчик нажатия кнопки «Закрыть приложение» с кодом: Close;

9Создать обработчик нажатия кнопки «Отменить фильтрацию»:

ADOTable1.Filtered := False;

10Создать обработчик нажатия кнопки «Filter», содержащий следующий код: case RadioGroup1.ItemIndex of

0:ADOTable1.Filter := 'DataPrih=' +

DateToStr (DateTimePicker1.Date);

1: ADOTable1.Filter := 'Tovar=' + char(39) + Edit1.Text + char(39);

end;

 

ADOTable1.Filtered := True;

//включаем фильтрацию

Замечание. Для вставки в условие фильтрации символов «», ограничивающих строковое значение для поля «Товар», используется функция Char, возвращающая символ по его коду.

11 Сохранить внесенные изменения, запустить приложение на выполнение.

Рассмотрим фильтрацию с помощью события OnFilterRecord.

Обработчик события OnFilterRecord имеет два параметра: имя фильтруемого набора данных DataSet и Accept, указывающий условия фильтрации записей в наборе данных. Программный код метода должен присваивать параметру Accept истинное или ложное значение. В отфильтрованный набор данных включаются только те записи, для которых параметр Accept имеет значение True.

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

12 Для компонента ADOTable1 написать обработчик события OnFilterRecord: procedure TForm1.ADOTable1FilterRecord (DataSet: TDataSet;

var Accept: Boolean);

begin //проверяем, фильтр по каким данным выбран: case RadioGroup1.ItemIndex of

//если выбран фильтр по дате:

0:Accept := ADOTable1DataPrih.AsString = DateToStr(DateTimePicker1.Date);

//если выбран фильтр по названию товара, то условие задается в Edit1:

1:Accept := ADOTable1Tovar.AsString = Edit1.Text;

end;

end;

13 Написать обработчик нажатия кнопки «OnFilterRecord» с кодом:

//включаем фильтрацию по выбранному параметру:

ADOTable1.Filtered := True;

//вызываем событие OnFilterRecord:

ADOTable1.OnFilterRecord (ADOTable1,Accept);

14В разделе декларации после служебного слова VAR добавить описание глобальной переменной: Accept: Boolean;

15Сохранить внесенные изменения, запустить приложение на выполнение.

18

3.2 САМОСТОЯТЕЛЬНАЯ РАБОТА 2

Доработать проект следующим образом:

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

TRadioGroup;

если в компонент TEdit не введено условие фильтрации или не выбран параметр фильтра в компоненте TRadioGroup, должны выводиться соответствующие сообщения.

3.3Навигация в неотфильтрованном наборе данных между записями, удовлетворяющими фильтру

Внеотфильтрованном в данный момент наборе данных можно обеспечить навигацию только между теми записями, которые удовлетворяют условию фильтрации. Для этой цели используются методы FindFirst, FindLast. FindNext, FindPrior. Действие данных методов таково: они кратковременно переводят набор данных в отфильтрованное состояние (Filtered=True) без визуализации этой фильтрации в TDBGrid или другом визуальном компоненте, находят соответствующую запись и переводят набор данных в неотфильтрованное состояние (Filtered=False). В случае если искомая запись найдена, данные методы возвращают True, в противном случае – False. Условие фильтрации задается событием

OnFilterRecord или (и) свойством Filter.

Функция FindFirst переводит указатель на первую запись, удовлетворяющую фильтру. Функция FindLast переводит указатель на последнюю запись, удовлетворяющую фильтру. Функция FindNext переводит указатель на следующую запись, удовлетворяющую фильтру. Функция FindPrior переходит на предыдущую запись, удовлетворяющую фильтру. Свойство Found возвращает True, если последнее обращение к одному из предыдущих методов привело к нахождению нужной записи.

Вкачестве примера рассмотрим предоставление пользователю возможности перемещаться на первую, последнюю, следующую, предыдущую запись, содержащую фамилию сотрудника, часть которой введена в компонент Edit1. Заметим, что свойство Filtered компонента ADOTable1 должно быть равно False, т.е. хотя в обработчике события ADOTable1.OnFilterRecord и указано условие фильтрации, набор данных остается в неотфильтрованном состоянии и в нем показываются все

записи.

//задание условия фильтрации:

procedure TForm1.ADOTable1FilterRecord (DataSet: TDataSet; var Accept: Boolean);

begin

Accept := POS(Edit1.Text, DataSet['FIO'])> 0;

end;

// обработка нажатия кнопки «Первая»:

procedure TForm1.FindFirstButtonClick (Sender: T0bject); begin

Label1.Caption := '';

If not ADOTable1.FindFirst Then Label1.Caption := 'Нет такой записи';

end;

// обработка нажатия кнопки «Последняя»:

procedure TForm1.FindLastButtonClick (Sender: TObject);

19

begin Label1.Caption:='';

If not ADOTable1.FindLast Then Label1.Caption := 'Нет такой записи';

end;

// обработка нажатия кнопки «Следующая»:

procedure TForm1.FindNextButtonClick (Sender: TObject); begin

Label1.Caption := '';

If not ADOTable1.FindNext Then Label1.Caption := 'Нет такой записи';

end;

// обработка нажатия кнопки «Предыдущая»:

procedure TForm1.FindPriorButtonClick (Sender: TObject); begin

Label1.Caption := '';

If not ADOTable1.FindPrior Then Label1.Caption := 'Нет такой записи';

end;

3.4 САМОСТОЯТЕЛЬНАЯ РАБОТА 3

Создать проект, позволяющий перемещаться по неотфильтрованным записям таблицы «Приход товара», удовлетворяющим заданному условию фильтрации. Вид формы приложения представлен на рисунке 19.

Рисунок 19 – Примерный вид формы для проекта Proba_find.dpr

Условие фильтрации задается свойством Filter при выборе параметра фильтра

(событие OnClick компонента TRadioGroup).

20