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는 이 모든 기능을 하나의 컨트롤로 제공하며, 이미 사용 중인 데이터셋에 바인딩됩니다.
DevExpress cxGrid(ExpressQuantumGrid)는 폭넓고 성숙한 그리드입니다. 주로 그룹화, 요약, 필터링, 저장된 레이아웃을 갖춘 테이블 뷰로 사용하는 팀은 전체 소스 코드가 포함된 sgcGrid로 이 범위를 충분히 처리할 수 있으며, 그리드보다 훨씬 많은 범위를 포함하는 구독을 정리할 수 있습니다.
현재 그리드에 드는 비용: 2026-10-20 기준 DevExpress VCL 가격표에는 세 가지 구독이 있었고, 모두 ExpressQuantumGrid 컨트롤을 포함합니다. 가장 저렴한 것은 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와 TsgcGridSource_DataSet에 DataSet, Grid, KeyField를 지정합니다. 데이터셋 이벤트가 그리드를 동기화 상태로 유지합니다.
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(두 번째 뷰) | 같은 그리드에서 ViewStyle := gvsCard, CardOptions(CaptionField, CardWidth, CardHeight, ShowFieldCaptions) | Registered |
각 발췌 코드는 Delphi 7과 Delphi 13(Win32 및 Win64)에서 컴파일되는 MigrateFromDBGrid 데모에서 복사한 것입니다. 주석에는 대체하는 TDBGrid 또는 cxGrid 코드가 표시되어 있습니다.
변경 전: TDBGrid와 DataSource := dsProducts. 변경 후: 폼의 소스 컴포넌트.
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를 설정합니다.
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이며, 마스터 디테일은 cxGrid 레벨이 아니라 Detail입니다(Registered 에디션).SummaryType입니다. 한 열에 여러 요약 항목을 두는 것은 지원되지 않습니다.TDBGrid.SelectedField와 SelectedIndex에는 직접 대응하는 항목이 없습니다. SelectedCol와 Columns[SelectedCol].FieldName를 사용하세요.40개 제품이 담긴 하나의 TClientDataSet과 Category 조회 필드를 "TDBGrid에서"와 "cxGrid에서" 두 페이지에 표시합니다.
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에 없는 기능이 있습니다. 하나의 그리드 컨트롤에서 여러 뷰와 레벨을 사용하는 것, INI 레이아웃, 그리고 다른 대규모 컨트롤 모음이 그것입니다. 애플리케이션이 이런 기능에 의존한다면 이동 작업은 이 페이지에 나온 것보다 커집니다. 위에 나열한 그리드 기능을 사용하고 있고, 전체 소스 코드와 함께 Delphi 7~13에서 단일 제품으로 쓰고 싶다면 sgcGrid가 알맞은 선택입니다. 전체 기능 목록은 sgcGrid 제품 페이지를 참조하세요.