StringGrid Enterキーでセル移動(横・縦)

StringGridのOptionsプロパティの goEditing=Trueにしたとき
StringGridのColorプロパティをclWindow以外の色にすれば編集状態時にセル位置が見やすくなります
[Shift+Enter]で逆方向に移動するようにしたものです。
//StringGridのOnKeyDownイベント
procedure TForm1.StringGrid1KeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
if Key=VK_RETURN then begin
with TStringGrid(Sender) do begin
if SpBtnRight.Down then
//------------------------------------- {[→]横移動}
if Shift=[ssShift] then begin {Shift+Enter 左移動}
if Col > FixedCols then
Col:=Col-1
else
if Row > FixedRows then begin
Col:=ColCount-1;
Row:=Row-1;
end else begin
Col:=ColCount-1;
Row:=RowCount-1;
end
end
else begin {Enter 右移動}
if Col < ColCount-1 then
Col:=Col+1
else
if Row < RowCount-1 then begin
Col:=FixedCols;
Row:=Row+1;
end else begin
Col:=FixedCols;
Row:=FixedRows;
end;
end
else
//------------------------------------- [↓]縦移動
if Shift=[ssShift] then begin {Shift+Enter 上移動}
if Row > FixedRows then
Row:=Row-1
else
if Col > FixedCols then begin
Row:=RowCount-1;
Col:=Col-1;
end else begin
Col:=ColCount-1;
Row:=RowCount-1;
end
end
else
begin {Enter 下移動}
if Row < RowCount-1 then
Row:=Row+1
else
if Col < ColCount-1 then begin
Col:= Col +1;
Row:=FixedRows;
end else begin
Col:=FixedCols;
Row:=FixedRows;
end;
end;
end;{with}
end;
end;
StringGridで右寄せ表示・書式設定
//StringGridのOnDrawCellイベント
procedure TForm1.StringGrid1DrawCell(Sender: TObject;
ACol, ARow: Longint;
Rect: TRect; State: TGridDrawState);
begin
StringGrid1.Canvas.FillRect(Rect);
Rect.Top := Rect.Top + 2;
DrawText(StringGrid1.Canvas.Handle,
PChar(StringGrid1.Cells[ACol,ARow]),
Length(StringGrid1.Cells[ACol,ARow]),
Rect, DT_RIGHT); // DT_RIGHT=右寄せ
end;
// 応用編
procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol,
ARow: Integer; Rect: TRect; State: TGridDrawState);
var
SGrid :TStringGrid;
S :String;
DTdraw :Integer;
begin
SGrid:=TStringGrid(Sender);
if (ARow>0)and(ACol=6) then
SGrid.Canvas.Brush.Color:=$00DAFECF; {7列目の背景色を変更}
SGrid.Canvas.FillRect(Rect);
Rect.Left:= Rect.Left + 3;
S:=SGrid.Cells[Acol,Arow];
if (ARow=0) then DTdraw:=DT_CENTER else {1行目は、中央揃え}
case ACol of
0,4:DTdraw:=DT_CENTER; {1,5列目は、中央揃え}
1,3:DTdraw:=DT_RIGHT; {2,4列目は、右揃え}
5,6:begin {6,7列目は、右揃えで桁区切り}
DTdraw:=DT_RIGHT;
S:=FormatFloat('#,###',StrToFloatDef(S,0));{表示のみ変更}
end
else DTdraw:=DT_LEFT; {その他は、左揃え}
end;
DrawText(SGrid.Canvas.Handle,
PChar(S),
Length(S),
Rect, DTdraw or DT_VCENTER or DT_SINGLELINE);{縦は中央揃え}
end;StringGrid 行を削除する
procedure GridLineDel(var SGrid:TStringGrid; DeleteFix:Boolean=True);
var
ACol,ARow: Integer;
begin
with SGrid do begin
//1行全てを削除して行を繰上げる
if DeleteFix then begin
for ARow:= Row to RowCount -1 do
Rows[ARow].Assign(Rows[ARow+1]);
Rows[RowCount -1].Clear; //最終行
// if RowCount-1 > FixedRows then RowCount:=RowCount-1; //表の最終行を減らす場合
end else
//FixedCellを残して削除する
begin
for ARow:= Row to RowCount -1 do
for ACol:= FixedCols to ColCount -1 do
Cells[ACol,ARow]:=Cells[ACol,ARow +1];
for ACol:= FixedCols to ColCount -1 do //最終行
Cells[ACol,RowCount -1]:='';
end;
end;
end;
呼出しはPopUpMenuとかでするのがよいでしょう。 以下の例では、選択範囲の行を削除しています。
var ARow:Integer;
begin
with StringGrid1 do begin
for ARow:=1 to Selection.Bottom-Selection.Top+1 do
// GridLineDel(StringGrid1); //1行全てを削除して行を繰上げる場合
GridLineDel(StringGrid1,False);//FixedCellを残して現在行を削除する
Selection:= TGridRect(Rect( Col,Row,Col,Row)); //選択解除
end;
end;
StringGrid 行を挿入する
procedure GridLineIns(var SGrid:TStringGrid; InsertFix:Boolean=True);
var
ACol,ARow :Integer;
begin
with SGrid do begin
//1行挿入
if InsertFix then begin
// RowCount:=RowCount+1; //行を増やす場合
if Row < RowCount-1 then
for ARow:=RowCount-1 downto Row+1 do
Rows[ARow].Assign(Rows[ARow-1]);
Rows[Row].Clear;
end else
//FixedCellは残す
begin
if Row < RowCount-1 then
for ARow:=RowCount-1 downto Row+1 do
for ACol:=FixedCols to ColCount-1 do
Cells[ACol,ARow]:=(Cells[ACol,ARow-1]);
for ACol:=FixedCols to ColCount-1 do
Cells[ACol,Row]:='';
end;
end;
end;
以下の例では、選択範囲の行数分を挿入しています。
var ARow:Integer;
begin
with StringGrid1 do begin
for ARow:=1 to Selection.Bottom-Selection.Top+1 do
// GridLineIns(StringGrid1); //1行挿入
GridLineIns(StringGrid1,False); //FixedCellを残して行を挿入する
Selection:= TGridRect(Rect( Col,Row,Col,Row));
end;
end;
StringGridで特定のセルを編集可・不可にする
//StringGridのOnSelectCellイベント
procedure TForm1.StringGrid1SelectCell(Sender: TObject;
ACol, ARow: Integer; var CanSelect: Boolean);
begin
with TStringGrid(Sender) do begin
if ACol = 2 {1列目のAColは0}
then Options := Options - [goEditing] {3列目を編集不可}
else Options := Options + [goEditing]; {編集可}
end;
end;
(注)編集可にすると、複数セルの選択ができなくなります。
StringGridですべての列幅を自動調整する
procedure SGridAutoFit(SGrid: TStringGrid);
var
ARow, ACol, tmpColWidth, maxColWidth: Integer;
begin
for ACol := 0 to SGrid.ColCount-1 do begin
maxColWidth := SGrid.DefaultColWidth;
for ARow := 0 to SGrid.RowCount-1 do begin
tmpColWidth := SGrid.Canvas.TextWidth(SGrid.Cells[ACol,ARow]);
if tmpColWidth > maxColWidth then maxColWidth := tmpColWidth;
end;
SGrid.ColWidths[ACol] := maxColWidth + 10;
end;
end;
StringGridでソートする (複数キーに対応)
GridSort(対象StringGrid, キー列, [true=数値 False=文字列]);
複数キーで、ソートする場合は、下位キーから順番に実行して下さい。
例: GridSort(StringGrid1, 2); 3列目文字キー
GridSort(StringGrid1, 0, True); 1列目数値キー
数値を文字列キーにする場合は、桁あわせ(0で埋める)が必要ですが、
StringGrid1.Cells[1,1]:=IntToStr(数値) X
StringGrid1.Cells[1,1]:= FormatFloat('000',数値) O
第3引数をTrueにすれば実数でソートします
procedure GridSort(SGrid:TStringGrid; ACol:Integer; KeyIsNum:Boolean=False);
procedure MergeSort(Buffer: TStringList; ARow, Count: Integer);
var I, J, Center : Integer;
Temp: TStringList;
Hikaku: Boolean;
begin
if Count = 1 then Exit;
Center := Count div 2;
MergeSort(Buffer, ARow, Center);
MergeSort(Buffer, ARow + Center, Count - Center);
I:=0; J:=0;
Temp := TStringList.Create;
try
while (I < Center) and (J < Count - Center) do begin
if KeyIsNum then
Hikaku:=( StrToFloatDef(Buffer[ARow+I],0) > StrToFloatDef(Buffer[ARow+Center+J],0) )
else
Hikaku:=( CompareStr(Buffer[ARow+I],Buffer[ARow+Center+J]) >0 );
if Hikaku then begin
Temp.AddObject(Buffer[ARow + Center + J], Buffer.Objects[ARow + Center + J]);
Inc(J);
end else begin
Temp.AddObject(Buffer[ARow + I], Buffer.Objects[ARow + I]);
Inc(I);
end;
end;
if I = Center then
while J < Count - Center do begin
Temp.AddObject(Buffer[ARow + Center + J], Buffer.Objects[ARow + Center + J]);
Inc(J);
end
else
while I < Center do begin
Temp.AddObject(Buffer[ARow + I], Buffer.Objects[ARow + I]);
Inc(I);
end;
for I:=0 to Count-1 do begin
Buffer[ARow + I] := Temp[I];
Buffer.Objects[ARow + I] := Temp.Objects[I];
end;
finally
Temp.Free;
end;
end;
var
ARow: Integer;
Buffer: TStringList;
begin
with SGrid do begin
Buffer := TStringList.Create;
try //Buffer に key とそれに対応する Rows を格納する
for ARow:=FixedRows to RowCount-1 do begin
Buffer.AddObject(Cells[ACol, ARow], TStringList.Create);
TStringList(Buffer.Objects[ARow - FixedRows]).Assign(Rows[ARow]);
end;
//Buffer を実際にソートする
MergeSort(Buffer, 0, RowCount - FixedRows); //Buffer.Sort; と置き換え
//ソートしたデータを Grid に書き戻す
for ARow := FixedRows to RowCount - 1 do begin
Rows[ARow].Assign(TStringList(Buffer.Objects[ARow - FixedRows]));
TStringList(Buffer.Objects[ARow - FixedRows]).Free;
end;
finally
Buffer.Free;
end;
end;
end;
StringGridのデータをExcelに書き出す
usesに ComObj を追加して下さい。
procedure ExportToExcel(SGrid:TStringGrid);
var
MsExcel : Variant;
MsApplication: Variant;
WBook : Variant;
WSheet : Variant;
iCol,iRow : integer;
function columnToA1(clm:Integer) :string ;
begin // カラム数 ==> A1参照形式へ変換
if (clm-1) div 26 > 0 then
Result:=Chr(64+ (clm-1) div 26)
else
Result:='';
Result:=Result+ chr(65 + (clm-1) mod 26);
end;
begin
//Excel起動
MsExcel := CreateOleObject('Excel.Application');
MsApplication := MsExcel.Application;
MsApplication.Visible := True;
WBook := MsApplication.WorkBooks.Add ;
WSheet :=WBook.ActiveSheet;
//Excelにデータ出力
WSheet.Rows[1].Font.Bold:= 'True'; //タイトル行を太字にする
for iRow:=0 to SGrid.RowCount-1 do begin
for iCol:=0 to SGrid.ColCount-1 do begin
WSheet.Cells[iRow+1,iCol+1].Value:=SGrid.Cells[iCol,iRow];
end;
end;
WSheet.Columns['A:'+columnToA1(SGrid.ColCount)].AutoFit; //列幅自動調整
end;
StringGridのデータをFILEに書き出す
テキストの区切りにTABを使用
procedure GridSave(SGrid:TStringGrid; fName: String);
var stList :TStringList;
ARow,ACol :Integer;
S :String;
begin
stList:=TStringList.Create;
try
for ARow:=0 to SGrid.RowCount-1 do begin
S:= '';
for ACol:=0 to SGrid.ColCount-1 do
S:= S + SGrid.Cells[ACol,ARow]+ Chr(VK_TAB);
stList.Add (S);
end;
stList.SaveToFile(fName);
// stList.SaveToFile(fName,TEncoding.Unicode); //Delphi2009
finally
stList.Free;
end;
end;
//SaveDialogでの使用例
procedure TForm1.Button1Click(Sender: TObject);
begin
SaveDialog1.DefaultExt:='TXT';
SaveDialog1.Filter:= 'Text files (*.txt)|*.TXT';
if SaveDialog1.Execute then
GridSave(StringGrid1,SaveDialog1.FileName);
end;
テキストの区切りに','を使用(CSV)
procedure GridSaveCSV(SGrid:TStringGrid; fName: String);
var stList :TStringList;
ARow :Integer;
begin
stList:=TStringList.Create;
try
for ARow:=0 to SGrid.RowCount-1 do
stList.Add(SGrid.Rows[ARow].CommaText);
stList.SaveToFile(fName);
// stList.SaveToFile(fName,TEncoding.Unicode); //Delphi2009
finally
stList.Free;
end;
end;
//SaveDialogでの使用例
procedure TForm1.Button1Click(Sender: TObject);
begin
SaveDialog1.DefaultExt:='CSV';
SaveDialog1.Filter:= 'CSV files (*.csv)|*.CSV';
if SaveDialog1.Execute then
GridSaveCSV(StringGrid1,SaveDialog1.FileName);
end;
StringGridのデータをFILEから読込む
TABで区切ったtextFileの読込み
procedure GridLoad(SGrid:TStringGrid; fName:string);
var stList: TStringList;
ARow,ACol: Integer;
tmpS: string;
FldSeparator: Char;
begin
stList:=TStringList.Create;
try
FldSeparator:= Char(VK_TAB);
stList.LoadFromFile(fName);
SGrid.RowCount:= stList.Count;
SGrid.ColCount:= SGrid.FixedCols;
for ARow:=0 to stList.Count-1 do begin
ACol:= 0;
tmpS:= stList[ARow];
while Pos(FldSeparator,tmpS) > 0 do begin
if ACol > SGrid.ColCount-1 then SGrid.ColCount:= ACol+1;
SGrid.Cells[ACol,ARow]:= Copy(tmpS,1,Pos(FldSeparator,tmpS)-1);
Delete(tmpS,1,Pos(FldSeparator,tmpS));
Inc(ACol);
end;
end;
finally
stList.Free;
end;
end;
CSVFileからStringGridへ読込み
procedure GridLoadCSV(SGrid:TStringGrid; fName:string);
var stList: TStringList;
ARow: Integer;
begin
stList:=TStringList.Create;
try
stList.LoadFromFile(fName);
SGrid.RowCount:= stList.Count;
for ARow:=0 to stList.Count-1 do
SGrid.Rows[ARow].CommaText:= stList[ARow];
finally
stList.Free;
end;
end;
選択範囲をクリップボードにコピー
usesに ClipBrd を追加して下さい。
//第2パラメータ、[Select=True]で選択範囲、Falseで全範囲
procedure CopyFromStringGrid(SGrid:TStringGrid;Select:Boolean=True);
var
S :String;
GRect :TGridRect;
ACol,ARow :Integer;
begin
if Select
then GRect:=SGrid.Selection
else GRect:=TGridRect(Rect(0,0,SGrid.ColCount-1,SGrid.RowCount-1));
S:='';
for ARow:=GRect.Top to GRect.Bottom do begin
for ACol:=GRect.Left to GRect.Right do begin
if ACol= GRect.Right
then S:=S+SGrid.Cells[ACol,ARow]
else S:=S+SGrid.Cells[ACol,ARow]+#9;
end;
S:=S+#13#10;
end;
ClipBoard.AsText:= S;
end;
セル位置にクリップボードから貼付け(範囲指定は考慮していません)
usesに ClipBrd を追加して下さい。
//第2パラメータ、[Select=True]で選択位置、Falseで左上(0,0)に貼付けます
procedure PasteToStringGrid(SGrid:TStringGrid; Select:Boolean=True);
var
S,tmpS :String;
ARow,ACol :Integer;
begin
if Select then ARow:= SGrid.Row-1
else ARow:= -1;
S:=ClipBoard.AsText;
while Pos(#13,S) > 0 do begin
Inc(ARow);
if Select then ACol:= SGrid.Col-1
else ACol:= -1;
tmpS:= Copy(S,1,Pos(#13,S));
while Pos(#9,tmpS) > 0 do begin
Inc(ACol);
if (ACol <= SGrid.ColCount-1) and (ARow <= SGrid.RowCount-1) then
SGrid.Cells[ACol,ARow]:= Copy(tmpS,1,Pos(#9,tmpS)-1);
Delete(tmpS,1,Pos(#9,tmpS));
end;
if (ACol <= SGrid.ColCount-1) and (ARow <= SGrid.RowCount-1) then
SGrid.Cells[ACol+1,ARow]:= Copy(tmpS,1,Pos(#13,tmpS)-1);
Delete(S,1,Pos(#13,S));
if Copy(S,1,1)=#10 then Delete(S,1,1);
end;
end;
ページトップ