42326

Технология создания простейшей информационной системы (часть 2)

Лабораторная работа

Информатика, кибернетика и программирование

Например в компоненте DBGrid подчинённой таблицы отображается содержимое только тех строк подчинённой таблицы в которых содержимое поля внешнего ключа подчинённой таблицы ссылается на содержимое поля первичного ключа той строки главной таблицы на которую указывает курсор главной таблицы содержимое других строк подчинённой таблицы остаётся невидимым для пользователя. Для отказа от этого механизма визуализации в окне инспектора объектов компонента набор данных подчинённой таблицы в нашем случае это компонент Tble2 таблица – Prihod...

Русский

2013-10-29

1.12 MB

2 чел.

PAGE  6

      Лабораторная работа № 4 (часть 2)

      «Технология создания простейшей

      информационной системы»

1. Определение визуальных компонентов для работы с полями

 Улучшим интерфейс нашей программы так, чтобы работать с данными в полях записей набора данных Таble2 можно было бы не только в сетке компонента DBGrid2, но и с помощью дополнительных визуальных компонентов (строк редактирования, выпадающих списков, кнопок).

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

        Прежде, чем производить в визуальной среде Delphi какие-либо действия по разработке приложения, работающего с таблицами БД (работать с соответствующими компонентами палитры Delphi, изменять параметры свойств этих компонентов, писать тексты программ-обработчиков событий этих компонентов и т.п.) необходимо перевести все наборы данных, с которыми работает создаваемое приложение в неактивное состояние, то есть разорвать все связи приложения с таблицами БД. Для этого надо выставить для всех наборов данных свойство Active=false. И только после выполнения всех действий по редакции (созданию, доработке) приложения и его интерфейса, непосредственно перед компиляцией и запуском приложения на выполнение (перед нажатием клавиши F9, или выполнением Run/Run) необходимо установить для всех наборов данных свойство Active=true (восстановить связь приложения с таблицами).  

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

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

 Прежде всего, откажемся от стандартного механизма визуализации связи таблиц, который был определён в п.п. 4.3 лабораторной работы №4 часть 1. Этот механизм позволяет работать со связанными таблицами без использования дополнительных компонентов формы. Но он имеет ряд недостатков. Например, в компоненте DBGrid подчинённой таблицы отображается содержимое только тех строк подчинённой таблицы, в которых содержимое поля внешнего ключа подчинённой таблицы ссылается на содержимое поля первичного ключа той строки главной таблицы, на которую указывает курсор главной таблицы (содержимое других строк подчинённой таблицы остаётся невидимым для пользователя).

Для отказа от этого механизма визуализации, в окне инспектора объектов компонента «набор данных» подчинённой таблицы (в нашем случае это компонент Table2, таблица – Prihod) надо очистить содержимое строк ввода свойств MasterSource, MasterFields и IndexName. В результате стандартный механизм визуализации связи таблиц перестанет работать. Но таблицы останутся связанными.

Поместите на форму два компонента TDBEdit (страница Data Controls палитры компонентов): компонент DBEdit1 под столбцом «Дата прихода», а компонент DBEdit2 под столбцом «Количество» (рис. 1).

 DBEdit – это компонент «Окно редактирования, связанное с данными». Он позволяет отображать и редактировать данные полей различных типов: строка, число, булева величина. Если определить свойство этого компонента ReadOnly=true, то он может служить элементом отображения данных. Нам этого делать не надо (то есть должно остаться ReadOnly=false). Связь компонента с конкретным набором данных устанавливается свойством DataSource. Значение свойства DataField компонента определяет имя поля, отображаемого компонентом. В окне компонента будет отображаться значение соответствующего поля текущей записи набора данных. А если во время работы приложения текст в окне компонента будет изменён, то изменённый текст будет занесён в соответствующее поле БД.

 Чтобы связать компоненты DBEdit1 и DBEdit2 с полями  DatPrih  и Kolvo таблицы Prihod,  поместите в их свойства DataSource значение DataSource2 и в свойства DataField соответственно DatPrih и Kolvo.

 Для доступа к данным поля Tovar таблицы Prihod нужен более сложный компонент, который позволял бы вводить в это поле только те значения, которые уже введены в поле Tovar таблицы Tovary, и никакие другие. Для этой цели под столбцом «Товар» компонента DBGrid2 разместите компонент TDBLookupComboBox (рис.1).

                                     

      Рис. 1. Форма приложения с визуальными компонентами

 Визуализирующие компоненты TDBListBox (список), TDBComboBox (выпадающий список), TDBLookupListBox (список для полей просмотра),   TDBLookupComboBox (выпадающий список для полей просмотра) образуют группу списочных компонентов работы с БД. Все они работают со связанными с ними списками значений.

 Списочные компоненты предназначены для ввода в определённое поле текущей записи набора данных значения (нового, или заменяющего уже имеющееся в этом поле значение). Первые два компонента изначально имеют пустые списки, которые приложение должно заполнить, прежде чем эти списки станут доступны пользователю в качестве источников данных для заполнения полей записей набора данных (НД). Третий и четвёртый компоненты формируют свои списки автоматически, используя значения, взятые из поля другого НД.

 Компонент TDBLookupComboBox применяется для ввода значений в поле одного набора данных (назовём его НД1) из списка значений, источником которого служат значения поля из другого набора данных (НД2). Наборы НД1 и НД2 связываются по полю связи, которое должно иметь один и тот же тип в обоих НД. При этом редактируемое поле НД1 должно быть ссылочным (т. е. должно быть полем внешнего ключа таблицы НД1), а поле НД2 должно быть полем первичного ключа таблицы НД2 (т. е. между таблицами НД1 и НД2 должна быть реляционная связь, в которой таблица НД2 – родительская, а таблица НД1 – подчинённая). Указанные условия справедливы при работе с таблицами Paradox, но при работе с таблицами SQL-серверов, условия могут отличаться от перечисленных выше (см. литературу).

 В нашем случае, когда поле Tovar НД1,  в которое надо вводить значения (или их редактировать), не является полем просмотра (подстановочным полем), настройка компонента TDBLookupComboBox производится  следующим образом:

1).  В свойство DataSource компонента TDBLookupComboBox помещается имя компонента-источника редактируемого НД. В нащем случае мы редактируем набор данных Table2. Имя компонента-источника этого НД DataSource2.

2).  В свойство DataField компонента TDBLookupComboBox помещается имя поля (редактируемого НД), которое мы собираемся заполнять или редактировать. Редактировать нам надо поле Tovar НД таблицы Prihod. В нашем случае родительской является таблица Tovary.db (ей соответсвует НД Table1), дочерней является таблица Prihod.db (ей соответствует НД Table2). Полем НД Table2 дочерней таблицы, которое нам надо заполнять и редактировать, является ссылочное поле Tovar (его значения ссылаются на значения поля первичного ключа Tovar родительской таблицы Tovary.db – набор данных Table1).

3).  В свойство ListSource компонента TDBLookupComboBox помещается имя компонента-источника  НД таблицы, которая является родительской для таблицы редактируемого НД. Редактируемый набор данных – Table2. Родительской таблицей для таблицы НД Table2 (Prihod.db), является таблица Tovary.db, имя компонента-источника набора данных которой – DataSource1.

4).  В свойство ListField компонента TDBLookupComboBox помещается имя поля НД родительской таблицы, из которого автоматически должны быть взяты значения в раскрывающийся список компонента  TDBLookupComboBox. В литературе это поле называют отображаемым или результирующим. В нашем случае предполагается, что в редактируемое поле НД дочерней таблицы (Tovar) надо будет помещать значения из поля первичного ключа НД родительской таблицы - Tovar, которое, поэтому, и будет отображаемым (результирующим). Именно это имя и надо поместить в свойство ListField компонента TDBLookupComboBox

5).  В свойство KeyField компонента TDBLookupComboBox помещается имя, в общем случае индексого поля НД родительской таблицы, на которое ссылается редактируемое поле НД дочерней (редактируемой) таблицы (имя этого редактируемого поля НД редактируемой таблицы ранее уже было помещено в свойство DataField компонента TDBLookupComboBox). В нашем случае ссылочное поле Tovar НД дочерней таблицы Prihod.db ссылается на ключевое (то есть индексное) поле Tovar НД родительской таблицы Tovary.db. Поэтому, в свойство KeyField компонента компонента TDBLookupComboBox надо поместить имя поля первичного ключа (индексного поля) НД родительской таблицы -  Tovar.

 В итоге свойства  компонента TDBLookupComboBox должны приобрести следующие значения:

Свойство 

Значение 

Свойство 

Значение 

DataSource
DataFiled
ListSource
 

DataSource2
Tovar
DataSource1
 

ListField
KeyField
 

Tovar
Tovar
 

 

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

 Добавьте к форме 5 компонентов TButton (страница Standard палитры компонентов). Измените имена этих компонентов (свойство Name) соответственно на InsertButton, EditButton, DeleteButton, PostButton, EditButton. Измените надписи на кнопках (свойство Caption) соответственно на «Добавить», «Изменить», «Удалить», «Запомнить», «Отменить».

 Осталось только написать обработчики событий – нажатий размещённых нами на форме кнопок.

1).  Обработчик события OnClick для компонента InsertButton, соответствующего кнопке «Добавить». Рассмотрим подробнее, как написать обработчик события «нажатие кнопки» (OnClick) для компонента InsertButton, который соответствует экранной кнопке «Добавить».

 1.1). Двойной щелчок «мыши» по кнопке «Добавить» в окне разработки формы проекта в Delphi приведет к тому, что в тексте программного модуля проекта будут автоматически сформированы все структуры, необходимые для написания обработчика события OnClick для этой кнопки, начиная от объявления нужных переменных и процедуры, и, кончая формированием заготовки непосредственно для обработчика события. При этом автоматически произойдет переход из окна проектирования формы проекта в окно программного модуля проекта, в котором курсор установится непосредственно в том месте, начиная с которого надо писать текст обработчика события OnClick компонента InsertButton, соответствующего кнопке «Добавить». Для примера на рис.2 показан вид окна программного модуля Unit1 проекта Project1, в котором отображена заготовка обработчика события OnClick для экранной кнопки Button6, которая видна в окне разработки формы проекта Form1.

      Рис. 2. Заготовка обработчика события OnClick для экранной кнопки Button6

1.2). Далее, между строками с ключевыми словами Begin и end заготовки обработчика события OnClick надо вписать основной текст этого обработчика. Это должен быть текст программы реализации  действий, которые должны происходить после щелчка «мышью» по экранной кнопке «Добавить».

Ниже показан полный текст обработчика события OnClick для компонента InsertButton, соответствующего экранной кнопке «Добавить».

Procedure Tform1.InsertButtonClick(Sender: TObject);

begin

if  Table2.State = dsBrowse then

Table2.Insert;
end;

 Если набор данных Table2 находится в режиме просмотра dsBrowse, то метод Insert переводит его в состояние добавления записи dsInsert. Ввод значений полей новой записи набора данных Table2, соответствующего таблице Prihod, в нашей программе осуществляется в компонентах DBEdit1, DBLookupComboBox1, DBEdit2.

2).  Обработчик события OnClick для компонента EditButton, соответствующего кнопке «Изменить»:

procedure Tform1.EditButtonClick(Sender:  TObject);

begin

if  Table2.State = dsBrowse then

Table2.Edit;
end;

 Если набор данных Table2 находится в режиме просмотра dsBrowse, то метод Edit переводит его в состояние добавления записи dsEdit. Ввод новых значений полей для текущей записи набора данных Table2, соответствующего таблице Prihod, в нашей программе осуществляется в компонентах DBEdit1, DBLookupComboBox1, DBEdit2.

3). Обработчик события OnClick для компонента DeleteButton, соответствующего кнопке «Удалить»:

procedure Tform1.DeleteButtonClick(Sender:  TObject);

begin

 if Table2.State = dsBrowse then

 if MessageDlg('Подтвердите удаление записи’,

  mtConfirmation,[mbYes, mbNo],0)  = mrYes then

 Table2.Delete;
end;

 Если набор данных Table2 находится в режиме просмотра записей dsBrowse, то вызывается диалоговое окно MessageDlg с предложением подтвердить удаление записи. Если пользователь нажимает кнопку Yes, текущая запись в наборе данных Table2 удаляется методом Delete.

4). Обработчик события OnClick для компонента PostButton, соответствующего кнопке «Запомнить»:

procedure TForm1.PostButtonClick(Sender:  TObject);

begin

 if  Table2.State in [dsInsert, dsEdit] then

   Table2.Post;
end;

 Если набор данных Table2 находится в режиме добавления новой записи или редактирования, то вызывается метод Post набора данных Table2, который запоминает текущее состояние текущей записи набора данных Table2 в таблицу Prihod, которой набор данных Table2 соответствует. После запоминания набор данных автоматически переводится в режим просмотра dsBrowse.

5). Обработчик события OnClick для компонента CancelButton, соответствующего кнопке «Отменить»:

procedure TForm1.CancelButtonClick(Sender:  TObject);

begin

if  Table2.State in [dsInsert, dsEdit]  then

   Table2.Cancel;
end;

 Если набор данных Table2 находится в режиме добавления новой записи или редактирования, то вызывается метод Cancel, который отменяет сделанные изменения и переводит набор данных в режим просмотра dsBrowse.

 Запустите программу. При добавлении новой записи, или при корректировке существующей, в поля можно заносить значения, используя компоненты DBEdit1, DBEdit2 и путем выбора из списка значений в компоненте DBLookupComboBox1. To же происходит при изменении записи. При удалении записи появляется диалоговое окно, показанное на рис. 2.

 

      Рис. 3. Окно подтверждения

      удаления записи

      

 Заметим, что хотя компонент TDBLookupComboBox даёт возможность просматривать список возможных значений редактируемого поля и выбирать из них нужное, но на самом деле значение, которое будет помещено в редактируемое поле реально берётся не из списка компонента TDBLookupComboBox, а из ключевого поля записи родительской таблицы (имя которого указано в свойстве KeyField), в которой присутствует выбранное в списке компонента TDBLookupComboBox значение (а список компонента  TDBLookupComboBox состоит из значений поля родительской таблицы, имя которого было указано в свойстве ListField).   

 Такой сложный метод ввода данных был выбран не случайно. Обычно в свойствах KeyField и ListField  указывается имя одного и того же поля (как в нашем случае). Но иногда удобнее сделать так, чтобы в в выпадающем списке компонента списке TDBLookupComboBox отображались бы значения одного поля родительской таблицы, а в редактируемое поле редактируемого набора данных заносились бы не значения, выбираемые из этого списка, а соответствующие им значения ключевого поля родительской таблицы. В этом случае сложный метод ввода данных даёт реальные преимущества. Допустим, есть родительская таблица, ключевым полем которой является идентификационный номер детали автомобиля (поле ID_D - числовое) и в этой же таблице есть уникальное поле наименования детали (Nam_D - строковое), каждое значение которого строго соответствует одному значению поля ID_D. В дочерней таблице, которую надо заполнять, тоже есть поле, которое должно содержать идентификационные номера деталей, но только деталей подвески автомобиля (ID_DP), поступающих на склад №3. Для того, чтобы оператору, заполняющему дочернюю таблицу не надо было бы помнить идентификационные номера всех деталей подвески автомобиля и при заполнении дочерней таблицы он мог бы ориентироваться не на них, а на наименования деталей, и при этом заносить в поле ID_DP дочерней таблицы именно идентификационные номера надо сделать так. Создать по полю ID_DP внешний ключ, ссылающийся на первичный ключ родительской таблицы ID_D. Для заполнения поля ID_DP использовать компонент TDBLookupComboBox в свойство KeyField которого поместить имя поля ID_D родительской таблицы, в свойство поля ListField поместить имя поля Nam_D родительской таблицы, а в свойство поля DataField поместить имя поля ID_DP дочерней (редактируемой) таблицы. В свойства Data Source и ListSource надо поместить имена компонентов-источников наборов данных соответственно дочерней и родительской таблиц. В этом случае всякий раз при заполнении или редактировании поля ID_DP дочерней таблицы будет раскрываться выпадающий список возможных значений, содержащий наименования деталей автомобиля (в имени всегда можно предусмотреть префикс или постфикс, косвенно указывающий на принадлежность детали, определённой системе автомобиля). Оператор по названию выбирает из этого списка нужную деталь, но при этом в поле ID_DP таблицы прихода деталей подвески на склад №3 заносится не выбранное наименование детали, а её идентификационный номер (шифр). То есть, с одной стороны, оператор работает не с труднозапоминае-мыми многозначными и «ничего не говорящими» шифрами деталей, а с их явно «говорящими» наиме-нованиями (что очень удобно оператору), а с другой стороны в дочерней таблице  сохраняются не длин-ные и занимающие много места в памяти имена деталей, а компактные цифровые шифры этих деталей – их идентификационные номера, что очень хорошо с точки зрения минимизации места, занимаемого таб-лицами БД, и с точки зрения упрощения и ускорения процессов обработки данных, содержащихся в этих таблицах.

Порядок работы с таблицей Prihod в нашей программе должен быть таким:

1. Перейти на запись, в которой (или с которой) предполагается произвести какую-то операцию.

2. Щелкнуть «мышью» по экранной кнопке, предназначенной для выполнения необходимой операции.

3. Если необходимая операция – это «Добавить» или «Изменить», то в комбобоксе и полях ввода определить новые значения полей «Товар», «Дата прихода» и «Количество». После этого щелкнуть «мышью» по экранной кнопке «Запомнить».

4. Если ввод новых значений был осуществлен с ошибками и надо отменить неверный ввод, то до щелчка мышью по клавише «Запомнить» нужно щелкнуть мышью по клавише «Отменить».

5. Для удаления всей текущей записи надо щелкнуть «мышью» по экранной кнопке «Удалить», а затем в экранной форме подтверждения подтвердить свое намерение удалить запись из таблицы щелчком «мыши» по кнопке «Yes».

2. Формирование набора данных из нескольких таблиц

 Создадим набор данных содержащий информацию из нескольких таблиц с помощью компонента TQuery.ёё

 Создайте новое приложение (с другим именем). Расположите на форме компоненты TQuery (вкладка DBE), TDataSource и TDBGrid. Установите в свойство Query1.DatabaseName имя алиаса Вашей БД. Свяжите компонент DataSource1 с Query1 (свойство DataSource1.DataSet), a DBGrid1 с
DataSource1 (свойство DBGrid1.DataSource).

 Раскройте редактор свойства SQL компонента Query1 и введите такой текст SQL-запроса:

SELECT P.DatPrih,  P.Tovar,  P.Kolvo,  T.Zena,

   (P.Kolvo * T.Zena) As Stoim

FROM Tovary T,  Prihod P

WHERE T.Tovar = P.Tovar

ORDER BY P.DatPrih,  P.Tovar;

 Закройте редактор кнопкой ОК.

 Как видно из текста запроса, набор данных собирается из двух таблиц: tovary . db и prihod.db (первой присвоен временный псевдоним T, в второй P).  При этом соединяются записи, имеющие
одинаковое значение поля
tovar (where T.Tovar = P.Tovar). Часть select P.DatPrih, P.Tovar, P.Kolvo, T.Zena, (P.Kolvo * T.Zena) As Stoim текста запроса определяет выбираемые поля, причем создается вычисляемое поле Stoim со значением P.Kolvo * T.Zena.

 Чтобы выполнить запрос, установите в свойство Queiyl.Active значение True.

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

 




 

А также другие работы, которые могут Вас заинтересовать

30185. Разработка системы управления электроприводом листоправильной машины, учитывающий переменность статического момента нагрузки и момента инерции, с целью повышения энергетической эффективности стана11×280×2300 3.84 MB
  передачи от двигателя к валку отн. От первого двигателя 24–M1 по ходу металла приводится пять правильных валков три верхних и два нижних находящихся ближе к входу листоправильной машины; от второго двигателя 24–M2 – остальные шесть валков №6–№11. Двигатели предназначены для работы от преобразователей частоты и оснащены каждый датчиком импульсов 24–BN1 24BN2 – контроль скорости вентилятором обдува с электроприводом двигатели 24–M3 24–M4 а также датчиками контроля температуры в обмотках KTY 84–130 – 1 шт и подшипниках...
30186. Разработка проекта межевания земельных участков на землях бывшего колхоза “Россия” Каширского района Воронежской области 3.42 MB
  Земельный кодекс Российской Федерации от 25.10.2001 г. №136-ВЗ является головным отраслевым законом, обладающим приоритетом в регулировании земельных отношений. Кодекс создает правовые гарантии провозглашенных в Конституции РФ земельных прав граждан; устанавливает приоритет охраны земли перед использованием в качестве недвижимости; приоритет охраны жизни и здоровья человека при решении вопроса о затратах
30187. Динамика роста и накопление сухого вещества по фазам развития растений яровой пшеницы в зависимости от условий питания и применения удобрений 80.51 KB
  Народнохозяйственное значение яровой пшеницы. Морфологические и биологические особенности яровой пшеницы. Влияние удобрений на урожайность и качество зерна яровой пшеницы яровых зерновых культур. Динамика роста и накопление сухого вещества по фазам развития растений яровой пшеницы в зависимости от условий питания и применения удобрений.
30188. Развитие композиционных умений учащихся 6-х классов средствами декоративного натюрморта в технике гуашь 1.13 MB
  Одной из основных задач образования является всестороннее созревание личности ребенка, а так же эстетическое воспитание подрастающего поколения. Эстетическое воспитание - это сложный и продолжительный процесс, дети приобретают первые художественные впечатления, изучая различные виды художественной деятельности. Изобразительная деятельность - специфическое, образное постижение действительности, которое может идти всевозможными путями.
30189. ОСНОВНЫЕ ТРЕБОВАНИЯ, ПРЕДЪЯВЛЯЕМЫЕ К СТАНОЧНЫМ ЭЛЕКТРОПРИВОДАМ 113.5 KB
  Так при требуемой точности ПОЗИционирования шпинделя 01максимальной частоте вращения двигателя 30005000 об мин суммарный диапазон изменения частоты вращения должен быть не менее 10000 Электромеханический способ регулирование скорости частоты вращения для приводов главного движения является наиболее перспективным. Требуемый технологический диапазон регулирования скорости шпинделя с постоянной мощностью равный 20 50 при двухступенчатой коробке скоростей можно обеспечить при электрическом регулированни скорости двигателя с постоянной...
30191. Учетная политика общества с ограниченной ответственностью «Релай Авто» 225 KB
  Учётная политика организации по бухгалтерскому учету. Рабочий план счетов организации. Расчет начисления амортизации за квартал 20122013 года с разбивкой по месяцам по любым 23 основным средствам организации.
30192. УЧЕТ И АНАЛИЗ РЕАЛИЗАЦИИ ТОВАРОВ НА ПРЕДПРИЯТИИ РОЗНИЧНОЙ ТОРГОВЛИ (на материалах Потребительского общества «ИЛГЭ») 146.62 KB
  Уровень и качество планирования оборота розничной торговли определяются следующими важнейшими условиями: компетентностью руководства организации на всех уровнях управления; квалификацией специалистов, работающих в функциональных подразделениях; наличием информационной базы и обеспеченностью компьютерной техникой.