TDBGrid と cxGrid から sgcGrid への移行
sgcGrid は VCL 用のデータグリッド TsgcVCLGrid です。任意の TDataSet にバインドでき、グループ化、集計、フィルター、検索パネル、バンド、保存可能なレイアウトをすべてのエディションで利用できます。このキットでは、お使いの TDBGrid と cxGrid の各メンバーを sgcGrid の対応メンバーに結び付け、コンパイル済みデモのコードを示し、対応しない点も率直に挙げます。
sgcGrid は VCL 用のデータグリッド TsgcVCLGrid です。任意の TDataSet にバインドでき、グループ化、集計、フィルター、検索パネル、バンド、保存可能なレイアウトをすべてのエディションで利用できます。このキットでは、お使いの TDBGrid と cxGrid の各メンバーを sgcGrid の対応メンバーに結び付け、コンパイル済みデモのコードを示し、対応しない点も率直に挙げます。
標準の TDBGrid を使っている Delphi VCL チーム、そして DevExpress cxGrid のサブスクリプションを見直しているチームが対象です。
標準の VCL TDBGrid はデータセットを表示して編集できますが、できるのはそこまでです。フィルター行、列フィルター、グループ化、フッターやグループの集計、検索パネル、バンド、ベストフィット、レイアウトの保存と読み込みはありません。これらはどれも独自コードかサードパーティ製グリッドが必要です。sgcGrid なら、すでにあるデータセットにバインドした 1 つのコントロールですべてを利用できます。
DevExpress cxGrid (ExpressQuantumGrid) は幅広く成熟したグリッドです。主にグループ化、集計、フィルター、保存したレイアウトを備えたテーブルビューとして使っているチームなら、その範囲は完全なソースコード付きの sgcGrid で賄えます。グリッド以外にも多くを含むサブスクリプションをやめることができます。
現在のグリッドの費用です。2026-10-20 時点で、DevExpress VCL の価格表には 3 つのサブスクリプションがあり、いずれも ExpressQuantumGrid Control を含みます。最も安いのは Express QuantumPack で USD 999.99、VCL Subscription は USD 1,699.99 です。2025 年 9 月 18 日の Delphi-PRAXiS のスレッドでは、あるユーザーが cxGrid のサブスクリプションが USD 400 から USD 550 に上がったと報告し、別のメンバーは、新しい Express GridPack ライセンスはもう販売されないという DevExpress の告知を引用していました (有効なサブスクライバーは更新できます)。sgcGrid は開発者ごとのライセンスで €199 から提供され、完全なソースコードと 1 年間のアップデートが付属します。すべての sgcUI エディションにも含まれています。
TsgcVCLGrid と、DataSet、Grid、KeyField を持つ TsgcGridSource_DataSet です。データセットのイベントによって、グリッドは常に同期されます。
FieldName で対応付ける設計時の列、ルックアップフィールド、セル、行、複数行の選択、行ヘッダー、カスタム描画、Ctrl+C、グループパネル、フッターとグループの集計、フィルター行、Excel 形式の列フィルター、検索パネル、バンド、ベストフィット、JSON によるレイアウトの保存と読み込み。
データセットへの双方向編集 (WriteBack)、カーソルの同期 (SyncCursor)、挿入、削除、貼り付け、元に戻す、カードビュー (ViewStyle)、非常に大きなテーブル向けのサーバーモード。体験版には評価用として含まれます。Community ビルドには含まれません。その場合でもデモはコンパイルでき、グリッドは読み取り専用で表示されます。
以下の sgcGrid の名前はすべて製品のソースコードにあり、デモで使っているものはそのままコンパイルできます。
| TDBGrid | sgcGrid | エディション |
|---|---|---|
TDBGrid | TsgcVCLGrid (ユニット sgcGrid_VCL) | すべて |
DataSource | TsgcGridSource_DataSet: DataSet、Grid、KeyField を設定し、Active := True にします (ユニット sgcGrid_Source_DataSet) | すべて |
Columns, TColumn.FieldName | Columns、Columns[i].FieldName。設計時の列は保持され、FieldName で対応付けられます。列がない場合は AutoColumns が作成します | すべて |
Title.Caption, Width, Visible | Columns[i].Caption, Width, Visible | すべて |
TColumn.ReadOnly | Columns[i].Editable | すべて (編集は Registered) |
TColumn.PickList、ルックアップフィールドのドロップダウン | Columns[i].PickList。ルックアップフィールドでは、ソースが LookupDataSet から一覧を埋めます | すべて (値の書き込みは Registered) |
TField.DisplayFormat | Columns[i].DisplayFormat | すべて |
ReadOnly, Options dgEditing | TsgcVCLGrid.ReadOnly (既定は True) と TsgcGridSource_DataSet.WriteBack | Registered |
dgRowSelect | SelectionMode := gsmRow (指定しない場合は gsmCell) | すべて |
dgMultiSelect, SelectedRows | SelectionMode := gsmMultiRow; SelectedRows, SelectedRowCount, GetSelectedKeys, RowSelected[] | すべて |
dgIndicator | RowHeader := [grhIndicator] (grhNumbers、grhCheckBox も可) | すべて |
dgColLines, dgRowLines | GridLinesV, GridLinesH | すべて |
| 現在のレコードがグリッドに追従します | TsgcGridSource_DataSet.SyncCursor | Registered |
OnDrawColumnCell, DefaultDrawColumnCell | aDefaultDraw を使う OnCustomDrawCell。色だけを変えるなら OnGetCellStyle または FormatRules | すべて |
OnTitleClick | OnHeaderClick | すべて |
| Ctrl+C (独自コード) | 組み込み済み (Ctrl+C、Ctrl+Ins)。テキストは SelectionToText から取得されます | すべて |
| Insert キーと Ctrl+Del キー | AllowInsert, AllowDelete, InsertRow, DeleteSelectedRows, OnBeforeDelete | Registered |
cxGrid の名前は DevExpress の識別子であり、参考として示すだけです。
| cxGrid | sgcGrid | エディション |
|---|---|---|
TcxGridDBTableView, DataController.DataSource | TsgcVCLGrid と TsgcGridSource_DataSet | すべて |
TcxGridDBColumn.DataBinding.FieldName | Columns[i].FieldName | すべて |
TcxGridDBColumn.GroupIndex | Columns[i].GroupIndex; GroupBy(['Field']), ClearGrouping, GroupCount | すべて |
OptionsView.GroupByBox | ShowGroupPanel | すべて |
DataController.Groups.FullExpand, FullCollapse | ExpandAll, CollapseAll | すべて |
OptionsView.Footer | ShowFooter | すべて |
DataController.Summary.FooterSummaryItems (skSum、skCount、skAverage、skMin、skMax) | Columns[i].SummaryType (gsuSum、gsuCount、gsuAverage、gsuMin、gsuMax)、SummaryFormat。値は FooterSummary(aCol)、FooterSummaryText(aCol) から取得します。SummaryScope も参照してください | すべて |
DataController.Summary.DefaultGroupSummaryItems | GroupSummaries。グループ内では列の SummaryType を使います | すべて |
FilterRow.Visible | ShowFilterRow, Columns[i].FilterRowOperator | すべて |
| 列フィルターのドロップダウン | ShowFilterButtons, ShowFilterPopup(aCol), ClearColumnFilter(aCol), ClearColumnFilters, OnFilterChange | すべて |
FindPanel.DisplayMode | ShowFindPanel, FindText, FindNext, FindPrevious, FindOnlyMatches | すべて |
TcxGridDBBandedTableView.Bands, Column.Position.BandIndex | Bands (Caption, ParentBand, Visible), Columns[i].Band | すべて |
ApplyBestFit | BestFitColumns, BestFitColumn(aCol), BestFitOnDblClick, BestFitSampleRows | すべて |
StoreToIniFile, RestoreFromIniFile | SaveLayoutToFile、LoadLayoutFromFile (JSON)。文字列やストリームとの入出力も可能で、AutoSaveLayout と LayoutStorageKey で自動化できます | すべて |
OptionsCustomize.ColumnMoving | ColumnMoving | すべて |
| 列のカスタマイズダイアログ | ShowColumnChooser | すべて |
OnCustomDrawCell | OnCustomDrawCell | すべて |
TcxGridDBCardView (2 つ目のビュー) | 同じグリッド上の ViewStyle := gvsCard と CardOptions (CaptionField、CardWidth、CardHeight、ShowFieldCaptions) | Registered |
各コード抜粋は MigrateFromDBGrid デモからコピーしたもので、Delphi 7 と Delphi 13 (Win32 と Win64) でコンパイルできます。コメントには、置き換える TDBGrid または cxGrid のコードを記しています。
移行前: DataSource := dsProducts を設定した TDBGrid。移行後: フォーム上のソースコンポーネントです。
object SourceDB: TsgcGridSource_DataSet
DataSet = cdsProducts
Grid = GridDB
KeyField = 'ID'
Left = 280
Top = 520
end移行前: dgEditing、dgRowSelect、dgMultiSelect、dgIndicator を持つ Options。移行後:
procedure TFormMain.chkOptionsClick(Sender: TObject);
begin
// TDBGrid.ReadOnly / Options dgEditing -> ReadOnly
{$IFDEF SGC_GRID_EDIT}
GridDB.ReadOnly := not chkEditing.Checked;
{$ENDIF}
// dgMultiSelect -> gsmMultiRow, dgRowSelect -> gsmRow, neither -> gsmCell
if chkMultiSelect.Checked then
GridDB.SelectionMode := gsmMultiRow
else if chkRowSelect.Checked then
GridDB.SelectionMode := gsmRow
else
GridDB.SelectionMode := gsmCell;
// dgIndicator -> RowHeader [grhIndicator] (grhNumbers, grhCheckBox too)
if chkIndicator.Checked then
GridDB.RowHeader := [grhIndicator]
else
GridDB.RowHeader := [];
end;移行前: Column.FieldName とフィールドの値を読む OnDrawColumnCell。移行後: aCol は Columns のインデックス、aRow は Data のビュー行です (CS_LOW_STOCK はデモの定数です)。
procedure TFormMain.GridDBCustomDrawCell(Sender: TObject; aCanvas: TsgcUICanvas;
aRow, aCol, aLeft, aTop, aRight, aBottom: Integer;
aState: TsgcGridCellDrawStates; var aDefaultDraw: Boolean);
begin
// TDBGrid.OnDrawColumnCell: Column.FieldName and Field.AsInteger.
// sgcGrid: aCol is the Columns index, aRow the view row of Data. The
// background is painted already; aDefaultDraw False would skip the text
if (aRow < 0) or (aRow >= GridDB.Data.ViewCount) or
(GridDB.Columns[aCol].FieldName <> 'Qty') then
Exit;
if StrToIntDef(VarToStr(GridDB.Data.Cells[aRow, aCol]), 0) < CS_LOW_STOCK
then
begin
// a red marker at the left edge of a low stock cell
aCanvas.BeginPath;
aCanvas.Rectangle(aLeft, aTop + 4, aLeft + 4, aBottom - 4);
aCanvas.ClosePath;
aCanvas.FillPath($FFDC2626);
end;
end;移行前: TDBGrid の dgEditing、および cxGrid の GroupByBox にドラッグした列。移行後:
procedure TFormMain.FormCreate(Sender: TObject);
begin
DoCreateData;
// TDBGrid: DataSource := dsProducts. sgcGrid: a TsgcGridSource_DataSet
// with DataSet, Grid and KeyField (set on the form). The grid columns are
// designed on the form like TDBGrid.Columns, matched by FieldName
{$IFDEF SGC_GRID_EDIT}
// TDBGrid dgEditing posts edits to the dataset: WriteBack. The current
// record follows the focused row and back: SyncCursor
SourceDB.WriteBack := True;
SourceDB.SyncCursor := True;
{$ELSE}
chkEditing.Checked := False;
chkEditing.Enabled := False;
chkEditing.Caption := 'Editing (Registered edition)';
GridDB.ReadOnly := True;
{$ENDIF}
SourceDB.Active := True;
SourceCx.Active := True;
chkOptionsClick(nil);
// cxGrid: drag a column to the GroupByBox. sgcGrid: ShowGroupPanel, and
// GroupBy from code (cxGridDBColumn.GroupIndex is Columns[i].GroupIndex)
GridCx.GroupBy(['Category']);移行前: フッター集計項目、グループ化ボックス、フィルター行、検索パネル、バンド付きテーブルビュー。移行後: フォーム上の列プロパティとグリッドプロパティです。
Columns = <
item
FieldName = 'ID'
Caption = 'ID'
DataType = gdtInteger
Width = 60
SummaryType = gsuCount
Band = 0
end
item
FieldName = 'Product'
Caption = 'Product'
Width = 220
Band = 0
end
item
FieldName = 'Category'
Caption = 'Category'
Width = 140
Band = 0
end
item
FieldName = 'Price'
Caption = 'Price'
DataType = gdtFloat
Width = 110
DisplayFormat = '#,##0.00'
SummaryType = gsuAverage
SummaryFormat = '#,##0.00'
Band = 1
end
item
FieldName = 'Qty'
Caption = 'Qty'
DataType = gdtInteger
Width = 90
SummaryType = gsuSum
Band = 1
end>
FormatRules = <>
ShowFooter = True
ShowGroupPanel = True
GroupSummaries = True
ShowFilterButtons = True
ShowFilterRow = True
ShowFindPanel = True
Bands = <
item
Caption = 'Product'
end
item
Caption = 'Stock and price'
end>移行前: ApplyBestFit、StoreToIniFile、RestoreFromIniFile、TcxGridDBCardView。移行後:
procedure TFormMain.btnBestFitClick(Sender: TObject);
begin
// cxGridDBTableView.ApplyBestFit -> BestFitColumns (BestFitColumn(i) for
// one column, BestFitOnDblClick for the header divider)
GridCx.BestFitColumns;
end;
function TFormMain.DoLayoutFile: string;
begin
Result := ExtractFilePath(ParamStr(0)) + 'migratefromdbgrid_layout.json';
end;
procedure TFormMain.btnSaveLayoutClick(Sender: TObject);
begin
// cxGridDBTableView.StoreToIniFile -> SaveLayoutToFile (JSON: columns,
// widths, order, sort, grouping, filters, summaries, bands, view)
GridCx.SaveLayoutToFile(DoLayoutFile);
DoShowStatus('layout saved to ' + ExtractFileName(DoLayoutFile));
end;
procedure TFormMain.btnLoadLayoutClick(Sender: TObject);
begin
// cxGridDBTableView.RestoreFromIniFile -> LoadLayoutFromFile
if GridCx.LoadLayoutFromFile(DoLayoutFile) then
DoShowStatus('layout loaded')
else
DoShowStatus('no saved layout');
end;
procedure TFormMain.chkCardViewClick(Sender: TObject);
begin
{$IFDEF SGC_GRID_ADVANCED}
// cxGridDBCardView (a second view of the level) -> ViewStyle gvsCard of
// the same grid, CardOptions for the caption field and the card size
if chkCardView.Checked then
GridCx.ViewStyle := gvsCard
else
GridCx.ViewStyle := gvsTable;
{$ENDIF}
end;データ層はそのままです。変更するのはグリッドとそのオプションだけです。
sgcGrid のパッケージをインストールし、フォームに TsgcVCLGrid と TsgcGridSource_DataSet を配置します。
ソースの DataSet に、以前のグリッドが使っていたデータセットを設定します (グリッドに TDataSource はもう不要です)。続いて Grid と KeyField を設定します。KeyField には、インプレース更新と書き戻しに必要な一意のフィールドを指定します。
FieldName、Caption、Width、DisplayFormat、Editable を持つ Columns を追加するか、Columns を空のままにして AutoColumns にフィールドから作成させます。
dgEditing には ReadOnly と WriteBack、dgRowSelect と dgMultiSelect には SelectionMode、dgIndicator には RowHeader、現在のレコードには SyncCursor を使います。
OnDrawColumnCell のコードを OnCustomDrawCell へ移します。色を設定するだけなら OnGetCellStyle へ移します。
ShowGroupPanel、ShowFooter、GroupSummaries、ShowFilterRow、ShowFilterButtons、ShowFindPanel。集計は Columns[i].SummaryType、バンドは Bands と Columns[i].Band、レイアウトは SaveLayoutToFile へ移します。
データセットを開いたら、ソースの Active := True を設定します。
移行を計画する前にお読みください。
ViewStyle であり、レベル上の 2 つ目のビューではありません。マスター詳細は cxGrid のレベルではなく Detail (Registered エディション) を使います。SummaryType が 1 つです。1 つの列に複数の集計項目を設定することはできません。TDBGrid.SelectedField と SelectedIndex に直接対応するものはありません。SelectedCol と Columns[SelectedCol].FieldName を使ってください。カテゴリのルックアップフィールドを持つ 40 製品の TClientDataSet を、「From TDBGrid」と「From cxGrid」の 2 ページで表示します。
sgcUI のインストーラーは Demos\Grid\Delphi\MigrateFromDBGrid に配置します。内容は MigrateFromDBGrid.dpr、frmMain.pas、frmMain.dfm、readme.html です。
Delphi 7 から 13 のいずれかで MigrateFromDBGrid.dpr を開き、Win32 または Win64 でビルドして実行します。各ページには、TDBGrid または cxGrid の概念が、対応する sgcGrid の機能の隣に示されています。
MigrateFromDBGrid.exe /test は、列とオプションのマッピング、コピーしたテキスト、グループ化、フッター集計、バンド、レイアウトの往復、Registered エディションでは書き戻しとカードビューを検証し、すべてのチェックに合格すると 0 で終了します。
両方のグリッドに公平を期すために述べると、cxGrid には sgcGrid にないものがあります。たとえば 1 つのグリッドコントロール内の複数のビューとレベル、INI レイアウトがあり、他にも多数のコントロールが付属します。アプリケーションがそれらに依存している場合、移行はこのページで示したものより大きくなります。上に挙げたグリッドの機能を使っていて、それを完全なソースコード付きで、Delphi 7 から 13 に対応する単一の製品として使いたいなら、sgcGrid が進むべき道です。機能の一覧は sgcGrid の製品ページをご覧ください。