Лекция № 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?