TStringGrid の使い方

概要

カラムをフォームデザイナで追加するには右クリックして [項目デザイナ] から "項目の追加" でカラムを追加します (単純に右クリックして [項目の追加] でも可)。

  

次に、カラムをコードで追加する方法について説明します。
VCL 版 TStringGrid では ColCount プロパティでカラムを増減できましたが、FMX 版 TStringGrid には ColCount プロパティはありません。代わりに ColumnCount プロパティがあるのですが、ReadOnly なプロパティであり、これを用いてカラムを増減させる事はできません。ではどうやってコードでカラムを追加するのかと言うと、

  // カラムを 3 つ作成
  StringGrid1.AddObject(TStringColumn.Create(StringGrid1));
  StringGrid1.AddObject(TStringColumn.Create(StringGrid1));
  StringGrid1.AddObject(TStringColumn.Create(StringGrid1));

  // カラムヘッダを設定
  StringGrid1.Columns[0].Header := 'フィールド1';
  StringGrid1.Columns[1].Header := 'フィールド2';
  StringGrid1.Columns[2].Header := 'フィールド3';

  // データは 50 行
  StringGrid1.RowCount := 50;

  // データ (1 行目)
  StringGrid1.Cells[00] := 'aaaaa';
  StringGrid1.Cells[10] := 'bbbbb';
  StringGrid1.Cells[20] := 'ccccc';

このように、カラムコントロールとして TStringColumn を AddObject() してやります。行の追加方法や、セルへのアクセス方法は VCL 版と同様です。

カラムコントロールとセルコントロール

TStringGrid のカラムは TColumn から派生した TStringColumn で構成されています。これがカラムコントロールです。

行を追加すると、カラムコントロールにセルコントロール (VCL 版 TStringGrid で言うインプレースエディタ) が生成されます。

TStringGrid のカラムコントロールである TStringColumn が生成するセルコントロールは TTextCell で、

TTextCell = class(TEdit) 

と定義されています。それならば、

procedure TForm1.Button1Click(Sender: TObject);
begin
  TEdit(StringGrid1.Columns[0].CellControlByRow(0)).TextAlign := TTextAlign.taLeading;
  TEdit(StringGrid1.Columns[1].CellControlByRow(0)).TextAlign := TTextAlign.taCenter;
  TEdit(StringGrid1.Columns[2].CellControlByRow(0)).TextAlign := TTextAlign.taTrailing;
end;

このようなコードでセルのセンタリングや右寄せができそうですが、それはうまく動作しないでしょう。何故ならば、セルコントロールは表示されている範囲のものしか生成されない...つまり、見えていないセルの TextAlign は設定できないからです。上記コードだと、グリッドの 1 行目がスクロールアウトしている場合には、セルコントロールが存在しないためにエラーが発生してしまいます。

Assigned() を用い、セルコントロールの存在確認を行ってエラーが出ないようにしてもいいのですが、一旦スクロールアウトして消滅したセルコントロールはスクロールインした際に再生成される訳で、このタイミングで TextAlign を再度設定してやらなくてはなりません...あまりにも面倒ですね。

センタリングや右寄せをしたいのであれば、独自にカラムコントロールを定義してやります。

{ TStringColumn_Center }
  TStringColumn_Center = class(FMX.Grid.TStringColumn)
  protected
    function CreateCellControl: TStyledControl; override;
  end;

 { TStringColumn_Right }
  TStringColumn_Right = class(FMX.Grid.TStringColumn)
  protected
    function CreateCellControl: TStyledControl; override;
  end;
  ...

{ TStringColumn_Center }
function TStringColumn_Center.CreateCellControl: TStyledControl;
begin
  result := inherited;
  TEdit(result).TextAlign := TTextAlign.taCenter;
end;

{ TStringColumn_Right }
function TStringColumn_Right.CreateCellControl: TStyledControl;
begin
  result := inherited;
  TEdit(result).TextAlign := TTextAlign.taTrailing;
end;

カラムの生成コードを以下のように記述します。

procedure TForm1.FormCreate(Sender: TObject);
begin
  // カラムを 3 つ作成
  StringGrid1.AddObject(TStringColumn.Create(StringGrid1));         // 左寄せ
  StringGrid1.AddObject(TStringColumn_Center.Create(StringGrid1));  // センタリング
  StringGrid1.AddObject(TStringColumn_Right.Create(StringGrid1));   // 右寄せ
 ...

標準のカラムコントロールである TStringColumn の代わりに、独自に定義したセンタリング/右寄せ用のカラムコントロールを使ってカラムを追加します。

TGrid も同じような考え方で機能拡張する事ができます。

セルコントロールを列単位で処理する

セルコントロールはカラムコントロール上に存在するので、列単位で何かやりたいのであれば、先に述べたように独自に定義したカラムコントロールを使って処理するのが簡単です。

特定の列だけ ReadOnly にするのは、カラムコントロールの ReadOnly プロパティを True に設定するだけでできます。

 // カラムを 3 つ作成
  StringGrid1.AddObject(TStringColumn.Create(StringGrid1));
  StringGrid1.AddObject(TStringColumn.Create(StringGrid1));
  StringGrid1.AddObject(TStringColumn.Create(StringGrid1));

  // カラムヘッダを設定
  StringGrid1.Columns[0].Header := 'フィールド1';
  StringGrid1.Columns[1].Header := 'フィールド2';
  StringGrid1.Columns[2].Header := 'フィールド3';

  // 2 列目を ReadOnly に
  StringGrid1.Columns[1].ReadOnly := True;

フォームデザイナでカラムを追加した場合には、カラムコントロールを選択すると、[オブジェクトインスペクタ] から ReadOnly プロパティを変更できます。

セルコントロールを行単位で処理する

セルコントロールはカラムコントロール上に存在するので、行単位で処理をする事はできません。セルコントロールを一つずつ制御する必要があります。

uses
  ..., FMX.Edit;

procedure TForm1.StringGrid1SelChanged(Sender: TObject);
var
  i: Integer;
  Control: TStyledControl;
begin
  // 10 行目をすべて ReadOnly にする
  for i:=0 to StringGrid1.ColumnCount-1 do
    begin
      Control := StringGrid1.Columns[i].CellControlByRow(9); // 10 行目
      if Assigned(Control) then
        TEdit(Control).ReadOnly := True;
    end;
end;

先に述べたように "セルコントロールは表示されている範囲のものしか生成されない" ので、Assigned を用いて必ず存在チェックを行う必要があります。

See Also:


 BACK