- •Методические указания к выполнению лабораторных работ по дисциплине
- •1. При проектировании используйте примеры программного кода непосредственно из исходных текстов программ, а не из методических описаний (*.Doc файла)
- •2. Имена отдельным модулям лучше давать по их функциональности, а не оставлять так как они даются по умолчанию (Unit1.Pas, Unit2.Pas и т.Д.)
- •3. При возникновении каких-либо ошибок в процессе выполнения работы проверьте по исходному примеру, все ли модули подключены в разделах interface и implementation, подразделе uses.
- •Теоретическое введение
- •Создание структуры таблиц бд
- •3.3 Синтез иконки прикладного приложения
- •3.4 Размеры экранных форм и их положение на экране
- •3.5 Разработка подчинённых форм
- •Создание формы
- •Размеры и положение
- •Работа приложения с бд
- •Доступ к таблицам бд. Компоненты доступа к данным. Приложение
- •AdoDataSet (Набор данных) или adoQuery (Запрос)
- •Сохранение пути к бд
- •Работа с данными
- •Обработка данных
- •Сортировка
- •Отчёты и обработки
- •Запросы, содержащие вычисления на выделенных записях таблицы (по столбцам)
- •В обработке события OnClick кнопки Button необходимо прописать следующее:
- •Разграничение прав доступа для различных пользователей
- •Организация многопользовательского режима
Обработка данных
Сортировка
Сортировку можно осуществлять несколькими способами: непосредственно через запрос (SELECT <поля> FROM <таблица> ORDER BY <поле>), или через свойство компонента ADOQuery (ADOQuery.Sort:='<поле> <ASC или DESC>'). Воспользуемся вторым способом.
Сортировка может осуществляться в двух направлениях: по возрастанию и по убыванию. Для выбора типа сортировки поместим на форму компонент GroupBox с вкладки Standart, в свойстве Caption данного компонента запишем: “Направление сортировки”. Далее на этот компонент поместим два компонента RadioButton с вкладки Standart. Свойства Caption этих компонентов будут соответственно “По возрастанию” и “По убыванию”. Установим свойство Checked компонента “По возрастанию” в true.
Сортировка того или иного столбца будет осуществляться по нажатии на его заголовок в DBGrid.
Чтобы пользователь лучше ориентировался по направлению сортировки, будем также менять цвет заголовка столбца. Сделаем при сортировке по возрастанию цвет заголовка зеленым, при сортировке по убыванию – голубым.
В свойстве OnTitleClick компонента DBGrid запишем следующее (ASC – сортировка по возрастанию, DESC – по убыванию):
procedure TS_sotrudnikiForm.DBGrid1TitleClick(Column: TColumn); var s:string; //направление сорировки i:integer; clr:TColor; // цвет колонки при сортировке begin // по умолчанию сортировка по возрастанию // цвет колонки - зеленый s:=' ASC'; clr:= clMoneyGreen; // меняем цвет и направление если пользователь выбрал иное if RadioButton2.Checked then begin s:=' DESC'; clr:= clSkyBlue; end; // возвращаем исходный цвет всех колонок // и подсвечиваем выбранную колонку for i:=0 to DBGrid1.Columns.Count-1 do DBGrid1.Columns.Items[i].Title.Color:= clBtnFace; DBGrid1.Columns.Items[Column.Index].Title.Color:=clr; // выполняем сортировку по выбранной колонке DM.SotrQuery.Sort:= DBGrid1.Columns.Items[Column.Index].FieldName+s; end; |
Результат работы представлен на рисунке 19.
Рисунок 19 – Работа сортировки
Вместо кнопок навигатора для работы с данными можно использовать стандартные кнопки «Добавить», «Изменить», «Удалить» (это второй способ). Данный способ рассмотрен на примере справочника «Хобби». Соответствующая форма будет вызываться из главного меню так, как показано на рисунке:
Программный код:
procedure TMainForm.N21Click(Sender: TObject); begin S_HobbyForm2:= TS_HobbyForm2.Create(self); // создание формы S_HobbyForm2.ShowModal; // вывод модальной формы на экран end;
|
Но прежде необходимо создать саму форму S_HobbyForm2. Для этого в меню выбрать File–>New–>Form. В создавшейся форме в свойстве Name прописать S_HobbyForm2. А в свойстве Capion можно прописать Хобби (вариант 2).
Затем выполнить сохранение File–>Save All и проверить, чтобы в Project Options, созданная форма располагалась в разделе Available forms.
Форма Хобби (вариант 2). представлена на рисунке:
На ней расположены DBGrid1, Panel1 с компонентами для поиска, GroupBox1 для сортировки, Timer1 и три кнопки. Компоненты для добавления и редактирования будут располагаться на другой форме, которая будет вызываться по нажатию на кнопку «Добавить» или «Изменить». Создаём эту форму также как и форму S_HobbyForm2, но в свойстве Name прописываем S_HobbyEdit. Форма представлена на рисунке:
В программном коде для формы S_HobbyForm2 в разделе private будет располагаться только процедура Refresh, имеющая следующий вид:
procedure TS_HobbyForm2.Refresh; var s:string; begin s:=DM.HobbyQuery.FieldValues['H_ID'];//запоминаем код хобби DM.HobbyQuery.Close; DM.HobbyQuery.Open; DM.HobbyQuery.Locate('H_ID',s,[]);// перемещаемся на нужную позицию end;
|
Таймер будет вызывать данную процедуру через определённое время следующим образом:
procedure TS_HobbyForm2.Timer1Timer(Sender: TObject); begin Refresh; end;
|
Рассмотрим программный код другой формы – S_HobbyEdit. Тут создаём процедуру OpenForm с логическим параметром ed таким образом, чтобы эта процедура была доступна для других модулей, а именно:
ed:boolean – логический параметр OpenForm, он принимает значения True и False.
Текст самой процедуры:
Вернёмся к форме S_HobbyForm2. Рассмотрим программный код кнопок (событие OnClick). Для кнопки «Добавить»:
procedure TS_HobbyForm2.Button1Click(Sender: TObject);//кнопка "Добавить" begin Timer1.Enabled:=false;// таймер выключается OpenForm(false); // вызов процедуры "открытие формы" второй случай (см.выше) Refresh; //вызов процедуры обновления Timer1.Enabled:=true; // таймер включается end;
|
Таймер необходимо выключить, пока мы будем работать с другой формой. Затем, после того как необходимая запись добавлена, самостоятельно вызываем процедуру Refresh, тем самым внесённые изменения отобразятся в таблице. Кроме того, включаем таймер, поскольку перестаём работать в другой форме, последующее обновление будет производиться через определённое в таймере время.
Для кнопки «Изменить»:
procedure TS_HobbyForm2.Button2Click(Sender: TObject);//кнопка "Изменить" begin Refresh; // вызов процедуры обновления if DM.HobbyQuery.FieldValues['edit']=false then begin Timer1.Enabled:=false; OpenForm(true); Refresh; Timer1.Enabled:=true; end else MessageDlg('Запись редактируется другим пользователем',mtError,[mbOK],0); //вывод сообщения или такого Showmessage('Запись редактируется другим пользователем'); end;
|
Прежде чем изменять какую-то запись, самостоятельно вызовем процедуру обновления Refresh, затем проверим признак редактирования, если запись не редактируется, то вызывается процедура OpenForm (первый случай- режим изменения). Таймер работает также как и для кнопки "Добавить". Если же запись редактируется другим пользователем, то выводится соответствующее сообщение.
ПРИМЕЧАНИЕ: ЗДЕСЬ УЖЕ УЧИТЫВАЕТСЯ НЕОБХОДИМОСТЬ РЕАЛИЗАЦИИ МНОГОПОЛЬЗОВАТЕЛЬСКОГО РЕЖИМА, ПОДРОБНО ОБ ОСОБЕНОСТЯХ, КОТОРОГО ВЫ МОЖЕТЕ УЗНАТЬ В ПОДРАЗДЕЛЕ 7 ДАННОГО ОПИСАНИЯ.
Для кнопки «Удалить»:
procedure TS_HobbyForm2.Button3Click(Sender: TObject); //кнопка "Удалить" begin Refresh; if DM.HobbyQuery.FieldValues['edit']=false then begin if MessageDlg('Удалить запись?',mtWarning,[mbYes,mbNo],0)=mrYes then//если «да» begin DM.HobbyQuery.Delete; Refresh; end; end else MessageDlg('Запись редактируется другим пользователем',mtError,[mbOK],0);
// Showmessage('Запись редактируется другим пользователем'); end;
|
Прежде чем удалять какую-то запись, самостоятельно вызовем процедуру Refresh, затем проверим признак редактирования, если запись не редактируется, то выводим сообщение-вопрос: «Удалить запись?». Если ответ на вопрос «Да» (ОК), то вызываем режим удаления записи и обновляем. Если «Нет» (Отмена), запись не удаляется. Если же запись редактируется другим пользователем, то выводится соответствующее сообщение.
На форме S_HobbyEdit есть две кнопки «Ок» и «Отмена». Для кнопки «Ок»:
procedure TS_HobbyEdit.Button1Click(Sender: TObject); //Ок begin dm.HobbyQuery.FieldValues['edit']:=false;// признак редактирования – не редактируется DM.HobbyQuery.Post; //подтверждение изменений S_HobbyEdit.Close; // форма закрывается end;
|
Для кнопки «Отмена»:
procedure TS_HobbyEdit.Button2Click(Sender: TObject); // отмена begin DM.HobbyQuery.Cancel; //Отмена несохраненных изменений DM.HobbyQuery.Edit; в режим редактирования dm.HobbyQuery.FieldValues['edit']:=false;// признак редактирования – не редактируется DM.HobbyQuery.Post; //подтверждение изменений S_HobbyEdit.Close;// форма закрывается end;
|
Поиск
Поиск также можно осуществлять различными способами. Два наиболее распространенных это переход курсора на искомую запись (Query.Locate(поля; значения; опции) :boolean;) или отбор записи по значению (SELECT <поля> FROM <таблица> WHERE <имя>=<значение> или SELECT <поля> FROM <таблица> WHERE <имя> LIKE "< значение >%" – поиск по неполному совпадению).
Метод Locate ищет первую запись, удовлетворяющую критерию поиска, и если такая запись найдена, делает ее текущей. В этом случае в качестве результата возвращается True. Если поиск был неуспешный, возвращается False. То есть, этот метод предназначен в основном лишь для определения наличия данной записи.
Предиката Like определяет возможность поиска по шаблону (т.е. поиск уже с первой нажатой клавиши).
Таким образом, для поиска всех удовлетворяющих запросу записей и при удобстве использования шаблона, остановимся на использовании предиката Like.
Добавим на форму панель (Panel ). На неё расположим компонент ComboBox и Edit с вкладки Standart, как показано на рисунке 20. Свойство компонента CharCase необходимо установить в значение ecUpperCase.
Рисунок 20 – Панель поиска
В ComboBox необходимо внести список полей, по которым возможен поиск. Для этого в событии создании формы S_sotrudnikiForm - onCreate следует внести следующий код:
// Заполняем ComboBox1 по заголовкам секций компонента DBGrid1 for i:=0 to DBGrid1.Columns.Count-1 do ComboBox1.Items.Add(DBGrid1.Columns.Items[i].Title.Caption); |
Для осуществления поиска рассмотрим предикат
LIKE
Предикат LIKE сравнивает строку, указанную в первом выражении для вычисления значения строки, называемого проверяемым значением, с шаблоном, который определен во втором выражении для вычисления значения строки. В образце разрешается использовать два трафаретных символа:
Символ подчеркивания (_), который можно использовать вместо любого единичного символа в проверяемом значении.
Символ процента (%), который заменяет набор любых символов (число символов в наборе может быть от 0 и более) в проверяемом значении.
Если проверяемое значение соответствует образцу с учетом трафаретных символов, то значение предиката равно TRUE. Ниже приводится несколько примеров написания шаблонов.
Шаблон |
Описание |
'abc%' |
Любые строки, которые начинаются с букв "abc". |
'abc_' |
Строки длиной строго 4 символа, причем первыми символами строки должны быть "abc". |
'%z' |
Любая последовательность символов, которая обязательно заканчивается символом "z". |
'%Rostov%' |
Любая последовательность символов, содержащая слово "Rostov" в любом месте строки. |
При событии редактирования в поле Edit следует осуществлять одновременно поиск по неполному совпадению. Для этого в событии onChange нужно прописать следующий код:
procedure TS_sotrudnikiForm.Edit1Change(Sender: TObject); Var S:String; begin if ComboBox1.ItemIndex=-1 then ComboBox1.ItemIndex:=0; // Сохранение имени поля DBGrid1 в переменную S, по индексу выбранной записи в ComboBox1 S:=DBGrid1.Columns.Items[ComboBox1.ItemIndex].FieldName; DM.SotrQuery.SQL.Clear; // Формирования запроса по полю сохранённому в переменной S DM.SotrQuery.SQL.Add(SOTR_SQL+' WHERE '+s+' LIKE "'+Edit1.text+'%"'); // Обновляем Refresh; end; |
Таким образом, при каждом изменении записи в поле Edit будет формироваться запрос на выборку по неполному совпадению. Причем будут отбираться те записи, которые начинаются с символа, вводимого в поле Edit. Результат работы поиска представлен на рисунке 21.
Рисунок 21 – Результаты работы поиска