Практическое занятие № 18
Тема: «Работа с сеткой DBGrid»
Цель работы: получить практические навыки для работы с сеткой DBGrid
Ход работы
В среде Delphi создайте программу для работы с данными таблицы из БД "personal", в которой в двух таблицах хранится информация о должностях и сотрудниках предприятия (связаны по полю id_dolg).

При этом форма должна иметь вид:

В сетке отображаются все поля кроме поля "foto". Все поля должны иметь название по-русски и приемлемую ширину колонок.
Указания: для главной форме задайте свойства: Caption="Работа с сеткой DBGrid", Position="DesktopCenter", BorderStyle="bsSingle". На форму нанесите компонент ADOConnection (ADO). В свойстве ConnectionString укажите параметры подключения к БД Access. В свойстве LoginPrompt укажите false, чтобы программа не запрашивала логин и пароль при соединении с БД.
Нанесить на форму компонент ADOTable (ADO). В свойстве Connection укажите соединение с БД ADOConnection1, в свойстве TableName укажите таблицу Sotr.
Для того, чтобы программа корректно подключала таблицу в событии формы OnCreate введите код:
procedure TForm1.FormCreate(Sender: TObject);
begin
ADOTable1.Active:=true;
end;
Для того, чтобы программа корректно отключала таблицу в свойстве формы OnDestroy введите код:
procedure TForm1.FormDestroy(Sender: TObject);
begin
ADOConnection1.Connected:=false;
end;
Двойным щелчком на компоненте ADOTable1, в контекстном меню окна выберите команду "Add All Field". В результате в окне появится список полей таблицы. По очереди выделяйте каждое поле и в свойстве DisplayLabel укажите название поля в сетке, а в поле DisplayWidth укажите ширину поля в символах.
Вместо поля "id_dolg" создайте список с перечнем должностей из таблицы Dolg.
Указания: для формирования перечня значений для списка будем использовать запрос.
Нанесите на форму компонент ADOQuery (ADO) и задайте свойства: Connection = ADOConnection1, SQL =текст запроса вида:
select id_dolg, dolg from dolg
union
select null, null from dolg
В событии OnCreate формы добавьте код активации запроса:
ADOQuery1.Active:=true;
Двойным щелчком на компоненте ADOTable1 откройте список полей таблицы. В контекстном меню выберите команду New Field и для нового поля задайте следующие параметры:
Name = dolg (имя нового поля в таблице);
Type = String (тип нового поля в таблице);
Field type = Lookup (поле будет выпадающим списком);
Dataset = ADOQuery1 (источник данных для заполнения выпадающего списка);
Key Fields = id_dolg (поле, по которому таблица Sotr связана с должностями)
Lookup Keys = id_dolg (поле, по которому таблица Dolg связана с сотрудниками)
Result Field = dolg (поле из таблицы Dolg, которое будет отображаться в поле на форме).
Для переименования поля задайте для него свойство Display Label = Должность.

Спроектируйте сетку для отображения данных таблицы.
Указание: Нанесите на форму компонент DataSource (DataAccess). Задайте для него свойство DataSet =ADOTable1.
Нанесите на форму компонент DBGrid (DataControls). В свойстве DataSource укажите имя компонента DataSource1. Щелкните два раза на компоненте DBGrid. В окне вызовите контекстное меню и выберите команду "Add All Fields". В результате в окне отобразится список полей таблицы. Для полей "id_dolg" и "foto" задайте свойство Visible=false.
Нанесите на форму компонент DBNavigator (DataControls). Задайте свойство DataSource=DataSource1.
Для выравнивания компонентов на форме для компонента DBNavigator задайте свойство Align = alBottom, для компонента DBGrid свойство Align = alClient.
В ячейке колонки "Дата рождения" отображается кнопка с троеточием, с помощью которой открывается вспомогательная форма с календарем:

Указания: для отображения кнопки с троеточием двойным щелчком на сетке откройте список колонок, выделите колонку Datar и задайте свойства: ReadOnly=true; ButtonStyle=cbsEllipsis.
Для редактирования поля "Datar" создадим новую форму. Чтобы форма не создавалась автоматически при запуске программы выполните команду "Project – Options" и перенесите форму в список "Available Forms". Для новой формы задайте свойства: BorderStyle=bsNone, Position = poOwnerFormCenter.
Нанесите на форму компонент MonthCalendar (Win32) и две кнопки. Для календаря задайте свойство Align = alTop.
При открытии этой формы в календаре должна отображаться дата из поля "Datar" сетки. Для этого в событии OnCreate формы введите код:
procedure TForm2.FormCreate(Sender: TObject);
begin
//если поле "Datar" не пустое
if form1.ADOTable1.FieldByName('datar').AsString<>'' then
//в календаре отображаем значение этого поля
MonthCalendar1.Date:=form1.ADOTable1.FieldByName('datar').Value
//если поле "Datar" пустое
else
//в календаре отображаєм текущую дату
MonthCalendar1.Date:=date;
end;
Кнопка "Сохранить" закрывает форму, а в поле "Datar" сетки отображается выбранная дата. Для этого для кнопки напишем код:
procedure TForm2.Button1Click(Sender: TObject);
begin
//в поле сетки отображаем выбранную дату
form1.ADOTable1.FieldByName('datar').Value:=MonthCalendar1.Date;
//переходим в поле "datar"
form1.ADOTable1.FieldByName('datar').FocusControl;
//закрываем форму
Close;
end;
Кнопка "Отменить" закрывает форму не внося изменений в поле сетки. Для кнопки напишем код:
procedure TForm2.Button2Click(Sender: TObject);
begin
//переходим на поле "datar"
form1.ADOTable1.FieldByName('datar').FocusControl;
//закрываем форму
Close;
end;
При закрытии формы с календарем форма должна удаляться из памяти. В событии формы OnClose введите код:
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action:=caFree;
end;
При щелчке на кнопке с тремя точками должна открываться созданная вами форма с календарем. Для этого в событие OnEditButtonClick сетки введите код:
procedure TForm1.DBGrid1EditButtonClick(Sender: TObject);
begin
//если пользователь щелкнул в ячейке поля "datar"
if DBGrid1.Columns[DBGrid1.SelectedIndex].FieldName='datar' then
begin
//переводим таблицу в режим редактирования
ADOTable1.Edit;
//создаем и открываем форму Form2
form2:=TForm2.Create(self);
form2.ShowModal;
end;
end;
В сетке создайте специальную колонку для отображения состояния поля "foto". Если поле заполнено (имеется фото в базе), то в колонке отображается одна иконка, иначе - другая.
Указания: для добавления пустой колонки щелкните на сетке два раза. В контекстном меню окна выберите команду "Add". Для созданной колонки задайте свойства: FieldName=pict, Title - Caption = 1 пробел, Width = 25.
Для хранения иконок нанесите на форму компонент ImageList (Win32). Двойным щелчком откройте этот компонент и с помощью кнопки "Add" добавьте в него нужные рисунки.
Для отображения иконок в ячейках созданной колонки в событии OnDrawColumnCell опишите переменную:
var p:TBitmap;
и добавьте код:
//если заголовок колонки равен пробелу (наша новая ячейка)
if Column.Title.Caption = ' ' then
begin
//создаем в памяти переменную для считывания иконки
p:=TBitmap.Create;
//если поле "foto" не пустое
if not ADOTable1.FieldByName('foto').IsNull then
//считываем первую иконку (нумерация с 0)
ImageList1.GetBitmap(0,p)
//иначе, если поле "foto" не пустое
else
//считываем вторую иконку
ImageList1.GetBitmap(1,p);
//отображаем считанную иконку в ячейке колонки
DBGrid1.Canvas.Draw(Rect.Left,Rect.Top,p);
end;
В сетке выполните условной форматирование строк по правилу: строки с окладом до 1500 обозначаются одним цветом, а более 1500 - другим.
Указания: в событии DrawColumnCell сетки НАД КОДОМ ОТОБРАЖЕНИЯ ИКОНОК введите код:
procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;DataCol: Integer; Column: TColumn; State:TGridDrawState);
begin
//если поле "oklad" менее 1500
if ADOTable1.FieldByName('oklad').Value<1500 then
//для сетки задаем один цвет фона
DBGrid1.Canvas.Brush.Color:=$00FFAFC8
else
//иначе задаем другой цвет фона
DBGrid1.Canvas.Brush.Color:=$00A5FFB6;
//заливаем строку указанным цветом фона
DBGrid1.Canvas.FillRect(Rect);
//после заливки весь текст становится невидимым (залитым фоном)
//нужно заново вывести весь текст в колонках
//при этом колонка с рисунком не имеет текста и ее нужно пропустить
//если заголовок текущей колонки не равен пробелу (не колонка с рисунком)
if Column.Title.Caption <> 'Фото' then
//выводим в ней текст
DBGrid1.Canvas.TextOut(Rect.Left+2,Rect.Top+2,Column.Field.Text);
end;
При щелчке на иконке нужно отображать окно для просмотра и редактирования поля "foto".

Указания: добавьте новую форму. Чтобы форма не создавалась автоматически при запуске программы выполните команду Project - Options и перенесите форму в список Available Forms. Для новой формы задайте свойства: Caption=Фото, Position = poOwnerFormCenter. С помощью команды File - Use Unit подключите модуль главной формы Unit1.
Нанесите на форму компонент DBImage(DataControls) и две кнопки.
Для DBImage задайте свойства: DataSource=Form1.Datasource, DataField=foto, Align=alTop, Stretch=true.
Кнопка "Изменить" открывает диалог выбора файла и записывает указанный файл в поле "foto". Для этого нанесите на форму компонент OpenPictureDalog (Dialogs). В свойстве Filter оставьте только формат *.bmp. Для кнопки напишите код:
procedure TForm3.Button1Click(Sender: TObject);
begin
if OpenPictureDialog1.Execute then
//загружаем в поле "foto" выбранный файл
TBlobField(form1.ADOTable1.FieldByName('foto')).LoadFromFile(OpenPictureDialog1.FileName);
end;
Для работы функции TBlobFeld подключите модуль DB.
Кнопка "Очистить" очищает содержимое поля. Для кнопки напишите код:
procedure TForm3.Button2Click(Sender: TObject);
begin
TBlobField(form1.ADOTable1.FieldByName('foto')).Clear;
end;
При закрытии формы нужно форму удалить из памяти. Для этого в событии OnClose формы введите код:
procedure TForm3.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action:=caFree;
end;
Созданная форма должна появляться после щелчка пользователем в ячейке с картинкой. Для этого в событии OnCellClick сетки добавьте код:
//если щелкнули в ячейке с картинкой (заголовок колонки равен пробелу)
if Column.Title.Caption = ' ' then
begin
//переводим таблицу в режим редактирования
ADOTable1.Edit;
//создаем и открываем форму Form3
form3:=TForm3.Create(Self);
form3.ShowModal;
end;
В программе реализовать сохранение и восстановление таких параметров сетки как: порядок, ширина и заголовок колонок.
Указания: для работы с реестром подключите модуль Registry.
Для сохранения параметров колонок сетки в событии OnClose формы введите код:
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
//вначале опишите переменную для работы с реестром и счетчик цикла
var reg:TRegistry; i:integer;
begin
//создаем объект для работы с реестром
reg:=TRegistry.Create;
//задаем текущий раздел реестра
reg.RootKey:=HKEY_LOCAL_MACHINE;
//в цикле проходим по всем колонкам сетки
for i:=0 to DBGrid1.Columns.Count-1 do
begin
//создаем или открываем в реестре раздел для i-й колонки
reg.Openkey('\Software\MyProgram\DBGrid\Col'+inttostr(i),true);
//записываем в реестр параметры сетки
reg.WriteString('Field',DBGrid1.Columns.Items[i].FieldName);
reg.WriteInteger('Width',DBGrid1.Columns[i].Width);
reg.WriteString('Caption',DBGrid1.Columns[i].Title.Caption);
//закрываем раздел для i-й колонки
reg.CloseKey;
end;
//удаляем из памяти объект для работы с реестром
reg.Free;
end;
При запуске программы из реестра нужно считывать сохраненные данные. Для этого в событие OnCreate главной формы добавьте код:
//вначале опишите переменную для работы с реестром и счетчик цикла
var reg:TRegistry; i:integer;
//в код события добавьте команды
//создаем объект для работы с реестром
reg:=TRegistry.create;
//задаем текущий раздел реестра
reg.RootKey:=HKEY_LOCAL_MACHINE;
//если в реестре существует указанная ветка
if reg.KeyExists('\Software\MyProgram\DBGrid') then
begin
//в цикле проходим по всем колонкам сетки
for i:=0 to DBGrid1.Columns.Count-1 do
begin
//открываем в реестре раздел для i-й колонки
reg.OpenKey('\Software\MyProgram\DBGrid\Col'+inttostr(i),true);
//применяем к колонке сетки считываемые параметры
DBGrid1.Columns[i].FieldName:=reg.ReadString('field');
DBGrid1.Columns[i].Width:=reg.ReadInteger('Width');
DBGrid1.Columns[i].Title.Caption:=reg.ReadString('caption');
//закрываем раздел для i-й колонки
reg.CloseKey;
end;
end;
//удаляем из памяти объект для работы с реестром
reg.Free;
end;
Запустите программу измените порядок и ширину колонок в сетке. Перезапустите программу и убедитесь, что параметры восстанавливаются корректно.