Delphi Programming / Object Pascal
[掲載 2012年07月28日] [更新 2012年07月28日] Delphi サンプルプログラム集 |
062_TDBGrid のセル値のコピー |
動作確認等 |
Windows 7 U64(SP1) + Delphi XE Pro ( BDE 5.2 + Paradox 7.0 ) |
|
062_DBGrid_CellCopy.zip [1,722 KB] 2012年07月28日版 (EXE 同梱) |
[050_TStringGrid とカスタム描画] で セルの値をクリップボードに出力したり,ディクスに保存するサンプルを掲載しました.本ページは,その TDBGrid 版です.
実際に操作するのは「セルの値」ではなく,データセットの値です.列に相当するのは,各レコードの各項目(フィールド)で,行がレコードに相当します.
取得可能な値は,Value プロパティと,DisplayText プロパティがあります.DisplayText の値は,デーベースコントロール等に表示する際の設定値です.これらの値は,TDBGrid にデータを表示する,しないにかかわらず取得できます.
データベースあるいはデータベースコントロールによっては,このようなデータの出力用のメソッド類を実装しているものがあります. |
各フィールドの値を String 型で取り出し,TStringList のリストに格納し,そのテキストをクリップボードにコピーします.TStringList をファイルに保存すれば,ディスクへの保存となります.
ここでは,各セルに表示されているデータではなく,データセットの値のコピーとなっています.そのためメモ型の項目の内容もクリップボードにコピーします.これを裂けるには,項目の種類を判定してメモ型の項目等を除外する必要があります.
セルに表示されている値をコピーする場合は,以下のように DisplayText に変更するか,DataSet の代わりに DBGrid1 にします.対象を DBGrid1 にすれば,DBGrid1 の DisplayText の値に対する処理になります. |
リスト1
Fields[i] が列に相当し,DisplayText がその列の値ということになる |
//データをデリミタ文字で区切ってリストに追加
for i := 0 to Dataset.FieldCount - 1 do begin
ColList.Add(DataSet.Fields[i].DisplayText);
end;
取り出されるデータの順番は,TDBGrid に表示されている列の順となります.したがって,マウスのドラッグ操作で列を移動すると,移動後の例順となります.取り出す順番を固定するには,取り出す項目(フィールド) の名前,例えば,FieldByName で直接指定します. |
[備考]
TDataSet.Fielss の各項目の DisplayText の値と,TDBGrid.Fields の各項目の DisplayText の値が必ずしも同じとは限りません.TQuery 等のデータセット関係のコンポーネントには項目の設定があり,TDBGrid にも各項目設定用のカラムエディタがあります.
|
|
図1
設計時画面 |
|
図2
実行画面
- インジケータの行が現在のレコード
- このレコードの内容をコピーする
- タブ区切りのテキストは,エクセルのセルへの貼り付けが可能
|
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Db, DBTables, Grids, DBGrids, ExtCtrls, Buttons;
type
TForm1 = class(TForm)
DBGrid1: TDBGrid;
DataSource1: TDataSource;
Panel1: TPanel;
Query1: TQuery;
SpeedButton1: TSpeedButton;
SpeedButton2: TSpeedButton;
SpeedButton3: TSpeedButton;
procedure FormCreate(Sender: TObject);
procedure SpeedButton1Click(Sender: TObject);
procedure SpeedButton2Click(Sender: TObject);
procedure SpeedButton3Click(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
uses Clipbrd;
{$R *.DFM}
type
TMyDBGrid = class(TDBGrid);
//=============================================================================
// フォーム生成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
Query1.Close;
DataSource1.DataSet := Query1;
DBGrid1.DataSource := DataSource1;
DBGrid1.Options := DBGrid1.Options - [dgEditing];
DBGrid1.Options := DBGrid1.Options + [dgRowSelect];
Query1.DatabaseName := 'DBDEMOS';
Query1.SQL.Clear;
Query1.SQL.Add('select * from customer.db');
Query1.Open;
end;
//=============================================================================
// [タブ形式 現レコード]
// TQueryの現在のレコードのデータをクリップボードにコピー
// タブ形式はエクセルのセルに直接貼り付けることができる
//=============================================================================
procedure TForm1.SpeedButton1Click(Sender: TObject);
var
Dataset : TDataSet;
SL : TStringList;
ColList : TStringList;
i : Integer;
begin
//TDBGridに表示しているデータセット取得
Dataset := DBGrid1.DataSource.DataSet;
SL := TStringList.Create;
ColList := TStringList.Create;
//デリミタの設定
ColList.Delimiter := Chr(VK_TAB);
try
//データをデリミタ文字で区切ってリストに追加
for i := 0 to Dataset.FieldCount - 1 do begin
ColList.Add(Dataset.Fields[i].AsString);
end;
SL.Add(ColList.DelimitedText);
Clipboard.AsText := SL.Text;
finally
FreeAndNil(SL);
FreeAndNil(ColList);
end;
DBGrid1.SetFocus;
end;
//=============================================================================
// [タブ形式 全レコード]
// TQueryの全レコードのデータをクリップボードにコピー
// タブ形式はエクセルのセルに直接貼り付けることができる
//=============================================================================
procedure TForm1.SpeedButton2Click(Sender: TObject);
var
RowCount : Integer;
RN : Integer;
td-dateRecNo : Integer;
CurrentRowNo : Integer;
Dataset : TDataSet;
SL : TStringList;
ColList : TStringList;
i : Integer;
begin
//TDBGridに表示しているデータセット取得
Dataset := DBGrid1.DataSource.DataSet;
//表示更新を止める
Dataset.DisableControls;
//----- DBGridのスクロール状態を元に戻すための変数設定 ---------------------
CurrentRowNo := TMyDBGrid(DBGrid1).Row - 1;
td-dateRecNo := Dataset.RecNo - CurrentRowNo;
//---------------------------------------------------------------------------
SL := TStringList.Create;
ColList := TStringList.Create;
//デリミタの設定
ColList.Delimiter := Chr(VK_TAB);
try
//全てのレコードに対して操作
while (Dataset.Eof = False) do begin
//データをデリミタ文字で区切って行単位でリストに追加
ColList.Clear;
for i := 0 to Dataset.FieldCount - 1 do begin
ColList.Add(Dataset.Fields[i].AsString);
end;
SL.Add(ColList.DelimitedText);
Dataset.Next;
end;
Clipboard.AsText := SL.Text;
//----- DBGridのスクロール状態を元に戻すための処理 ---------------------
RowCount := TMyDBGrid(DBGrid1).VisibleRowCount;
Dataset.RecNo := td-dateRecNo;
Dataset.MoveBy(RowCount);
while Dataset.BOF = False do begin
RN := Dataset.RecNo;
if RN = td-dateRecNo then begin
Break;
end else begin
Dataset.Prior;
end;
end;
Dataset.MoveBy(CurrentRowNo);
//-------------------------------------------------------------------------
finally
FreeAndNil(SL);
FreeAndNil(ColList);
end;
//表示更新再開
Dataset.EnableControls;
DBGrid1.SetFocus;
end;
//=============================================================================
// [CSV形式 現レコード]
// TQueryの現在のレコードのデータをクリップボードにコピー
//=============================================================================
procedure TForm1.SpeedButton3Click(Sender: TObject);
var
Dataset : TDataSet;
SL : TStringList;
ColList : TStringList;
i : Integer;
begin
//TDBGridに表示しているデータセット取得
Dataset := DBGrid1.DataSource.DataSet;
SL := TStringList.Create;
ColList := TStringList.Create;
//デリミタの設定
ColList.Delimiter := ',';
try
//データをデリミタ文字で区切ってリストに追加
for i := 0 to Dataset.FieldCount - 1 do begin
ColList.Add(Dataset.Fields[i].AsString);
end;
SL.Add(ColList.DelimitedText);
Clipboard.AsText := SL.Text;
finally
FreeAndNil(SL);
FreeAndNil(ColList);
end;
DBGrid1.SetFocus;
end;
end.
現在のレコードの値を複写しておき,レコードを追加した時に,追加したレコードの各フィールド(項目)値にセットするサンプルです.
一度にセットするのではなく,入力項目を移動する度に,前のレコードの値を参考用に表示するという用途にも利用できます.データの種類には,数値型もありますから,全てを文字列型で扱うというわけにはいきません.そこで,バリアント配列を作成して操作しています. |
|
図3
設計時画面 |
|
図4
適当なレコードを選択
|
|
図5
[レコード追加]をクリック
- 選択レコードと同じデータのレコードが追加される
- ただし,キー項目の値はコードで変更している
|
|
図6
[レコード削除]をクリック
- テストなので,追加したレコードを削除してからプログラムを閉じる
|
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Db, DBTables, Grids, DBGrids, ExtCtrls;
type
TForm1 = class(TForm)
DataSource1: TDataSource;
Panel1: TPanel;
Button1: TButton;
Query1: TQuery;
DBGrid1: TDBGrid;
Button2: TButton;
procedure FormCreate(Sender: TObject);
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
//=============================================================================
// フォーム生成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
Query1.Close;
//Query1を編集,更新可能にしておく
Query1.RequestLive := True;
DataSource1.DataSet := Query1;
DBGrid1.DataSource := DataSource1;
Query1.DatabaseName := 'DBDEMOS';
Query1.SQL.Clear;
Query1.SQL.Add('select * from customer.db');
Query1.Open;
ActiveControl := DBGrid1;
end;
//=============================================================================
// フォームを閉じる時の処理
//=============================================================================
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
Query1.Close;
end;
//-----------------------------------------------------------------------------
// 引数のDataSetにレコードを追加する関数
// 現在のレコードのフィードの値をコピーして,それを新しいレコードの値とする
// バリアント型であれば,変数の型を意識する必要がない
// ただし,キー項目等,重複する値はデータの更新が出来ないので注意
//
// (1) 現在のレコードの値をバリアント型の配列に代入
// (2) レコードを追加
// (3) バリアント配列に格納した値を,追加レコードの各フィールドに代入
//-----------------------------------------------------------------------------
procedure AppendCurrentData(Dataset: TDataset);
var
FieldList : Variant;
i : Integer;
begin
//バリアント型の配列を作成
FieldList := VarArrayCreate([0, DataSet.FieldCount - 1], VarVariant);
for i := 0 to DataSet.FieldCount - 1 do begin
FieldList[i] := DataSet.Fields[i].Value;
end;
DataSet.Append;
for i := 0 to DataSet.FieldCount -1 do begin
DataSet.Fields[i].Value := FieldList[i];
end;
end;
//=============================================================================
// [レコード追加]
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
Dataset : TDataSet;
begin
//TDBGridに表示しているデータセット取得
Dataset := DBGrid1.DataSource.DataSet;
AppendCurrentData(Dataset);
//キー項目は重複して登録できないので変更
Dataset.FieldByName('CustNo').Value := '100000';
Dataset.Last;
DBGrid1.SetFocus;
end;
//=============================================================================
// [レコード削除]
// テストなので,追加したレコードは削除しておいた方がいいだろう
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
var
Dataset : TDataSet;
begin
//TDBGridに表示しているデータセット取得
Dataset := DBGrid1.DataSource.DataSet;
Dataset.Delete;
DBGrid1.SetFocus;
end;
end.
|