Лекция № 11

Тема: «Работа с табличными данными. Диаграммы и графики»

 

План

1. Отображение табличных данных

2. Фильтрация данных в сетке

3. Условное форматирование сетки

4. Построение диаграмм и графиков

 

1. Отображение табличных данных

Для отображения данных, которые представляют собой таблицу, но фактически не являются таблицей некоторой БД, существует специальный компонент StringGrid (Additional).

Компонент имеет следующие свойства:

 

Align

привязка сетки к краю формы

BorderStyle

отображает границу у сетки

ColCount

количество колонок в сетке

Color

цвет фона сетки

DefaultColWidth

ширина колонок по умолчанию

DefaultRowHeight

высота строк по умолчанию

FixedColor

цвет фиксированных ячеек в сетке (ячейки слева и сверху в сетке, если они есть)

FixedCols

количество фиксированных колонок

FixedRows

количество фиксированных строк

GridLineWidth

толщина линий сетки

Options

набор дополнительных параметров сетки: goFixedVertLine - отображает вертикальные линии между ячейками в фиксированных столбцах, goFixedVertLine - отображает горизонтальные линии между ячейками в фиксированных столбцах, goVertLine - отображает вертикальные линии между ячейками, goVertLine - отображает горизонтальные линии между ячейками, goRangeSelect - включает возможность выделения мышью любого диапазона ячеек, goRowSizing - позволяет изменять ширину колонок, goColSizing - позволяет изменять высоту строк, goRowMoving - позволяет изменять порядок строк в сетке, goColMoving - позволяет изменять порядок колонок в сетке, goEditing - позволяет редактировать данные в сетке, goTabs - позволяет переходить по ячейкам сетки клавишей Tab, goRowSelect - позволяет отмечать в сетке не отдельные ячейки, а всю строку целиком, goAlwaysShowEditor - позволяет всегда в активной ячейке отображать курсор ввода

RowCount

количество строк в сетке

 

Все указанные свойства можно изменять как при проектировании формы, так и в процессе выполнения программы.

 

Особенно нужно упомянуть свойство Options, которое представляет из себя множество. Для включения какого-либо значения в данном свойстве использую команду:

 

//включаем у сетки возможность редактирования

//и перехода клавишей Tab

StringGrid1.Options:=StringGrid1.Options+[goEditing, goTabs];

 

Для выключения какого-либо значения в данном свойстве использую команду:

 

//выключаем у сетки возможность редактирования

//и перехода клавишей Tab

StringGrid1.Options:=StringGrid1.Options-[goEditing, goTabs];

 

Кроме указанных свойств, которые доступны при проектировании формы, сетка имеет свойства, доступные только при написании кода:

 

Col

номер активной колонки в сетке (нумерация с 0)

Row

номер активной строки в сетке (нумерация с 0)

Cells[i,j]

позволяет обратиться к тексту указанной ячейки. Обратите внимание, что i - номер колонки, j- номер строки (нумерация с 0).

ColWidths[i]

позволяет задать ширину i-й колонки

RowHeights[i]

позволяет задать высоту i-й строки

 

Пример. Пусть имеется сетка из 7 колонок. Необходимо при старте формы задать названия колонок сетки.

В событии OnCreate формы введите код:

 

procedure TForm1.FormCreate(Sender: TObject);

begin

    //задаем ширину колонки с указанным номером

    StringGrid1.ColWidths[0]:=40;

    //задаем текст надписи в шапке таблицы (строка с номером 0)

    //первая колонка в строке также имеет номер 0

    StringGrid1.Cells[0,0]:='№ п/п';

    //аналогично для остальных ячеек первой строки   

    StringGrid1.ColWidths[1]:=100;

    StringGrid1.Cells[1,0]:='Фамилия';

    StringGrid1.ColWidths[2]:=100;

    StringGrid1.Cells[2,0]:='Имя';

    StringGrid1.ColWidths[3]:=100;

    StringGrid1.Cells[3,0]:='Отчество';

    StringGrid1.ColWidths[4]:=100;

    StringGrid1.Cells[4,0]:='Дата рожд.';

    StringGrid1.ColWidths[5]:=60;

    StringGrid1.Cells[5,0]:='Ср.балл';

    StringGrid1.ColWidths[6]:=60;

    StringGrid1.Cells[6,0]:='Стипендия';

end;

 

Другие примеры работы с указанными свойствами:

 

//для текущей ячейки задаем значение 0

StringGrid1.Cells[StringGrid1.Col, StringGrid1.Row]:='0';

//для текущей строки задаем высоту

StringGrid1.RowHeights[StringGrid1.Row]:=50;

 

Для обработки ячеек в сетке использую операторы цикла.

 

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

 

for i:=0 to StringGrid1.ColCount-1 do

    for j:=0 to StringGrid1.RowCount-1 do

        ...StringGrid1.Cells[i,j]...

 

Пример. Пусть нужно обратиться ко всем ячейкам 4 колонки.

 

for j:=0 to StringGrid1.RowCount-1 do

    ...StringGrid1.Cells[3,j]...

 

Пример. Пусть нужно обратиться ко всем ячейкам 3 строки.

 

for i:=0 to StringGrid1.ColCount-1 do

    ...StringGrid1.Cells[i,2]...

 

Если первая строка содержит фиксированные ячейки (шапку таблицы), то цикл по j нужно начинать с 1.

Если первая колонка содержит фиксированные ячейки, то цикл по i нужно начинать с 1.

 

2. Фильтрация данных в сетке

При вводе данных в сетку необходимо выполнять защиту программы от ошибок. Для этого существует два подхода:

- запрет на ввод в ячейки;

- фильтрация вводимой информации.

Запрет на ввод предполагает, что, если в сетке есть ячейки, которые нельзя изменять (например ячейки, рассчитываемые автоматически по формулам), то можно запретить выбор таких ячеек. При попытке выбора ячейки наступает событие OnSelectCell, в котором с помощью параметров ACol и ARow можно определить номер текущей колонки и строки. Параметр CanSelect разрешает (true) или запрещает (false) доступ к ячейке.

Пример. Пусть в сетке нужно запретить доступ к ячейкам в 1 и 5 колонках.

В событии сетки OnSelectCell введите код:

 

procedure TForm1.StringGrid1SelectCell(Sender: TObject; ACol,ARow: Integer; var CanSelect: Boolean);

begin

    //если колонка 1 или 5

    if (ACol=0) or (ACol=4) then

        //блокируем установку в ячейку курсора

        CanSelect:=false;

end;

 

Пример. Пусть нужно заблокировать доступ к ячейке на пересечении 3 колонки и 5 строки.

 

procedure TForm1.StringGrid1SelectCell(Sender: TObject; ACol,ARow: Integer; var CanSelect: Boolean);

begin

    //если колонка 3 и строка 5

    if (ACol=2) and (ARow=4) then

        //блокируем установку в ячейку курсора

        CanSelect:=false;

end;

 

Фильтрация информации предполагает анализ данных непосредственно при вводе.

Пример. Пусть в сетке в 6 колонке вводится размер среднего балла. При этом средний балл может находиться в диапазоне от 2 до 5. Если балл введен верно, то на его основании в 7 колонке рассчитывается размер стипендии по формуле:  средний балл * 120. Если балл не верный, то введенное значение очищается.

В событии OnSetEditText сетки введите код:

 

procedure TForm1.StringGrid1SetEditText(Sender: TObject; ACol,ARow: Integer; const Value: String);

//переменная для считывания значения из ячейки сетки

var ch:real;

begin

    //если редактируется не 6 колонка (не средний балл)

    if ACol<>5 then

        //процедура завершает свою работу   

        Exit;

 

    //пытаться выполнить код

    Try

        //конвертируем содержимое ячейки 6 колонки в число

        ch:=StrToFloat(StringGrid1.Cells[5,ARow]);

        //если конвертирование удалось и

        //полученное значение попадает в допустимый диапазон (от 2 до 5)

        if (ch>=2) and (ch<=5) then

        begin

            //считаем размер стипендии

            StringGrid1.Cells[6,ARow]:=FloatToStr(StrToFloat(StringGrid1.Cells[5,ARow])*120);

            //завершаем работу процедуры

            Exit;

        end;

    //если конвертирование не удалось (в ячейке не число)

    //ничего не делаем (пустой оператор "точка  с запятой")

    Except;

    end;

    

    //если работа процедуры не завершена (в ячейке не число или

    //оно не попадает в диапазон от 2 до 5)   

    //колонки "Средний балл" и "Стипендия" очищаются

    StringGrid1.Cells[5,ARow]:='';

    StringGrid1.Cells[6,ARow]:='';

    end;

end;

 

3. Условное форматирование сетки

Условное форматирование облегчает визуальное восприятие табличных данных. Данный подход предполагает окрашивание строк таблицы в зависимости от определенных условий. Данное форматирование выполняется в коде OnDrawColumnCell.

Для закраски ячейки цветом использую код вида:

 

//задаем цвет фона (в данном примере - белый)

StringGrid1.Canvas.Brush.Color:=clWhite;

//заливаем ячейку заданным цветом

StringGrid1.Canvas.FillRect(Rect);

 

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

 

StringGrid1.Canvas.TextOut(Rect.Left+2, Rect.TOP+2,StringGrid1.Cells[ACol,ARow]);

 

Указанная команда выводит текст с выравниванием по левому краю. Для вывода текста по центру используют команду, приведенную в примере ниже.

 

Пример. Пусть в 6 колонке сетки вводится средний балл. Если ячейка пустая - окраска белым цветом, если средний балл равен 5 - окраска зеленым цветом, 4 - окраска синим цветом, 3 - окраска желтым цветом, 2 и ниже - красным цветом.

В событии OnDrawColumnCell введите код:

 

procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState);

//метка для перехода к блоку выдачи текста в сетке

begin

 

    //если ячейка относится к фиксированной области, то конец

    if (ACol=0) or (ARow=0) then Exit;

   

    //если ячейка активная, то фон для нее салатовый

    if gdFocused in State then

        StringGrid1.Canvas.Brush.Color:=clLime;

 

    //если в 6 колонке нет данных (средний балл не введен)

    if StringGrid1.Cells[5,ARow]='' then

        //цвет фон ячеек белый

        StringGrid1.Canvas.Brush.Color:=clWhite;

    //если балл 5

    else if StrToFloat(StringGrid1.Cells[5,ARow])=5 then

        //цвет фона зеленый

        StringGrid1.Canvas.Brush.Color:=clGreen

    //если средний балл 4 и выше

    else if StrToFloat(StringGrid1.Cells[5,ARow])>=4 then

        //цвет фона синий

        StringGrid1.Canvas.Brush.Color:=clBlue

    //если средний балл 3 и выше

    else if StrToFloat(StringGrid1.Cells[5,ARow])>=3 then

        //цвет фона желтый

        StringGrid1.Canvas.Brush.Color:=clYellow

    else

        //во всех остальных случая цвет фона красный

        StringGrid1.Canvas.Brush.Color:=clRed;

 

    //заливаем строку сетки указанным фоном

    StringGrid1.Canvas.FillRect(Rect);

 

    //блок вывода текста в сетку

    //если колонки не 1, не 2 или не 3 (не ФИО)

    if (ACol<>1) or (ACol<>2) or (ACol<>3) then

        //выдаем текст по центру ячейки

        StringGrid1.Canvas.TextOut((Rect.Left+(Rect.Right-Rect.Left-Canvas.TextWidth(StringGrid1.Cells[ACol,ARow]))div 2), Rect.Top+2,StringGrid1.Cells[ACol,ARow])

    //ячейки с ФИО выдаем по левому краю

    else

        StringGrid1.Canvas.TextOut(Rect.Left+2, Rect.TOP+2,StringGrid1.Cells[ACol,ARow]);

end;

 

4. Построение диаграмм и графиков

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

Для построения диаграмм или графиков используется компонента Chart (TeeChart Std). Наиболее удобно с компонентом работать в специальном окне, которое можно вызвать двойным щелчком на компоненте.

 

 

Окно имеет две закладки:

-Chart - параметры всей диаграммы. Данная закладка имеет вложенные закладки с разными параметрами;

- Series - параметры отдельного ряда данных диаграммы.Данная закладка имеет вложенные закладки с разными параметрами;

Создание диаграммы начинается с того, что на закладке Chart - Series с помощью кнопки Add создают новый ряд данных. При этом в отдельном окне указывают тип диаграммы.

 

 

После этого для всей диаграммы можно задать свойства:

General - параметры печати диаграммы и параметры масштабирования;

Axis - параметры шкалы значений. Данная вкладка имеет свои вкладки, на которых можно задать отображение шкалы и ее размещение, текст надписи для шкалы, параметры надписей на оси и прочие визуальные эффекты;

Title - параметры заголовка диаграммы;

Legend - параметры легенды диаграммы;

Panel - параметры панелей диаграммы, если они имеет вид 3D и др. параметры.

 

Каждый ряд данных (вкладка Series) имеет такие параметры:

Format - задается цвет и тип рамки;

General - задается отображение ряда в легенде, параметры отображения осей для ряда;

Marks - задается отображение на диаграмме маркеров возле каждой точки ряда;

DataSource - задается источник данных: случайные значение или значение функции.

 

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

 

//очистка заголовка диаграммы

Chart1.Title.Text.Cler;

//задание текста заголовка диаграммы

Chart1.Title.Text.Add('Заголовок');

 

//очистка ряда от данных

Chart1.Series[i].Clear;

//добавление в ряд нового значения

//цвет указывать необязательно

Chart1.Series[i].Add(значение точки, название точки[, цвет]);

//добавить в ряд значение функции f(x) в точке x

//используется при построении графиков функций

//название точки и цвет указывать не обязательно

Chart1.Series[i].AddXY(x, f(x)[, название точки, цвет]);

//отобразить или скрыть ряд данных на диаграмме

Chart1.Series[i].Active:=true/false;

//скопировать все значения из ряда j в ряд i

Chart1.Series[i].Assign(Chart1.Series[j]);

 

Пример. На отрезке от -10 до 10 с шагом 1 построить график функции y=4x2-3.

Двойным щелчком откройте окно компонента Chart и с помощью кнопки Add добавьте новый ряд, указав ему в качестве типа диаграммы "FastLine (график)".

Пусть график строится при щелчке на кнопке. В событии OnClick кнопки напишите код:

 

procedure TForm1.Button1Click(Sender: TObject);

//переменная-аргумент функции

var x:integer;

begin

    //очищаем старый заголовок диаграммы

    Chart1.Title.Text.Clear;

    //задаем новый заголовок диаграммы

    Chart1.Title.Text.Add('График функции');

    //очищаем ряд от старых значений

    Chart1.Series[0].Clear;

 

    //в цикле меняем значение аргумента от -10 до 10

    for x:=-10 to 10 do

        //в ряд данных добавляем значение аргумента и функции в определенной точке отрезка

        Chart1.Series[0].AddXY(x,4*x*x-3);

end;

 

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

Двойным щелчком откройте окно компонента Chart и с помощью кнопки Add добавьте новый ряд, указав ему в качестве типа диаграммы "Bar".

Для кнопки в событии OnClick введите код:

 

procedure TForm1.Button1Click(Sender: TObject);

//переменная для цикла по строкам колонки

var i:integer;

begin

    //очищаем старый заголовок диаграммы

    Chart1.Title.Text.Clear;

    //задаем новый заголовок диаграммы

    Chart1.Title.Text.Add('График функции');

    //очищаем ряд от старых значений

    Chart1.Series[0].Clear;

 

    //организуем цикл по строкам сетки (начинаем с 1, т.к. 0 строка - это шапка сетки)

    for i:=1 to StringGrid1.RowCount-1 do

        //если значение в 5 колонке текущей строки не пустое

        if StringGrid1.Cells[4,i]<>'' then

            //добавляем в ряд это значение

            //в качестве названия точки используем значение из 1 колонки

            Chart1.Series[0].Add(StrToFloat(StringGrid1.Cells[4,i]),StringGrid1.Cells[1,i])

        //если значение в 5 колонке текущей строки пустое

        else

            //добавляем в ряд значение 0

            //в качестве названия точки используем значение из 1 колонки

            Chart1.Series[0].Add(0,StringGrid1.Cells[1,i]);

end;

 

Пример. Пусть на форме имеется диаграмма, отображающая данные в разных видах: Series[0] - график, Series[1 - диаграмма. На форме имеется группа переключателей RadioGroup, с помощью которой пользователь может отображать данные в нужном ему виде.

 

В событии OnClick компонента RadioGroup введите код:

 

procedure TForm1.RadioGroup1Click(Sender: TObject);

begin

    //если выбран первый ряд (график)

    case RadioGroup1.ItemIndex of

    0: begin

            //первый ряд диаграммы отображаем

            Chart1.Series[0].Active:=true;

            //второй ряд скрываем

            Chart1.Series[1].Active:=false;

       end;

    //если выбран второй ряд (диаграмма)   

    1: begin

                   //для второго ряда диаграммы загружаем данные из первого ряда

            Chart1.Series[1].Assign(Chart1.Series[0]);

            //первый ряд диаграммы скрываем

            Chart1.Series[0].Active:=false;

            //второй ряд отображаем

            Chart1.Series[1].Active:=true;

       end;

    end;

end;

 

Вопросы для самопроверки

1. Какие основные свойства имеет компонент StringGrid?

2. Как программно задать настройки свойства Options для сетки StringGrid?

3. Какие свойства сетки StringGrid доступны при написании кода?

4. Как заблокировать доступ к определенным ячейкам сетки StringGrid?

5. В каком событии сетки StringGrid можно выполнять фильтрацию вводимой информации?

6. В каком событии выполняется условное форматирование сетки StringGrid? Как залить ячейки разными цветами?

7. Для чего нужно выводить текст при условном форматировании сетки StringGrid? Как это сделать?

8. Какие основные параметры компонента Chart можно настроить в окне редактора?

9. Какие основные свойства ряда данных Chart можно настроить в окне редактора?

10. Как программно задать заголовок диаграммы Chart? Как очистить ряд с данными?

11. Какие команды существуют для добавления в ряд данных Chart нового значения?

12. Как скопировать данные из одного ряда Chart в другой? Как отобразить или скрыть ряд данных на диаграмме?