Шаг 5.
Вкладка Additional. Компонент TStringGrid

    На этом шаге мы рассмотрим компонент TStringGrid.

    Компонент TStringGrid позволяет отображать текстовые данные в ячейках, расположенных в строках и столбцах. В таблице строк находится много свойств и методов для контроля и отображения данных, так же как и для использования преимуществ их табличного расположения. Этот компонент называют таблицей строк, или просто таблицей. Несмотря на название, таблица строк способна отображать и графическую информацию. Но при этом хранение графических данных и их прорисовок реализуются программистом самостоятельно.

    Таблица делится на 2 части - фиксированную и рабочую. Фиксированная часть служит для показа заголовков колонок и рядов, а также для ручного управления их размерами. Обычно фиксированная часть занимает левую колонку и верхний ряд таблицы, однако с помощью свойств FixedCols и FixedRows можно задать другое количество фиксированных колонок и рядов (если эти свойства имеют значение 0, таблица не содержит фиксированной зоны). Рабочая часть - это остальная часть таблицы. Она может содержать произвольное количество кнопок и рядов, более того, эти величины могут изменяться программно. Рабочая часть может не умещаться целиком в пределах окна компонента, в этом случае в него автоматически помещаются нужные полосы прокрутки. При прокрутке рабочей области фиксированная область не исчезает, но меняется ее содержимое - заголовки колонок и рядов.

    Центральным свойством компонента является свойство Cells - массив ячеек, каждая из которых может содержать произвольный текст. Конкретная ячейка определяется парой чисел - номером колонки и номером ряда, на пересечении которых она находится (нумерация начинается с нуля). Свойство Cells имеет тип string, поэтому программа может легко прочитать или записать содержимое нужной ячейки. Например:

   Cells [1,1]: =  'Левая верхняя ячейка рабочей зоны';

    Количество ячеек по каждому измерению хранит пара свойств ColCount (количество колонок) и RowCount (количество рядов). Значения этих свойств и, следовательно, размеры таблицы могут меняться как на этапе разработки программы, так и в ходе ее работы, однако их значения должны быть как минимум на единицу больше соответственно значений в свойствах FixedCols и FixedRows, определяющих размеры фиксированной зоны.

    Содержимое ячеек можно редактировать. Для этого в таблице используется специализированный потомок поля с маской ввода TMaskEdit.

    Свойства компонента TStringGrid:

Таблица 1. Свойства компонента TStringGrid
Свойство Описание
Property BorderStyle: TBorderStyle Определяет рамку компонента:
  • bsNone - нет рамки;
  • bsSingle - рамка толщиной 1 пиксель.
Property Cells[ACol, ARow: integer]: string; Определяет содержимое ячейки с табличными координатами(ACol, ARow).
Property Col: LongInt; Содержит номер колонки с ячейкой, имеющей фокус ввода. (ACol, ARow).
Property ColCount: LongInt; Содержит количество колонок таблицы.
Property Cols[Index: Integer ] : TStrings; Содержит все строки колонки с индексом Index.
Property ColWidths[Index: LongInt]: Integer; Содержит ширину колонки с индексом Index.
Property DefaultColWidth: Integer; Содержит значение ширины колонки, заданной по умолчанию.
Property DefaultDrawing: Boolean; Разрешает/запрещает автоматическую прорисовку служебных элементов таблицы - фиксированной зоны, фона и прямоугольника ячейки, имеющей фокус ввода, и т.п.
Property DefaultRowHeight: Integer; Содержит значение высоты рядов, заданное по умолчанию.
Property EditorMode: Boolean; Разрешает/запрещает редактирование ячеек. Игнорируется, если свойство Options включает значение goAlwayseShowEditor или не включает значение goEditing.
Property FixedColor: TColor; Определяет цвет фиксированной зоны.
Property FixedCols: Integer; Определяет количество кнопок фиксированной зоны.
Property FixedRows: Integer; Определяет количество рядов фиксированной зоны.
Property GridHeight: Integer; Содержит значение высоты таблицы.
Property GridLineWidth: Integer; Определяет толщину линий, расчерчивающих таблицу.
Property GridWidth: Integer; Содержит значение ширины таблицы.
Property LeftCol: LongInt; Содержит номер самого левого столбца, видимого в зоне прокрутки.
Property Objects[ACol, ARow: integer]: TObject; Обеспечивает доступ к объекту, связанному с ячейкой (ACol, ARow).
Property Options: TGridOptions; Содержит параметры таблицы.
Property Row: LongInt; Содержит номер ряда ячейки, имеющей фокус ввода.
Property RowCount: LongInt; Содержит количество рядов таблицы.
Property RowHeights[ Index: LongInt]: Integer; Содержит значение высоты ряда с индексом Index.
Property Rows[Index: integer]: TStrings; Содержит все текстовые строки ряда с индексом Index.
Type TScrollStyle = (ssNone, ssHorizontal, ssVertical, ssBoth);
Property ScrollBars: TScrollStyle;
Определяет полосы прокрутки:
  • ssNone - нет полос;
  • ssHorizontal - в таблицу вставляется горизонтальная полоса;
  • ssVertical - вставляется вертикальная полоса;
  • ssBoth - вставляются обе полосы.
TGridRect = record
Case integer of
0:(left, top, right, bottom: LongInt);
1:(TopLeft, BottomRight:TGridCoord);
end;
Property Selection: TGridRect;
Определяет группу выделенных ячеек в координатах левой верхней и правой нижней ячейки (нумерация рядов и колонок идет от нуля, включая колонки и ряды фиксированной зоны). После выведения фокус ввода окажется в правой нижней ячейке.
Property TabStops[ Index: LongInt ]:Boolean; Разрешает/запрещает выбирать колонку с индексом Index при обходе ячеек с помощью клавиши . Игнорируется, если свойство Options не содержит значения goTabs
PropertyTopRow: LongInt; Содержит номер самого верхнего ряда, видимого в прокручиваемой зоне ячеек.
Property VisibleColCount: Integer; Содержит количество колонок, полностью видимых в зоне прокрутки.
Property VisibleRowCount: Integer; Содержит количество рядов, полностью видимых в зоне прокрутки.

    Для задания режима работы ячеек таблицы и их отображения во время выполнения используются значения свойства Options типа TGridOptions. Это свойство представляет собой множество и может принимать комбинации значений, приведенные ниже.

Таблица 2.Назначение элементов множества TGridOptions
Значения для свойств Options Описание
goFixedVertLine Для фиксированных элементов отображаются вертикальные разделительные линии.
goFixedHorzLine Для фиксированных элементов отображаются горизонтальные разделительные линии.
goVertLine Для прокручиваемых элементов отображаются вертикальные разделительные линии.
goHorzLine Для прокручиваемых элементов отображаются горизонтальные разделительные линии.
goRangeSelect Пользователю разрешен выбор диапазона. Игнорируется, если установлено значение true для пункта goEditing
goDrawFocusSelected Имеющие фокус ввода ячейки выделяются прямоугольной рамкой и цветом, подобно выделенным ячейкам без фокуса ввода. При отключенном пункте goDrawFocusSelected (значение False) ячейки, имеющие фокус ввода, выделяются только прямоугольной рамкой.
goRowSizing Допускается изменять высоту прокручиваемых столбцов.
goColSizing Допускается изменять ширину прокручиваемых строк.
goRowMoving Прокручиваемые строки могут перемещаться с помощью мыши.
goColMoving Прокручиваемые столбцы могут перемещаться с помощью мыши.
goEditing Пользователю разрешается редактировать данные в ячейках. При установленном пункте goEditing значение goRangeSelect не действует.
goTabs Допускается перемещение между ячейками с помощью клавиш < Tab > и .
goRowSelect Допускается выбор всей строки, если установлен этот пункт, то goAlwaysShowEditor не действует.
goAlwaysShowEditor Таблица открыта для редактирования, и клавиша не действует. Если не установлен пункт goEditing, то данная установка не действует. Также если выбран пункт goRowSelect, то goAlwaysShowEditor не действует.
goThumbTracking Данные в ячейках обновляются в процессе прокручивания таблицы. Если этот пункт не установлен, то обновление данных при прокрутке происходит после отпускания бегунка полосы прокрутки.

    Следующая программа, рабочее окно которой показано на рис.1, позволит лучше понять работу компонента TStringGrid.

    Выполним задание: создадим приложение под Windows, которое позволит подсчитать успеваемость ученика в каждой четверти (т.е. средний балл всех оценок) и годовую оценку по каждому предмету (т.е. средний балл оценок в четверти).


Рис.1.Компонент TStringGrid. Окно приложения при запуске

    Форма должна содержать следующие компоненты: TPanel, TEdit, TLabel, TBitBtn, TStringGrid.


Рис.2.Windows-окно примера при проектировании

    Необходимо создать следующие обработчики событий:

    1) Обработчик события OnCreate для компонента TForm. Этот обработчик необходим для задания значений фиксированной строки таблицы (заметим, что это событие возникает при создании окна формы, но до его появления).

    2) Обработчик события OnClick для компонента BitBtn1. Этот обработчик необходим для осуществления добавления предмета в фиксированную область.

    3) Обработчик события OnSetEditText для StringGrid1. Это событие возникает при завершении редактирования текста в ячейке. В параметре Value обработчик получает результат ввода или редактирования текста ячейки.

    4) Обработчик события OnSelectCell для StringGrid1 (это событие запрещает пользователю выделять ячейку последней строки или последнего столбца).

    Текст приложения отображается ниже:

unit Un_TABLE;
interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Grids, StdCtrls, Buttons, ExtCtrls;
type
  TForm1 = class(TForm)
    Panel1: TPanel;
    Edit1: TEdit;
    Label1: TLabel;
    BitBtn1: TBitBtn;
    BitBtn2: TBitBtn;
    StringGrid1: TStringGrid;
    procedure FormCreate(Sender: TObject);
    procedure BitBtn1Click(Sender: TObject);
    procedure StringGrid1SetEditText(Sender: TObject; ACol, ARow: Integer;
      const Value: String);
    procedure StringGrid1SelectCell(Sender: TObject; ACol, ARow: Integer;
      var CanSelect: Boolean);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  n: integer;

implementation
{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
 n:=0;  {Обнуление начального значения номера предмета}
 with StringGrid1 do
  begin

{определяем текст содержимого ячейки таблицы с координатами ACol, ARow, 
  где ACol - номер колонки, а ARow - номер строки.}
   Cells[0,0]:='предмет';
   Cells[1,0]:='1 четверть';
   Cells[2,0]:='2 четверть';
   Cells[3,0]:='3 четверть';
   Cells[4,0]:='4 четверть';
   Cells[5,0]:='годовая оценка';
   Cells[0,1]:='Средняя оценка за четверть';
  end;
end;

procedure TForm1.BitBtn1Click(Sender: TObject);
var j: byte;
begin
{проверяем введены ли данные в Edit1}
 if Edit1.Text='' then ShowMessage('вы не ввели данные!!!!!')
  else
    begin
     StringGrid1.Enabled:=True; {делаем таблицу доступной для пользователя}
     n:=n+1; {увеличиваем количество предметов}
     with StringGrid1 do
      begin
       RowCount:=RowCount+1; {увеличиваем количество строк}
       for j:=0 to 5 do 
       {перемещаем строку с данными о средней оценке за четверть 
             в последнюю строку таблицы}
        begin
         Cells[j,RowCount-1]:= Cells[j,RowCount-2];
         Cells[j,RowCount-2]:=' '; {очищаем предпоследнюю строку}
        end;
{помещаем название предмета из Edit1 в предпоследнюю строку таблицы}
       Cells[0,RowCount-2]:=Edit1.Text; 
      end;
     Edit1.Clear; {очищаем  Edit1}
    end;
   Edit1.SetFocus;
end;

procedure TForm1.StringGrid1SetEditText(Sender: TObject; ACol,
  ARow: Integer; const Value: String);
var b, c: integer; { b  - значение строки редактирования}
      j, k: byte;  { j - параметр цикла для текущего номера столбца}
      SumRow, SumCol: real;
begin
 with StringGrid1 do
  if (ARow<>RowCount-1) and (ACol<>ColCount-1) then
{если редактируется область оценок, то проверяется, верны ли введенные данные}
   begin
    if value <> ' ' then {если введенное значение не пусто}
     begin
      val(Value, b, c); {переводим в число}
      if (c<>0) or  ( not (b in [1..5])) 
                   
                 then Cells[ACol, ARow]:=' ';
{игнорируем неверно введенную оценку}
     end;
    SumRow:=0; {обнуляет сумму оценок в строке}
    k:=0;
    for j:=1 to 4 do
     if Cells[j, ARow]<>'' then 
     {если ячейка таблицы с координатами j, ARow не пустая}
      begin
       SumRow:=SumRow+ StrToInt(Cells[j,ARow]); 
       inc(k); {считаем количество не пустых значений}
      end;
     if k<>0 then SumRow:=SumRow/k;
     Cells[5,ARow]:= FormatFloat('##.##', SumRow); {отображаем годовую оценку}
     SumCol: =0; {обнуляет сумму оценок в столбце}
     k:=0;
     for j:=1 to n do
      if Cells[ACol, j]<>'' then 
        {если ячейка таблицы с координатами ACol, j не пустая}
       begin
        SumCol: = SumCol + StrToInt(Cells[ACol, j]);
        inc(k); {считаем количество не пустых значений}
       end;
     if k<>0 then SumCol: =SumCol/k;
     Cells[ACol, n+1]:= FormatFloat('##.##', SumCol); 
     {отображаем среднюю оценку за четверть в n+1 строке таблицы}
   end;
end;

procedure TForm1.StringGrid1SelectCell(Sender: TObject; ACol,
  ARow: Integer; var CanSelect: Boolean);
begin
 if (ARow=StringGrid1.RowCount-1) 
   or (ACol=StringGrid1.ColCount-1) 
          then CanSelect:=False; 
                {запрещаем выделять ячейку последней строки и последнего столбца}
end;

end.
Текст этого примера можно взять здесь.

    На следующем шаге мы рассмотрим компонент TDrawGrid.




Предыдущий шаг Содержание Следующий шаг