DBGrid 동일값 셀병합
개발을 하다보면, DBGrid 콤포넌트의 기능이 약해서,
제3자 Grid 콤포넌트를 많이 사용하게 된다.
그런데, 그 덩치큰 삼자 Grid 콤포넌트의 전체 기능이 필요한 것이 아니고,
한두가지 기능만 필요한 경우가 많다.
더우기, 퀀텀그리드 같은 경우는 전체 레코드를 메모리에 로딩하기 때문에,
필요한 한두가지 기능때문에 쓰기는 참 사치스럽기까지 하다.
속도향상을 위해 메모리테이블을 써야 되는 경우도 있는데,
퀀텀에서 또 내부적으로 메모리테이블을 사용하므로
이런 경우 이중으로 메모리를 낭비하는 셈이 된다.
물론, 요즘 일반적 컴 사양에서 별무리가 아니라 하더라도,
한두가지 기능때문에 이런 식으로 퀀텀을 쓰기에는
소 잡는 칼로 닭 잡는 수가 될 수도 있다는 얘기다.
이 예제는, 인접하는 칼럼의 값이 같을 경우에,
이를 Merge하는 기능을 가진 그리드를 임포스터 방식으로 만든 것이다.
퀀텀 그리드의 경우 칼럼 머지 기능이라고 하는 것 같다.
혹은 그룹칼럼 머지 기능이라고도 하는 것 같다.
어떻게 동작하는지는 첨부한 예제를 실행해보면 알것이다.
예제를 실행하면, 이전 이후 레코드의 Category필드의 값이 같은 경우,
이를 병합해서 표시할 것이다.
주의) 컴파일할려면 kbmMemTable이 필요합니다.
물론 소스를 수정하면 다른 메모리테이블이나 리스트같은 걸 사용해도 가능합니다.
// 가져다 쓰는 폼의 소스
unit mainf;
interface
uses
..., dbgridext;
type
TDbGrid = class(TGroupDbGrid);
TForm1 = class(TForm)
Grid: TDBGrid;
....
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
// 그룹으로 보야줄 필드명
Grid.GroupFieldName:= 'Category';
// 라인은 깜박임을 줄이기 위해 내부에서 직접 그려준다.
// 오브젝트 인스펙터에서 설정해도 됨
// 임포스터 클래스에서 설정하면 오브젝트인스펙터 설정값이 우선함
Grid.Options:= Grid.Options - [dgColLines, dgRowLines];
end;
end.
// 그루핑디비그리드 임포스터 클래스
// 내부적으로 메모리 테이블을 사용한다.
unit
dbgridext;
interface
uses
Windows, Messages, Classes, SysUtils, Types, Variants, Graphics, Db, Grids, DBGrids, KBMMemTable;
type
TGroupDbGrid = class(TDbGrid)
private
FPaintCol, FPaintRow: Integer;
FGroupFieldName: String;
FDrawTable: TKbmMemtable;
procedure WMMouseWheel(var Message: TMessage); message WM_MOUSEWHEEL;
protected
procedure DrawCell(ACol, ARow: Integer; ARect: TRect; AState: TGridDrawState); override;
procedure DrawColumnCell(const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState); override; procedure Scroll(Distance: Integer); override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
property PaintCol: Integer read FPaintCol;
property PaintRow: Integer read FPaintRow;
property GroupFieldName: string read FGroupFieldName write FGroupFieldName;
end;
implementation
constructor TGroupDbGrid.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
inherited DefaultDrawing := False;
FPaintCol:= -1;
FPaintRow:= -1;
FDrawTable := TkbmMemTable.Create(Self);
with FDrawTable do
begin
FieldDefs.Add('Col', ftInteger);
FieldDefs.Add('Row', ftInteger);
FieldDefs.Add('Text', ftString, 30);
CreateTable;
Active := True;
end;
end;
destructor TGroupDbGrid.Destroy;
begin
// FDrawTable.Free;
// FDrawTable:= nil;
inherited Destroy;
end;
procedure TGroupDbGrid.DrawCell(ACol, ARow: Longint; ARect: TRect; AState: TGridDrawState);
begin
FPaintCol:= ACol;
FPaintRow:= ARow;
inherited DrawCell(ACol, ARow, ARect, AState);
if (gdFixed in AState) then
begin
DrawEdge(Canvas.Handle, ARect, BDR_RAISEDINNER, BF_BOTTOMRIGHT);
DrawEdge(Canvas.Handle, ARect, BDR_RAISEDINNER, BF_TOPLEFT);
end;
end;
procedure TGroupDbGrid.DrawColumnCell(const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState);
var
R: TRect;
i: Integer;
b: Boolean;
X, Y: Integer;
begin
if (gdFixed in State) then Exit;
R:= Rect;
if AnsiCompareText(Column.FieldName, FGroupFieldName) <> 0 then
begin
x:= 2; y:= 2;
Canvas.TextRect(R, R.Left + x, R.Top + y, Column.Field.DisplayText);
R.Bottom:= R.Bottom - 1;
R.Right:= R.Right - 1;
Canvas.Pen.Color:= clSilver;
Canvas.MoveTo(R.Right, R.Top);
Canvas.LineTo(R.Right, R.Bottom);
Canvas.LineTo(R.Left, R.Bottom);
Exit;
end;
Canvas.Brush.Color := Color;
Canvas.Font.Color := Column.Font.Color; Canvas.FillRect(R);
with FDrawTable do if Locate('Col;Row', VarArrayOf([PaintCol, PaintRow]), []) then
begin
Edit;
FieldByName('Text').AsString:= Column.Field.AsString;
Post;
end
else
begin
Insert;
FieldByName('Col').AsInteger:= PaintCol;
FieldByName('Row').AsInteger:= PaintRow;
FieldByName('Text').AsString:= Column.Field.AsString;
Post;
end;
i:= 0;
b:= True;
if PaintRow > 0 then while b do
begin
Inc(i);
b:= FDrawTable.Locate('Col;Row', VarArrayOf([PaintCol, PaintRow - i]), []) and
(Column.Field.AsString = FDrawTable.FieldByName('Text').AsString);
end;
R.Top:= R.Top - ((R.Bottom - R.Top) * (i - 1));
x:= R.Left + 2; y:= R.Top + ((R.Bottom - R.Top - Canvas.TextHeight('W')) div 2);
Canvas.TextRect(R, x, y, Column.Field.DisplayText);
R.Bottom:= R.Bottom - 1;
R.Right:= R.Right - 1;
Canvas.Pen.Color:= clSilver;
Canvas.MoveTo(R.Right, R.Top);
Canvas.LineTo(R.Right, R.Bottom);
Canvas.LineTo(R.Left, R.Bottom);
end;
procedure TGroupDbGrid.Scroll(Distance: Integer);
begin
inherited;
Invalidate;
end;
procedure TGroupDbGrid.WMMouseWheel(var Message: TMessage);
var
i: SmallInt;
begin
i := HiWord(Message.wParam); if i > 0 then
Perform(WM_KeyDown, VK_UP, 0) else
Perform(WM_KeyDown, VK_DOWN, 0);
end;
end.
'Delphi Tip > 그리드' 카테고리의 다른 글
퀀텀 그리드 컬럼 동적 생성 (0) | 2024.05.03 |
---|---|
StringGrid Row색칠/정렬 하기 (0) | 2024.04.15 |
델파이 퀀텀 그리드 헤더 색깔 변경 (0) | 2021.09.24 |
StringGrid 팁 (0) | 2021.09.23 |
델파이 퀀텀그리드 출력 리스트 읽기 (0) | 2021.09.17 |
댓글