Лекция № 20
Тема: «Работа с сеткой DbGrid»
План
1. Основные свойства сетки
2. Работа с колонками сетки
3. Формирование списка значений для колонок
4. Условное форматирование сетки
5. Отображение графики в сетке
6. Сохранение параметров сетки в реестре
1. Основные операции с сеткой DbGrid
Компонент DbGrid служит для отображения записей в виде таблицы. Данный компонент обладает рядом свойств и событий, которые повышают удобство работы с данными.
Компонент имеет свойства:
· BorderStyle - позволяет отобразить или скрыть границы сетки
· Color - задает цвет фона сетки
· Columns - список колонок сетки. Позволяет настраивать свойства каждой колонки отдельно;
· Datasource - содержит ссылки на набор данных, который будет отображаться в сетке;
· FixedColor - цвет фиксированных областей на сетке;
· Options - перечень свойств сетки (см. Ниже);
· ReadOnly - защита сетки от редактирования;
· TitleFont - параметры шрифта заголовка сетки.
С помощью свойства Options можно задать множество параметров сетки. Каждый из параметров принимает два значения true/false. К таким параметрам относятся:
· dgEditing - данные в сетке можно редактировать;
· dgAlwaysShowEditor - при переходе в ячейку сетки сразу отображается курсор;
· dgTitles - отображается строка заголовка сетки;
· dgIndicator - слева отображается колонка для указания текущей записи;
· dgColumnResize - позволяет изменять ширину и порядок колонок сетки;
· dgColLines - отражает вертикальные линии сетки;
· dgRowLines - отражает горизонтальные линии сетки;
· dgTabs - позволяет переход по колонкам с помощью клавиши Tab;
· dgRowSelect - при щелчке на любой ячейке строки выделяется вся строка. При включении данного режима автоматически выключается свойство goEditing (сетку нельзя редактировать)
· dgAlwaysShowSelection - активная ячейка в сетке остается выделенной, даже если сетка потеряет фокус;
· dsConfirmDelete - при нажатии Ctrl + Delete пользователь может удалить выбранный строку. Данный параметр указывает, что при удалении нужно выдавать запрос на подтверждение операции;
· dsCancelOnExit - если пользователь добавил новую строку в сетку и ничего в нее не вводил, то при переходе на другой компонент (сетка потеряла фокус), новая строка уничтожается без сохранения;
· dsMultiSelect - позволяет выделение нескольких строк удерживая клавишу Ctrl или Shift.
Свойство Options можно устанавливать при проектировании формы, а также программно. При программном изменении в перечень стандартно включенных параметров добавляют нужны с помощью команды:
DbGrid1.Options = DbGrid1.Options + [список параметров];
Для выключения свойств их нужно вычесть с помощью команды:
DbGrid1.Options = DbGrid1.Options- [список параметров];
Например, пусть сетка заблокирована для редактирования (отключены свойства dgEditing и dgAlwaysShowEditor). При двойном щелчке текущей записи сетки нужно перейти в режим редактирования. Напишем код в событии сетки OnDblClick:
procedure TForm1.DbGrid1DblClick (Sender: Tobject)
begin
// переводим запись в режим редактирования
ADOTable1.Edit;
// активируем параметры для редактирования сетки
DbGrid1.Options:=DbGrid1.Options+[dgEditing,dgAlwaysShowEditor];
end;
При сохранении записи или отмене изменений сетка должна вернуться в исходное состояние. В событии OnAfterPost и OnAfterCancel таблицы ADOTable вставим команду:
DbGrid1.Options:=DbGrid1.Options-[dgEditing,dgAlwaysShowEditor];
Свойства, доступные при написании кода
Сетка имеет ряд свойств, которые доступны только при написании кода:
· FieldCount - количество колонок в сетке;
· SelectedField - позволяет обратиться к полю БД в активной колонке;
· SelectedIndex - содержит номер активной колонки (нумерация с 0);
2. Работа со столбиками сетки
Каждая сетка имеет колонки. При этом колонки могут быть как связаны с полями таблицы БД, так и быть пустыми. Для работы со списком колонок используют специальный редактор, который вызывается двойным щелчком на компоненте DbGrid или с помощью свойства Columns сетки.
В контекстном меню есть команды для добавления колонки, удаление колонки, добавление всех полей таблицы в виде колонок.
При выделении колонки в редакторе для него можно задать ряд свойств:
· Alignment - выравнивание текста;
· ButtonStyle - тип кнопки в колонке (bsAuto - выпадающий список, bsEllipsis - кнопка с тремя точками, bsNone - нет кнопки);
· Color - цвет фона колонки;
· DropDownRows - число отображаемых строк в полу с выпадающим списком;
· FieldName - имя поля таблицы, связаного с колонкой сетки;
· PickList - перечень значений для поля с выпадающим списком;
· ReadOnly - блокирует колонку для ввода;
· Title - параметры заголовка колонки;
· Visible - делает колонку видимой или невидимой;
· Width - ширина колонки.
Обращение к колонке сетки
Для обращения к колонке сетки можно использовать запись:
DbGrid1.Columns[i]
где i - номер колонки (нумерация с 0).
Такая запись позволяет обратиться к любому свойству колонки в программе:
DbGrid1.Columns[i].FieldName //обращение к имени поля колонки
DbGrid1.Columns[i].Visible //обращение к параметра видимости столбца
Обращение к текущей колонке сетки
Если пользователь щелкнул на ячейке сетки, то часто нужно узнать, на каком столбце выполнен щелчок. Это можно сделать с помощью свойства DbGrid1.SelectedIndex. Данное свойство содержит номер колонки, на которой щелкнул пользователь (нумерация с 0). Например, условие вида:
if DbGrid1.SelectedIndex = 1 then
. . .
проверяет, щелкнул ли пользователь на второй колонке.
Обратиться к активной колонке можно с помощью записи:
DbGrid1.Columns[DbGrid1.SelectedIndex]
Создание пустых колонок
Сетка может иметь колонки, не связанные с полями таблицы. Такие колонки могут играть информационную функцию. Например, ячейки такой колонки могут окрашиваться в разный цвет, в зависимости от некоторого условия.
Также такие колонки могут создаваться для просмотра BLOB-полей. Если пользователь щелкнет по ячейке такой колонки, то откроется содержимое BLOB-поля.
Например, пусть в сетке есть пустая колонка с заголовком «Фото». Если пользователь щелкнет по ячейке этой колонки, то откроется новая форма Form2, на которой отображается фото выбранного сотрудника.
Для обработки щелчка по ячейке сетки в компонента DbGrid имеется событие OnCellClick, в котором и напишем код:
if DbGrid1.Columns[DbGrid1.SelectedIndex].FieldName='' then
Form2.ShowModal;
Данный пример ищет столбик, для которого не указана свойство FieldName (пустое). Если в сетке будет несколько пустых полей, то при щелчке на каждом из них будет открывать форма Form2. Если нужно открывать форму только при щелчке на колонке с именем «Фото», то нужно проверять именно заголовок столбца, а код изменится так:
if DbGrid1.Columns[DbGrid1.SelectedIndex].Title.Caption='Фото' then
Form2.ShowModal;
3. Формирование списка значений для колонок
Если значение поля таблицы может принимать одно из значений некоторого фиксированного набора (например, пол, день недели, месяц, разряд и т.п.), то для такой колонки можно создать список с перечнем допустимых значений. Для этого двойным щелчком на сетке DbGrid откройте редактор колонок, выделите колонку нужного поля таблицы и в свойства PickList введите перечень значений. Также можно в свойствах DropDownRows указать количество строк списка, видимых для пользователя. Если реально в списке больше строк, чем указано в свойстве, то появится полоса прокрутки списка.
В результате в ячейке такой колонки будет появляться кнопка для раскрытия списка значений. Пользователь имеет возможность ввести значение с клавиатуры или выбрать из списка.
Динамическое формирование списка
Очень часто полный перечень допустимых значений колонки не известен и может изменяться в процессе работы программы. В этом случае приходится формировать такой перечень динамически по ходу работы. Чаще всего такой перечень формируется на основании данных из отдельной таблицы-справочника.
Для создания такой колонки со списком, необходимо подключить таблицу-справочник и создать в редакторе полей компонента ADOTable новое Lookup-поле (см. лекцию 19).
4. Условное форматирование сетки
Иногда нужно, чтобы строки или ячейки в сетке выделялись разным цветом. Для этого в событии сетки OnDrawColumnCell можно проверить нужные условии и отформатировать сетку.
Заливки элементов сетки выполняется стандартным набором операций:
· заливки фона поля
DbGrid1.Canvas.Brush.Color:=clRed; // задаем цвет фона
DbGrid1.Canvas.FillRect(Rect); // заливаем строку
· вывод текста
DbGrid1.Canvas.Font.Color:=clBlack; // задаем цвет текста
DbGrid1.Canvas.TextOut(Rect.Left,Rect.Top,Column.Field.Text); // вывести текст
Если проверяется только значение поля, то заливается вся строку.
Пример. Строки, в которых размер оклада более 1000 залить красным цветом, другие - синим. Текст выдать черным цветом. Если поле с окладом имеет имя oklad, то в события сетки OnDrawColumnCell напишем код:
// если оклад больше 1000
if ADOTable1.FieldByName('oklad').AsFloat>1000 then
// задаем красный цвет фона строки
DbGrid1.Canvas.Brush.Color:=clRed
Else
// в противном случае задаем синий цвет фона
DbGrid1.Canvas.Brush.Color:=clBlue;
// заливаем строку
DbGrid1.Canvas.FillRect(Rect);
// задаем цвет текста в строке
DbGrid1.Canvas.Font.Color:=clBlack;
// печатаем текст в строке
DbGrid1.Canvas.TextOut(Rect.Left+2,Rect.Top+2,Column.Field.Text);
Если кроме значения поля проверяется еще и имя поля, то заливается не вся строка сетки, а только ячейка, которая соответствует имени проверяемого поля. Для проверки имени поля в события OnDrawColumnCell используют запись:
Column.FieldName
Пример. Пусть в сетке имеется пустая колонка. В строках, в которых размер оклада более 1000, залить ячейку пустой колонки красным цветом, а другие ячейки этой же колонки синим. Если поле имеет имя oklad, то в события сетки OnDrawColumnCell напишем код:
if Column.FieldName='' then
begin
if ADOTable1.FieldByName('oklad').AsFloat>1000 then
// задаем красный цвет фона ячейки
DbGrid1.Canvas.Brush.Color:=clRed
else
// задаем синий цвет фона ячейки
DbGrid1.Canvas.Brush.Color:=clBlue;
// заливаем ячейку
DbGrid1.Canvas.FillRect(Rect);
end;
В рассмотренном выше пример текст всегда выводится по левому краю. В реальных программах текстовые данные обычно выдают по левому краю, а числа и даты по правому или по центру. Поэтому при выдаче текста нужно проверять тип выдаваемых данных и соответственно выравнивать их.
Перепишем пример с учетом вышесказанного.
Пример: Строки, в которых размер оклада более 1000, залить красным цветом, другие - синим. Текст выдать черным цветом.
if ADOTable1.FieldByName('oklad').AsFloat>1000 then
// задаем красный цвет фона строки
DbGrid1.Canvas.Brush.Color:=clRed
else
// задаем синий цвет фона строки
DbGrid1.Canvas.Brush.Color:=clBlue;
// заливаем строку
DbGrid1.Canvas.FillRect(Rect);
// задаем текст цвета текста в строке
DbGrid1.Canvas.Font.Color:=clBlack;
// если выводимый текст срочного типа
if (Column.Field.DataType=ftWideString) or
(Column.Field.DataType=ftString) then
// выдаем текст по левому краю
DbGrid1.Canvas.TextOut(Rect.Left+2,Rect.Top+2,Column.Field.Text)
// иначе выдаем текст по правому краю
else
DbGrid1.Canvas.TextOut(Rect.Right-DbGrid1.Canvas.TextWidth(Column.Field.Text)-2, rect.top+2, Column.Field.Text);
Пример. В строках, в которых размер оклада более 1000 грн, залить ячейку поля fam красным цветом и выдать текст черным цветом.
if Column.FieldName='fam' then
begin
if ADOTable1.FieldByName('oklad').AsFloat>1000 then
// задаем красный цвет фона ячейки
DbGrid1.Canvas.Brush.Color:=Clred
else
// задаем синий цвет фона ячейки
DbGrid1.Canvas.Brush.Color:=clBlue;
// заливаем ячейку
DbGrid1.Canvas.FillRect(Rect);
// задаем цвет текста в ячейке
DbGrid1.Canvas.Font.Color:=clBlack;
// если выводимый текст строчного типа
if (Column.Field.DataType=ftWideString) or
(Column.fIeld.DataType=ftString) then
// выдаем текст по левому краю
DbGrid1.Canvas.TextOut(Rect.Left+2,Rect.Top+2,Column.Field.Text)
// иначе выдаем текст по правому краю
else
DbGrid1.Canvas.TextOut(Rect.Right-DbGrid1.Canvas.TextWidth(Column.Field.Text)-2,rect.top+2, Column.Field.Text);
end;
Примечание: при выводе текста надо принимать во внимание, что в некоторых ячейках сетки не может быть текста (например - это поля с BLOB данными или поля, не связанные с полями таблицы). В этом случае команда вывода текста будет выдавать в таких ячейках ошибку. Поэтому надо всегда проверять имена полей перед выводом.
Пример. В предыдущем примере мы вывели тест с различным выравниванием в ячейках. Пусть в сетке имеется ячейка для поля photo. Надо вывести текст во всех ячейках, кроме этого поля. Код будет иметь вид:
// если ячейка принадлежит полю photo
// то код ниже не выполняется
if Column.FieldName='photo' then Exit;
// задаем цвет текста в ячейке
DbGrid1.Canvas.Font.Color:=clBlack;
// если выводимый текст строчного типа
if (Column.Field.DataType=ftWideString) or
(Column.Field.DataType=ftString) then
// выдаем текст по левому краю
DbGrid1.Canvas.TextOut(Rect.Left+2,Rect.Top+2,Column.Field.Text)
// иначе выдаем текст по правому краю
else
DbGrid1.Canvas.TextOut(Rect.Right-DbGrid1.Canvas.TextWidth(Column.Field.Text)-2,Rect.Top,Column.fiEld.Text);
end;
5. Отображение графики в сетке
В некоторых программах в ячейках сетки нужно отображать графические элементы (иконки). Например, при вставке фотографии в поле Фото в соответствующей ячейке появляется небольшая иконка, указывающая на то, что поле графическое и оно заполнено. Для реализации отображения графической информации в ячейке, необходимо поместить на форму компонент ImageList и добавить в него все иконки, необходимые для отображения. Затем в событии сетки OnDrawColumnCell ввести код:
// описываем переменную
var im1: TBitmap;
begin
// создаем объект для считывания картинок из ImageList
im1:=TBitmap.Create;
// будем отображать графику в колонке с именем pict
if (Column.FieldName='pict') then
begin
// заливаем ячейку белым цветом
DbGrid1.Canvas.Brush.Color:=clWhite;
DbGrid1.Canvas.FillRect(Rect);
// если поле foto не пустое
if not ADOTable1.FieldByName('foto').IsNull then
// считываем первую иконку для отображения
ImageList1.GetBitmap(0,im1)
// иначе считываем вторую картинку
else
ImageList1.GetBitmap (2,im1);
// по центру ячейки отражаем считанную картинку
DbGrid1.Canvas.Draw((Rect.Left+Rect.Right-im1.Width) div 2,Rect.top+2,im1);
end;
end;
5. Сохранение параметров сетки в реестре
Одним из существенных удобств для пользователя при работе с сеткой является реализация возможности настройки порядка, ширины и внешнего вида колонок сетки. Для сохранения параметров рекомендуется использовать реестр Windows. При сохранении параметров сетки в реестр необходимо учитывать следующее правило: нужно сохранять все параметры, которые вы меняли для колонок сетки + имя поля + видимость + ширину.
Рассмотрим пример: пусть для колонок сетки заданы цвет фона и заголовок. При выходе из программы необходимо сохранить параметры сетки в реестре в ветке HKLM_LOCAL_MACHINE \ Software \ MyProgram \ DbGrid.
В событии OnClose формы напишем код:
// описываем переменные
var reg: TRegistry; i: integer;
begin
// создаем объект для работы с реестром
reg:=TRegistry.Create;
// задаем начальный раздел реестра
reg.RootKey:=HKEY_LOCAL_MACHINE;
// в цикле проходим по всем колонкам сетки
for i:=0 to DbGrid1.FieldCount-1 do
begin
// создаем в реестре очередную ветку col[i]
reg.OpenKey('\Software\MyProgram\DbGrid\col'+IntToStr(i),true);
// записываем в реестр имя поля колонки
reg.WriteString ('field',DbGrid1.Columns.Items[i].FieldName);
// записываем в реестр текст заголовка колонки
reg.WriteString ('caption',DbGrid1.Columns[i].Title.Caption);
// записываем в реестр цвет фона колонки
reg.WriteInteger('color',DbGrid1.Columns[i].Color);
// записываем в реестр признак видимости колонки
reg.WriteBool('visible',DbGrid1.Columns[i].Visible);
// записываем в реестр ширину колонки
reg.WriteInteger('width',DbGrid1.Columns[i].Width);
//закрываем ветку по колонке сетки
reg.CloseKey;
end;
// удаляем из памяти объект для работы с реестром
reg.Free;
end;
Для работы кода не забудьте подключить модуль Registry.
Запустите программу и закройте ее. В результате в реестре будут созданы нужные записи. После этого можно писать код для чтения данных о параметрах сетки из реестра. В событии формы OnCreate напишите код:
// описываем переменные
var reg: TRegistry; i: integer;
begin
// создаем объект для работы с реестром
reg:=TRegistry.Create;
// задаем начальный раздел реестра
reg.RootKey:=HKEY_LOCAL_MACHINE;
// проверяем, существует ли в реестре запись о сетке
if reg.KeyExists('Software\MyProgram\DbGrid' then
begin
// в цикле проходим по всем колонкам сетки
for i:=0 to DbGrid1.FieldCount-1 do
begin
// открываем в реестре очередную ветку col[i]
reg.OpenKey('\software\myprogram\DbGrid\col'+IntToStr(i),true);
// читаем из реестра имя поля для колонки
DbGrid1.Columns[i].FieldName:=reg.ReadString('field');
// читаем из реестра текст заголовка колонки
DbGrid1.Columns[i].Title.Caption:=reg.ReadString('caption');
// читаем из реестра цвет фона колонки
DbGrid1.Columns[i].Color:=reg.ReadInteger('color');
// читаем из реестра параметр видимости колонки
DbGrid1.Columns[i].Visible:=reg.ReadBool('visible');
// читаем из реестра ширину колонки
DbGrid1.Columns[i].Width:=reg.ReadInteger('width');
//закрываем ветку по колонке сетки
reg.CloseKey;
end;
end;
// удаляем из памяти объект для работы с реестром
reg.free;
end;
Вопросы для самопроверки
1. Опишите основные свойства сетки DbGrid.
2. Опишите основные свойства отдельной колонки в сетке DbGrid.
3. Как можно в программе обратиться к нужной колонке в сетке DbGrid? Как можно обратиться к текущей колонке?
4. Как в сетке DbGrid создать пустую колонку? Как для колонки сетки создать выпадающий список?
5. В каком событии сетки DbGrid выполняют раскрашивания строк или ячеек? Приведите пример раскрашивания всех ячеек строки сетки.
6. Приведите пример раскрашивания отдельной ячейки в сетке DbGrid. Как в ячейке сетки отобразить иконку из ImageList?