入力桁数のチェック方法


たま  2002-12-27 20:37:49  No: 2442

お世話になります。
たまです。
[Windows2000,Delphi5,Oracle]

DBGridに表示させるカラム:Column1が「NUMBER(13,4)」なのですが
グリッド上で10桁以上入力するとエラーとなります。
そこでLength関数よりチェックを行おうと思っているのですが

  Column1_Length := Length(Column1_Value);
  if Column1_Length > 9 then
  begin
    Showmessage('桁数オーバー');
  end;

を、どのタイミング(イベント?)ですればよいのかわかりません。

お分かりになる方がいましたらよろしくお願い致します。


にしの  2002-12-27 21:26:03  No: 2443

(13,4)ということは、整数部9桁の小数部4桁だったと思いますが、違いましたっけ?


たま  2002-12-28 00:54:04  No: 2444

< (13,4)ということは、整数部9桁の小数部4桁だったと思いますが、違いましたっけ?
はい、その通りです。

いろいろとやってみたのですが(初心者レベルですが(^^; )

グリッドに入力された値(整数部9桁・小数部4桁まで)を変数に格納する場合に
型は、Double型?Extended型?その他? どれが適切なのでしょうか?

それと
小数部は、小数点以下5桁以上は自動的に切り上げになります。
整数部は、10桁以上入力した場合にエラーが発生します。
この時の対象法としてはどのようなものがあるでしょうか?

よろしくお願いいたします。


にしの  2002-12-28 01:41:41  No: 2445

http://www.borland.co.jp/qanda/delphi/d0002955.html
が参考になると思います。


たま  2002-12-28 03:19:03  No: 2446

はい、参考になりました。
「変数に格納する」という問題はフォーマット関数を使いクリアできました。
ありがとうございます。

なのですが
整数部に10桁以上入力した場合の問題がクリアできません。
入力してEnterなりをたたいた後に
「変換エラー。値が範囲外です。」
となってしまいます。
これもフォーマット関数で解決できるのでしょうか?
整数部が10桁以上入力されたことを知ることが出来ればよいのですが(!?)

よろしくお願いします。


Basser  2002-12-28 04:25:04  No: 2447

こんばんは、たまさん

TField にデータ検証をする為の OnValidate イベントがあります。
以下が例です。

  procedure FloatFieldValidate(Sender: TField);
  var
    Len: Integer;
  begin
    Len:= Length(Sender.AsString);
  
    if (Len > 9) and (AnsiPos('.', Sender.AsString) > 10) then
      raise Exception.Create('整数部の有効桁数を超えています');
  end;

上記はイレギュラーな入力を考慮していない為、不完全ですが、
同じくTField のValidChar プロパティで入力制限をかけてやれば、
イレギュラー処理も幾分楽になると思います。


たま  2002-12-29 00:11:07  No: 2448

Basserさん、ありがとうございます。

イベントについて初歩的な質問なのですが
> procedure FloatFieldValidate(Sender: TField);
とは、
『Table1コンポーネントをダブルクリックして「項目の追加」を行う画面でカラム:Column1 の OnValidate を設定する』
ということなのでしょうか?
もしあっているならば、こちら↓の手続きで(TTableではなくTQueryですが)

procedure TDM.Query1COLUMN1Validate(Sender: TField);
var
  Q_Length: Integer;
  Q_Value: String;
begin
  Q_Value := Form1.DBGrid1.SelectedField.Text;
  Q_Length := Length(Sender.AsString);

  if Q_Value > '999999999' then  //小数点以下は無視
  begin
    showmessage('最大値オーバー');
    DM.Query1.Cancel;
    Abort;
  end
  else
  begin
    //(小数点ナシ整数部10桁以上)or(小数点アリで位置が10桁目以上)の場合
    if ((Q_Length > 9) and (AnsiPos('.', Sender.AsString) = 0)) or (AnsiPos('.', Sender.AsString) > 10) then
    begin
      showmessage('入力桁数オーバー');
      DM.Query1.Cancel;
      Abort;
    end;
  end;
end;

うまく動作させることができました。
Basserさん、ありがとうございます m(_"_)m
"AnsiPos"の使い方を知りませんでした。

それと
> TField のValidChar プロパティで入力制限をかけて
というのは
  Form1.DBGrid1.Fields[3].ValidChars := [#0..#9];
では違いますよね?!

よろしくお願いします。


Basser  2002-12-30 04:40:27  No: 2449

こんばんは、たまさん

OnValidate イベントの設定方法ですが、
DMQueryが DBGrid にリンクされていると思うので
DMQuery の AfterOpenイベントで

  ※ フィールド名がわからないので 'Column1'としています
  With DMQuery do
    If Assigned(FieldByName('Column1')) then
    begin
      FieldByName('Column1').OnValidate:= TDMQuery1COLUMN1Validate;
      
      // '-', '.', '0'〜'9' のみ入力可
      FieldByName('Column1').ValidChars:= [#45,#46,#48..#57];
    end

とすれば、別に「項目の追加」をしなくても結構です。
「項目の追加」をした場合は、TFieldの下位クラスの
TFloatFieldが生成されると思うので、
制限によってはValidCharsはいらない場合があると思います。
(TFloatFieldで設定済)
現在、自宅にDelphiの環境が無いので、はっきり答えられないので
申し訳ありません。


たま  2002-12-30 10:44:05  No: 2450

Basserさん、ご回答ありがとうございます。

私も現在、自宅にDelphiの環境がないので
年明けにやってみようと思います m(_._)m


たま  2003-01-07 03:59:37  No: 2451

お世話になります。

入力制限を…ということでやってみたところうまく動作できました。
Basserさん、ありがとうございます。m(_~_)m

入力できるのは'.'と'0'〜'9'としました。
そこで、'.'を複数個入力された場合にエラー表示をさせようと
OnKeyDownイベントやOnKeyPressイベントで試みてみたのですが、、

procedure TForm1.DBGrid1KeyPress(Sender: TObject; var Key: Char);
begin
  if Key = Char(VK_BACK) then  //これはテストでBackSpaceを。。
    showmessage('BackSpace');
end;

『.』のキーコードが分からずできませんでした。(;_;)
VK_DECIMALは違うのでしょうか。。?

どうぞよろしくお願いします。


Basser  2003-01-07 19:28:41  No: 2452

OnKeyPress イベントの引数である Key は
文字型なので

  if Key = '.' then
  begin
    Key:= #0;
    Beep;
  end;

でいいと思います。


たま  2003-01-07 20:45:09  No: 2453

> OnKeyPress イベントの引数である Key は文字型なので
(Sender: TObject; var Key: Char);  ← このことですね!?
Basserさん、ありがとうございます。

また質問なのですが (^-^;
入力を行っている時に編集しているセルの値を取得することは可能でしょうか?
例えば、('100'を'101'にする)
1. 編集する前の値が'100'。
2. BackSpaceで'0'をひとつ消して'10'になった時に'10'を取得する。
3. '1'を入力して'101'にした時に'101'を取得する。
このような流れはできますか?

よろしくお願いします。


Basser  2003-01-08 01:38:41  No: 2454

TDBGrid の機能だけでは無理のような気がします。
自作コンポーネントで TCustomDBGrid.SetEditText を継承したクラスを
作成するのがいいかと思います。


たま  2003-01-09 03:28:29  No: 2455

Basserさん、いろいろとご教示ありがとうございます m(_'_)m

そうですか、
TDBGridではできない処理なのですね o(;_;)o

(また質問なのですが)
自作コンポーネントの作成とはこのような感じでよいのでしょうか?

type
  TMyDBGrid = class(TDBGrid)  //クラスの宣言はこんな感じですか?
                              //"TCustomDBGrid"?
  ……………
  procedure TMyDBGrid(?);  //"?"部は特に書かなくてもよい?
  begin
    {…処理…}
  end;

> TCustomDBGrid.SetEditText を継承したクラスを
SetEditTextはどのように書けばよいのでしょうか?

すみません、基本的な質問で (^-^;
よろしくお願い致します。


Basser  2003-01-09 04:25:08  No: 2456

私はイベントで取得できるようするのがいいかと思います
以下を例としてあげておきます

type
  TGetEditTextEvent = procedure(Sender: TObject;  const EditText: String) of object;

  TMyDBGrid = class(TDBGrid)
  private
    FOnGetEditText: TGetEditTextEvent;
  protected
    procedure SetEditText(ACol, ARow: Longint; const Value: string); override;
  public
    // public で宣言してますが、コンポーネントととして登録するのなら,
    // published で宣言した方がいいかも
    property OnGetEditText: TGetEditTextEvent read FOnGetEditText write FOnGetEditText;
  end;

implementation

{ TMyDBGrid }

procedure TMyDBGrid.SetEditText(ACol, ARow: Integer; const Value: string);
begin
  // 上位クラスのSetEditTextを呼び出し
  inherited SetEditText(ACol, ARow, Value);

  // イベントが設定されていれば、OnGetEditText イベントを発生させています
  if Assigned(FOnGetEditText) then FOnGetEditText(Self, Value);
end;


たま  2003-01-10 02:52:31  No: 2457

Basserさん、いつもありがとうございます。

Basserさんのサンプルコードを貼り付けてみました。
"クラスの宣言"と"procedure TMyDBGrid.SetEditText"はうまくできました。
でも OnGetEditTextイベントの設定の仕方がわかりません。。
(TStringGridにはこのイベントがあったのですが…)
自作の関数を作るということなのでしょうか?

public
  procedure OnGetEditText;  //宣言

procedure FOnGetEditText(???);  //?'const Value: string'?
begin
  {…処理…}
end;

こんな感じでは…ないですよね?!

「グリッドに入力された値を取得して、その中に'.'が含まれているかをチェックする」
これをしようとする場合、、
『(OnKeyPressイベントは使わずに(FOnGetEditTextイベントより値を取得しチェックする』
ということですよね?
それと、、(Helpを見てみたのですが)
"FOnGetEditText(Self, Value)"の'Self'には'ACol'と'ARow'が入るのでしょうか?

初歩的な質問ばかりですいません。。(^-^;

よろしくお願い致します。


Basser  2003-01-10 04:32:04  No: 2458

こんばんは、たまさん

>『(OnKeyPressイベントは使わずに(FOnGetEditTextイベントより値を取得しチェックする』
> ということですよね?

いいえ、チェックはOnKeyPressイベントで行う方法でいいと思います。
あくまでイベントは値を取得する為のものです。
Public部に変数を宣言し、そこに格納してもよかったのですが
TCustomDBGridの内部に同じ値が Private で存在している為、
同じ値を格納するのもどうかとゆうことでイベントにしただけです。

>それと、、(Helpを見てみたのですが)
>"FOnGetEditText(Self, Value)"の'Self'には'ACol'と'ARow'が入るのでしょうか?

上記に関しては、ヘルプで Self を見てもらえばわかると思います。

最後にイベントの設定方法ですが
下記のような感じです。
※必要以上のものは省いています

Type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    FEditText: String;
    FMyGrid  : TMyDBGrid;
    procedure MyGetEditText(Sender: TObject;  const EditText: String);
  end;

var
  Form1: TForm1;

implementation

procedure TForm1.MyGetEditText(Sender: TObject;  const EditText: String);
begin
  FEditText:= Value;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  FMyGrid:= TMyDBGrid.Create(Self);
  FMyGrid.Parent:= Self;
  FMyGrid.OnGetEditText:= MyGetEditText;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  FMyGrid.Free;
end;

後は、MyGetEditTextで取得したFEditTextの値をOnKeyPressイベントで参照するだけです。


※返信する前に利用規約をご確認ください。








  このエントリーをはてなブックマークに追加