テキストデータを表形式で表示するコンポーネント最適化された方法でデータ取得
明細の表示速度が高速
入力後のレスポンスが高速 入力の制御が容易に可能
TStringGridでのTabキーによるカーソル移動
しかし・・・
実は・・・ Options プロパティの設定のみで実装可能
TStringGridでのTabキーによるカーソル移動
Options プロパティの設定のみの場合
商品
CD
、単価、数量、備考のみ 入力可能 TStringGridでのTabキーによるカーソル移動
Options プロパティの設定のみの場合
入力可能なセルのみカーソルが 遷移すれば簡単に入力できるのに・・・
全セルにカーソルが遷移する
TStringGridでのTabキーによるカーソル移動
入力可能セルのみカーソルが移動すれば・・・
簡単に入力できる為
TStringGridでのTabキーによるカーソル移動
• 実装概要
①
指定のセルが、入力可能かどうかを判定する②
次の入力可能セルを見つけ、そのセルにカーソルを移動する TStringGridでのTabキーによるカーソル移動
①入力可能セルの判定
•
入力可能セルを判定するための関数private
function CanEdit(ACol: Integer): Boolean; // 変更可能判断
--- const
// 列位置情報
cCol_GYNO = 1; // 行№
cCol_SHCD = 2; // 商品CD cCol_SHNM = 3; // 商品名 cCol_TANK = 4; // 単価 cCol_SURY = 5; // 数量 cCol_KING = 6; // 金額 cCol_BIKO = 7; // 備考
--- function TfrmMGR010.CanEdit(ACol: Integer): Boolean;
begin
CanEdit関数
どの列に、何の情報が表示されているかを 定数にて管理する
入力可能なセルの場合にTrueを返却する 関数を作成する
TStringGridでのTabキーによるカーソル移動
②カーソルの移動
• CanEdit
関数を使用した入力可能セルへのカーソル移動procedure TfrmMGR010.stgListKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
var
iCol, iRow : Integer;
begin
// Tabキーが押下された場合 if Key in [VK_TAB] then begin
Key := 0; // 標準処理が実行されないようキーを初期化
// Shiftキーが押下されていない場合 if not (ssShift in Shift) then begin
// 次のセルを決定 iRow := stgList.Row;
iCol := stgList.Col + 1;
while iRow < stgList.RowCount do begin
while iCol < stgList.ColCount do
明細のOnKeyDownイベント<1>
次のカーソル位置を割り出すための変数を定義する
Tabキーが押下された場合のみ処理を実施する
Tabキー押下時の標準の処理が実行されると、カーソルの 位置設定後、もう一つ次のセルへカーソルが移動してしまう Shiftキーが押下されていない場合、一つ次の入力可能セルへ カーソルを移動させる
TStringGridでのTabキーによるカーソル移動
②カーソルの移動
• CanEdit
関数を使用した入力可能セルへのカーソル移動// 編集可能セルが見つかった場合 if CanEdit(iCol) then
begin
// セルを指定し、処理終了 stgList.Col := iCol;
stgList.Row := iRow;
Exit;
end;
// 次の列をチェック Inc(iCol);
end;
// 次の行をチェック Inc(iRow);
明細のOnKeyDownイベント<2>
各セル順番に入力可否をチェックし、
入力可能セルが見つかったタイミングで カーソルをセットする
TStringGridでのTabキーによるカーソル移動
②カーソルの移動
• CanEdit
関数を使用した入力可能セルへのカーソル移動// 編集可能セルが見つからなかった場合、行追加 stgList.RowCount := stgList.RowCount + 1;
stgList.Row := stgList.RowCount - 1; // 最終行にカーソル stgList.Col := cCol_SHCD; // 商品CDにカーソル
stgList.Cells[cCol_GYNO, stgList.RowCount - 1] := IntToStr(stgList.RowCount - 1); // 行№
end
// Shiftキーが押下されている場合 else
begin
(中略)
end;
end;
end;
明細のOnKeyDownイベント<3> 一つ次の入力可能セルが存在しなかった場合、
最終行に1行追加し、その行の商品CDへ カーソルをセットする
Shiftキーが押下されている場合、一つ前の入力可能セルへ カーソルを移動させる
TStringGridでのTabキーによるカーソル移動
③【補足】 セルの入力制御
• CanEdit
関数を使用したセルの入力制御procedure TfrmMGR010.stgListSelectCell(Sender: TObject; ACol, ARow: Integer;
var CanSelect: Boolean);
begin
// 入力可否制御
if CanEdit(ACol) then // 入力可能セルの場合 begin
stgList.Options := stgList.Options + [goEditing];
end
else // 入力不可セルの場合 begin
stgList.Options := stgList.Options - [goEditing];
end;
end;
明細のOnSelectCellイベント
入力可能セルにカーソルがセットされている場合、
OptionsプロパティにgoEditingを設定する
入力不可セルにカーソルがセットされている場合、
OptionsプロパティからgoEditingを解除する
2.開発効率・保守性の向上
開発効率・保守性の高いプログラム
• 開発効率
•
開発を行う際に、どれほど早く、または少ない労力で、作業を進められるか といった度合い• 保守性
•
改定を行うために必要な労力に関係するもの•
保守性は、4つの品質副特性を持つ①
解析性
ある変更を行うための修正箇所の割り出しの容易さ②
変更性
ある変更を行うための修正の容易さ③
安定性
ある変更を行う際のデグレードの発生確率 処理の共通化 ⇨ 開発効率・保守性の向上
• 処理の共通化がもたらす効果
•
開発効率
各画面に同じ処理を複数回記述する事になり、開発に時間がかかる•
保守性
仕様の変更が発生した場合、各画面への修正が必要となり、作業時間、デグレードが発生するリスクが高い
→処理を共通化することで、その処理が使用される画面にかかる 開発工数を大幅に削減できる
→共通化された処理のみの修正で全画面へ修正が反映される為 メンテナンスに費やす労力を最小限に抑えることができる
処理の共通化 ⇨ 開発効率・保守性の向上
• そこで、今回は処理の共通化を行う方法として
画面共通処理のフレームによる部品化
2-1.画面共通処理のフレームによる部品化
こんな時ないでしょうか?
複数のコンポーネントで1セットとなる項目を 複数の画面へ配置したい
見積入力
受注入力
発注入力
こんな時ないでしょうか?
各画面へ処理を記述した場合複数のコンポーネントで1セットとなる項目を 複数の画面へ配置したい
何度も同じ項目の配置や処理の記述 を行う為、開発効率が悪い
処理を共通化した場合同じ処理を記述する必要が無いため 開発時間の短縮ができる
こんな時ないでしょうか?
複数のコンポーネントで1セットとなる項目を 複数の画面へ配置したい
項目の桁数が変更になり、各項目の修正が必要になった・・・
各画面へ処理が記述されていると・・・修正箇所の割り出しに時間がかかる 修正自体にも時間がかかる
保守性が低いシステムになってしまう
処理が共通化されていると・・・修正箇所が1箇所の為、
短時間で修正することができる
処理の共通化
• 処理を共通化する方法
フレームを利用した処理の共通化をご紹介
1.
共通関数
ユニットなどを使用し、処理のみを共通化する方法
複数画面で使用される処理を共通化する場合に最適 ex)
明細データのCSV
出力、Ini
ファイルの参照、etc…
2.
カスタムコンポーネント
コンポーネントに、処理を記述することで共通化する方法
コンポーネント独自の処理を共通化する場合に最適 ex) Enter
キーの押下によるフォーカス移動、エラー項目の背景色反転、
etc…
3.
フレーム
複数コンポーネントの処理や制御などを共通化する方法 画面共通処理のフレームによる部品化
• フレームとは?
複数のコンポーネントを一つにまとめる為のコンポーネント
グループ単位でフォームや他のフレームへ配置することができる画面1
フレーム1 画面2
フレーム2
様々な処理を共通化することで
画面共通処理のフレームによる部品化
①フレームの生成
•
ツールバーより[ファイル|新規作成|その他…
]を選択 画面共通処理のフレームによる部品化
①フレームの生成
•
ダイアログより[Delphi
プロジェクト|Delphi
ファイル]のVCL
フレームを選択 画面共通処理のフレームによる部品化
①フレームの生成
•
フレームの保存保存先フォルダを指定し、任意のファイル名を入力後、
保存ボタンを押下する
画面共通処理のフレームによる部品化
②フレームへの処理の記述
•
フレームへコンポーネントの配置や処理の記述フォームの場合と同様の方法でコンポーネントを 配置、プロパティやイベントへの処理の記述を行う
画面共通処理のフレームによる部品化
②フレームへの処理の記述
public
constructor Create(AOwner: TComponent); override;
--- constructor TfraMGF010.Create(AOwner: TComponent);
begin
inherited;
// フレーム生成時の処理を記述 end;
フレーム生成時の処理を記述したい場合
public
destructor Destroy; override;
--- destructor TfraMGF010.Destroy;
begin
// フレーム解放時の処理を記述 inherited;
フレーム解放時の処理を記述したい場合
inheritedにて、フレーム自体のメモリが解放される為、
個別の処理はinheritedの前に記述する
画面共通処理のフレームによる部品化
③フレームの利用
•
ツールパレットへの追加 画面共通処理のフレームによる部品化
③フレームの利用
•
ツールパレットより画面への配置 画面共通処理のフレームによる部品化
③フレームの利用
•
フレームの項目より値を取得する方法フレームの項目値をファイルに更新
procedure TfrmMGR010.btnUpdateClick(Sender: TObject);
begin
// フレームの項目よりファイルを更新
SQLQuery1.ParamByName('SHCD').AsInteger := StrToIntDef(TfraMGF0101.edtSHCD.Text, 0); // 商品CD SQLQuery1.ParamByName('SURY').AsInteger := StrToIntDef(TfraMGF0101.edtSURY.Text, 0); // 数量 SQLQuery1.ParamByName('SIYO').AsString := TfraMGF0101.edtSIYO.Text; // 仕様
更新ボタンのOnClickイベント