16番会議室「玉石混淆みんなで作るSample蔵」に寄せられたサンプル
"TStringGridの使い方例"
この発言に対し以下のコメントが寄せられています
#00523 Satobe さん RE:TStringGridの使い方例
・全体をクリアする場合,動的に行数を変える場合は,RowCountを変化させ
るしかないようです.初めに行数を調べて,どばっと確保.Rows.Addとか
やってもだめ.
・StringGridから他のGrid等に項目をドラッグするには,dmAutomaticでは
動作がおかしくて使えないので,dmManualにしてBeginDragを自分で
する必要がありますが,特別の事情がない限りEndDragを呼んではいけません.
以下に複数行の項目をTreeViewにドラッグする例を示します.
ちなみにWin32コモンコントロールのTListViewは,比較的簡単に体裁良く
表が作れるし,dmAutomaticでいけちゃうし,Clearしてから動的に行を追加
してソートするとかは簡単ですが,何かの拍子にWin95のみ罫線が表示されなく
なる(NT4ではOK)バグとか,項目クラスの造りがMS的でダサイ,一行のピッチが
小さい,OnDrawCellイベントがないから行,桁ごとに色,文字を変えられ
ない(オーナードロー出来るのか?)等,使い込んでいくと不満が出てきます.
var
MovingSubject: TAcntSubject;
{ グリッドの行数を動的に決定しつつ,各行に表示対象のオブジェクトを
割り当てる例.
まずTListにオブジェクトを入れてソートし,順序よく並べて内容を表示
}
procedure TSbjExplr.UpdateNotePane;
var
Compo: TDataComponent;
AllotNote: TAllotNote;
Slip: TSlip;
i, j: integer;
S1,S2,S3: string;
PrevV,Sum,V,DrV,CrV: Currency;
SumDebt,SumCred: Currency;
Subject: TAcntSubject;
SbjList: TList;
begin
if SelectedSubject = nil then Exit;
SbjList := TList.Create;
try
Grid1.RowCount := 3; // Clear grid;
// 前月末の残高
with Grid1.Rows[1] do begin
Objects[0] := nil;
Strings[0] := '01/01';
Strings[1] := '期首残高';
Strings[2] := '';
Strings[3] := '';
Strings[4] := '';
Sum := SelectedSubject.InitialCarryover;
PrevV := Sum;
Strings[5] := FormatCurr('0,', Sum);
end;
if ShowMonthly1.Checked then begin
// 月別集計表示 略
end else begin // データ詳細表示
// タイトル行
with Grid1.Rows[0] do begin
Objects[0] := nil;
Strings[0] := '日付';
Strings[1] := '摘要';
Strings[2] := '相手科目';
Strings[3] := '借方';
Strings[4] := '貸方';
Strings[5] := '残高';
end;
// OnDrawCellの時に参照する非表示ラベルに書式をセット
TLabel(LBPanel.Controls[ColNum+1]).Alignment := taLeftJustify;
TLabel(LBPanel.Controls[ColNum+2]).Alignment := taLeftJustify;
// データを集めてStringListに取り込み
for i := 0 to SelectedSubject.DataCount-1 do begin
Compo := SelectedSubject.Datas[i];
// 通年データ表示
if Compo is TAllotNote then begin
// 仕訳データの取り込み
AllotNote := TAllotNote(Compo);
Slip := AllotNote.Slip;
// 作りかけは表示しない
if (Slip = nil)or(Slip.Owner = nil) then
Continue;
end;
SbjList.Add(Compo);
end;
// 日付順に項目をソート
SelectedSubjectTemp := SelectedSubject;
SbjList.Sort(ListSort1); // sort by date
SumDebt := 0;
SumCred := 0;
Grid1.RowCount := SbjList.Count + 3;
for i := 0 to SbjList.Count-1 do begin
Subject := SbjList.Items[i];
with Grid1.Rows[i+2] do begin
if Subject <> nil then begin
Objects[0] := Subject;
V := Subject.Value - Subject.InitialCarryover;
DrV := Subject.DrValue;
CrV := Subject.CrValue;
if Subject is TAllotNote then begin // 仕訳データ
Strings[0] := FormatDateTime('mm/dd', Subject.Date);
Slip := TAllotNote(Subject).Slip;
Strings[1] := Slip.Summary;
// 相手科目
S3 := '';
for j := 0 to Slip.NoteCount-1 do begin
if (Slip.Notes[j].Subject <> SelectedSubject)and
(Slip.Notes[j].DrCr <> TAllotNote(Subject).DrCr) then
begin
if Length(S3) > 0 then S3 := S3 + ' /';
S3 := S3 + Slip.Notes[j].Subject.SubjectName;
end;
end;
Strings[2] := S3;
if Subject.DrCr = dcDebtor then begin
S1 := FormatCurr('0,', DrV);
S2 := '';
SumDebt := SumDebt + DrV;
end else begin
S1 := '';
S2 := FormatCurr('0,', CrV );
SumCred := SumCred + CrV;
end;
end else begin // 子科目
Strings[0] := '子科目';
Strings[1] := Subject.SubjectName;
Strings[2] := '残高 : '
+ FormatCurr('0,',Subject.Value);
S1 := FormatCurr('0,', DrV);
SumDebt := SumDebt + DrV;
S2 := FormatCurr('0,', CrV );
SumCred := SumCred + CrV;
end;
Strings[3] := S1;
Strings[4] := S2;
if Subject.DrCr = SelectedSubject.DrCr then begin
Sum := Sum + V;
end else begin
Sum := Sum - V;
end;
end;
Strings[5] := FormatCurr('0,', Sum );
end;
end;
with Grid1.Rows[Grid1.RowCount-1] do begin
Sum := SelectedSubject.Value;
Objects[0] := nil;
Strings[0] := '12/31';
Strings[1] := '年間合計';
Strings[2] := '残高欄は増減を示す';
Strings[3] := FormatCurr('0,',SumDebt);
Strings[4] := FormatCurr('0,',SumCred);
V := Sum - SelectedSubject.InitialCarryover;
if V > 0 then S1 := '+'
else S1 := '';
Strings[5] := S1 + FormatCurr('0,', V);
end;
end;
finally
SbjList.Free;
end;
end;
// Gridからドラッグ開始
procedure TSbjExplr.Grid1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if Button = mbLeft then
Grid1.BeginDrag(False);
end;
procedure TSbjExplr.Grid1StartDrag(Sender: TObject;
var DragObject: TDragObject);
begin
MovingSubject := TAcntSubject(Grid1.Rows[Grid1.Selection.Top].Objects[0]);
end;
// 以下ドロップを受ける側
procedure TSbjExplr.TreeView1DragOver(Sender, Source: TObject; X,
Y: Integer; State: TDragState; var Accept: Boolean);
begin
Accept := False;
if (Source = Grid1)or(Source = Sender) then begin
if (MovingSubject <> nil) then begin
Accept := True;
end;
end;
end;
procedure TSbjExplr.TreeView1DragDrop(Sender, Source: TObject; X,
Y: Integer);
var
TargetSubject: TAcntSubject;
SrcSub: TAcntSubject;
i: integer;
begin
if Source = Grid1 then begin
TargetSubject := TAcntSubject(TreeView1.DropTarget.Data);
if (MovingSubject <> nil)
then begin
if (TargetSubject = MovingSubject) then begin
raise Exception.Create('受け側と送り側の科目が同じです');
end else if TargetSubject.IsOwnedBy(MovingSubject) then begin
raise Exception.Create('科目の親子関係は逆転できません');
end else begin
for i := Grid1.Selection.Top to Grid1.Selection.Bottom do begin
SrcSub := TAcntSubject(Grid1.Rows[i].Objects[0]);
if SrcSub <> nil then begin
SrcSub.Owner.RemoveComponent(SrcSub); // 親の差し替え
TargetSubject.InsertComponent(SrcSub);
end;
end;
UpdateSubjectPane; // TreeView,Gridの再描画
end;
end;
end else if Source = Sender then begin
// 以下略
end;
MovingSubject := nil;
end;
// Gridへの自力描画,書式設定はチューニング用の非表示コンポから拾ってくる
procedure TSbjExplr.Grid1DrawCell(Sender: TObject; Col, Row: Integer;
Rect: TRect; State: TGridDrawState);
var
GrC: TCanvas;
Grid: TStringGrid;
Algn: TAlignment;
S: string;
begin
Grid := TStringGrid(Sender);
GrC := Grid.Canvas;
if Row = 0 then begin
S := Grid.Cells[Col, Row];
Algn := TLabel(LBPanel.Controls[Col]).Alignment;
end else if Row = 1 then begin
if Grid.Row <> Row then begin
Grc.Brush.Assign(Shape1.Brush); //非表示Shapeから色を取ってくる
Grc.FillRect(Rect);
end;
S := Grid.Cells[Col, Row]; // ↓非表示Labelから書式を取ってくる
Algn := TLabel(LBPanel.Controls[Col + ColNum]).Alignment;
end else if Row = Grid.RowCount-1 then begin
if Grid.Row <> Row then begin
Grc.Brush.Assign(Shape2.Brush);
Grc.FillRect(Rect);
end;
S := Grid.Cells[Col, Row];
Algn := TLabel(LBPanel.Controls[Col + ColNum]).Alignment;
end else begin // 中間行
S := Grid.Cells[Col, Row];
Algn := TLabel(LBPanel.Controls[Col + ColNum]).Alignment;
end;
DrawString( S, GrC, Rect, Algn);
end;
// 右寄せ,センタリング表示も可能.CanvasのClipRectを事前に設定しておく
procedure DrawString( const S: string;
Canvas: TCanvas;
Rect: TRect;
Alignment:TAlignment);
var FontHeight: integer;
DrRect: TRect;
const
Alignments: array[TAlignment] of Word = (DT_LEFT, DT_RIGHT, DT_CENTER);
begin
FontHeight := Canvas.TextHeight('W');
with DrRect do begin
Left := Rect.Left+2;
Right := Rect.Right-2;
Top := ((Rect.Bottom + Rect.Top) - FontHeight) div 2;
Bottom := Top + FontHeight;
end;
Canvas.FillRect(Rect);
DrawText(Canvas.Handle, PChar(S), -1, DrRect, (DT_EXPANDTABS or
DT_VCENTER) or Alignments[Alignment]);
end;
TN(CQJ01721)
Original document by TN 氏 ID:(CQJ01721)
ここにあるドキュメントは NIFTY SERVEの Delphi Users' Forum の16番会議室「玉石混淆みんなで作るSample蔵」に投稿されたサンプルです。これらのサンプルはボーランド株式会社がサポートする公式のものではありません。また、必ずしも動作が検証されているものではありません。これらのサンプルを使用したことに起因するいかなる損害も投稿者、およびフォーラムスタッフはその責めを負いません。使用者のリスクの範疇でご使用下さい。
Copyright 1996-2002 Delphi Users' Forum
|