[[20160510172544]] 『UserFormのTextBoxに数値の入力制限』(YAN) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

『UserFormのTextBoxに数値の入力制限』(YAN)

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

<内容>
6つのバーコードを読んで
TextBox1〜Textbox6にバーコードの内容(すべて数字)が入力されるようにしたい。

番号登録【UserForm1】
(1)TextBox1
(2)TextBox2
(3)TextBox3
(4)TextBox4
(5)TextBox5
(6)TextBox6

・TextBox1〜TextBox6は各21桁の番号が入る。
・TextBox1〜TextBox6の番号が重複していたらメッセージ表示

<現在の状態>
バーコードを読むとバーコードの内容(すべて数字)が
各TextBoxに1桁ずつはいってしまう。

バーコードの内容(数字)が 256865....だと
下記状態になります。

番号登録【UserForm1】
(1)TextBox1 → 2 
(2)TextBox2 → 5
(3)TextBox3 → 6
(4)TextBox4 → 8
(5)TextBox5 → 6
(6)TextBox6 → 5

そして重複してもメッセージが表示されません。

初心者です。
ご教授願います。


Private Sub TextBox1_Change()
    If TextBox1.Text = TextBox2.Text Or TextBox1.Text = TextBox3.Text Or TextBox1.Text = TextBox4.Text Or TextBox1.Text = TextBox5.Text Or TextBox1.Text = TextBox6.Text Then
      MsgBox "番号が重複しています。"
    Exit Sub
    End If

    TextBox2.SetFocus
End Sub

Private Sub TextBox2_Change()
    If TextBox2.Text = TextBox3.Text Or TextBox2.Text = TextBox4.Text Or TextBox2.Text = TextBox5.Text Or TextBox2.Text = TextBox6.Text Then
      MsgBox "番号が重複しています。"
    Exit Sub
    End If

    TextBox3.SetFocus
End Sub

Private Sub TextBox3_Change()
    If TextBox3.Text = TextBox4.Text Or TextBox3.Text = TextBox5.Text Or TextBox3.Text = TextBox6.Text Then
      MsgBox "番号が重複しています。"
    Exit Sub
    End If

    TextBox4.SetFocus
End Sub

Private Sub TextBox4_Change()
    If TextBox4.Text = TextBox5.Text Or TextBox4.Text = TextBox6.Text Then
      MsgBox "番号が重複しています。"
    Exit Sub
    End If

    TextBox5.SetFocus
End Sub

Private Sub TextBox5_Change()
    If TextBox5.Text = TextBox6.Text Then
      MsgBox "番号が重複しています。"
    Exit Sub
    End If

    TextBox6.SetFocus
End Sub

Private Sub UserForm_Initialize()
    UserForm1.Caption = "番号登録"
    With TextBox1
        .Value = ""
        .IMEMode = fmIMEModeAlpha
        .MaxLength = 21
        .SetFocus
    End With

    UserForm1.Caption = "番号登録"
    With TextBox2
        .Value = ""
        .IMEMode = fmIMEModeAlpha
        .MaxLength = 21
        .SetFocus
    End With

    UserForm1.Caption = "番号登録"
    With TextBox3
        .Value = ""
        .IMEMode = fmIMEModeAlpha
        .MaxLength = 21
        .SetFocus
    End With

    UserForm1.Caption = "番号登録"
    With TextBox4
        .Value = ""
        .IMEMode = fmIMEModeAlpha
        .MaxLength = 21
        .SetFocus
    End With

    UserForm1.Caption = "番号登録"
    With TextBox5
        .Value = ""
        .IMEMode = fmIMEModeAlpha
        .MaxLength = 21
        .SetFocus
    End With

    UserForm1.Caption = "番号登録"
    With TextBox6
        .Value = ""
        .IMEMode = fmIMEModeAlpha
        .MaxLength = 21
        .SetFocus
    End With
 End Sub

< 使用 Excel:Excel2010、使用 OS:Windows7 >


 アップされたコードは、改善の余地も多いですし、不要なコードも見受けられますが、さておき。

 バーコードは使ったことがありませんが、基本としては、フォーカスのある TextBoxに読みこみ内容が
 入ってきますよね。で(おそらく)1文字ずつ入力されてきます。

 TextBoxのChangeイベントは、非常に使いづらいことで【定評】がありますが、1文字入力ごとに発生します。

 たとえば 256865 の入力の場合、TextBox1 に、2 が入って発生、そのChangeイベントでTextBox2にフォーカスを移していますので
 次の 5 は TextBox2 に入り、そこでイベントが発生して、TextBox3にフォーカスを移し・・・・

 ということになります。

 番号が21桁と決まっているなら、21桁になったら処理を行う。21桁未満ならなにもしない。

 こんな制御を加えればよろしいかと。

(β) 2016/05/10(火) 18:05


 追記です。

 バーコード側に、データを送りこんだ後、たとえば Enter信号を送るといった設定ができるようになっていませんか?
 それができるなら、CHangeイベントを使わず、BeforeUpdate や AfterUpdate といった Exit系のイベント処理を検討してください。
 エラーチェックを行いますので Exit をキャンセルできる BeforeUpdateがよろしいかと思います。

(β) 2016/05/10(火) 18:11


 >>そして重複してもメッセージが表示されません。 

 これについては、ご自分でコードを追いかければ、チェックの不備がわかると思いますが?

 アップされた例では TextBox5 に 6 が入った時に、重複にしたいですね。
 でも TextBox5 の Changeイベントでは、どことどこを比較しているでしょうか?

(β) 2016/05/10(火) 18:17


 Initializeルーティン、あまりにも無駄が多いので、コメントしておきますね。

 1.UserForm1.Caption = "番号登録"

   6回もでてきますね。シートのセルでいえば、同じセルに同じ値を6回書きこんでいるようなものです。
   また、ここは、あらかじめデザインでプロパティにセットしておけばコードは不要です。(後述)

 2..Value = ""

   各TextBox の値をクリアしているわけですが、Initializeのタイミングでは(よっぽど変なデザインでない限り)
   各TextBoxの値は空白ですよね。したがって、このコードは不要です。

 3..SetFocus

   これは何をしているつもりですか? Initializeのタイミングは、まだユーザーフォームが表示されない段階ですし
   なによりも、TextBox1にSetFocusし、続いて TextBox2にSetFocusし、続いて、・・・・・
   最終的には TextBox6 にSetFocusして終わっていますね。何がしたかったのですか?

   このコードは無意味ですので消しましょう。

 4..IMEMode = fmIMEModeAlpha と .MaxLength = 21

   前述の 1.と同じく、デザインで値をセットしておけば、このコードは不要です。
   ユーザーフォームデザイン画面で、6つのTextBoxを選択して、プロパティウィンドウで、このプロパティの値をセットすると
   6つのTextBoxすべての値としてセットされます。

   ただし、あえてコードで記述することで【文書化】の意味も出てきますので、これらについては、あってもいいかなと思っています。
   (コードそのものはループ記述で短くすることはできますが)

(β) 2016/05/10(火) 19:27


 仮に バーコードリーダ側で Enterコードの送信が可能で、その設定をして、読み取った後に
 自動的に次のTextBoxにフォーカスが映るとして。

 コード例です。Initializeはプロパティでセットしておけば不要ですが、【文書化】のポイントで
 必要なものだけを記述してあります。

 Private Sub UserForm_Initialize()
    Dim x As Long

    Caption = "番号登録"

    For x = 1 To 6
        With Controls("TextBox" & x)
            .IMEMode = fmIMEModeAlpha
            .MaxLength = 21
        End With
    Next

 End Sub

 Private Sub TextBox1_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)
      Cancel = IsDuplicate(TextBox1)
 End Sub
 Private Sub TextBox2_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)
      Cancel = IsDuplicate(TextBox2)
 End Sub
 Private Sub TextBox3_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)
      Cancel = IsDuplicate(TextBox3)
 End Sub
 Private Sub TextBox4_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)
      Cancel = IsDuplicate(TextBox4)
 End Sub
 Private Sub TextBox5_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)
      Cancel = IsDuplicate(TextBox5)
 End Sub
 Private Sub TextBox6_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)
      Cancel = IsDuplicate(TextBox6)
 End Sub

 Private Function IsDuplicate(tx As MSForms.TextBox) As Boolean
    Dim x As Long

    For x = 1 To 6
        With Controls("TextBox" & x)
            If .Name <> tx.Name Then
                If .Value = tx.Value Then
                    MsgBox "値が重複しています"
                    tx.SelStart = 0
                    tx.SelLength = tx.TextLength
                    IsDuplicate = True
                    Exit For
                End If
            End If
        End With
    Next

 End Function

(β) 2016/05/10(火) 20:17


(β)様
細かく教えていただき、本当にありがとうございます!

>TextBox5 の Changeイベントでは、どことどこを比較しているでしょうか?
  TextBox5 と TextBox6 の比較のつもりでした・・・

>プロパティウィンドウで、このプロパティの値をセットすると6つのTextBoxすべての値としてセットされます。
  はじめはプロパティウィンドウに直接入力していたのですが
  うまくいかず、デバックでみても何も出なかったんです・・・

とても基礎的なことで申し訳ないのですが
エラーチェックする時はデバッグのコンパイル、ステップインで見つけていくで良いでしょうか?
あと、IsDuplicateとはなんでしょうか?
ネットで調べてもでてこなかったので・・・

(YAN) 2016/05/11(水) 11:35


 IsDuplicate は 指定テキストボックスの値が他のテキストボックスと重複しているかどうかを調べる新しいメソッドです。

 なんてのは、嘘です。

 そういうメソッドがあればいいのですがないので、自分でつくりました。

 Private Function IsDuplicate(tx As MSForms.TextBox) As Boolean
      '
      '
 End Function

 で記述している部分です。

 いずれにしても重複チェックは、すべてのテキストボックスと比較しないといけません。
 そもそも、TextBox5 に値が入った時、おそらく順番に入力させているでしょうから TextBox6 は空白ですよね。
 そうすると、常に Not Equal ですから、重複チェックの役目は果たしませんよね。

 >>はじめはプロパティウィンドウに直接入力していたのですが 
 >>うまくいかず、デバックでみても何も出なかったんです・・・ 

 それはおかしいですね。

 たとえば新規ブックで、ユーザーフォームをつくり TextBox1 と TextBox2 を配置。
 デザインで、プロパティのIMEModeとMaxLengthに何かしらセットした上で

 Private Sub UserForm_Click()
    MsgBox TextBox1.IMEMode & vbLf & TextBox2.IMEMode
    MsgBox TextBox1.MaxLength & vbLf & TextBox2.MaxLength
 End Sub

 こんなコードを書いておき、ユーザーフォームを表示して、フォーム上のどこかをマウスでクリックしてみてください。
 プロパティでセットした値が表示されますよね?

 >>エラーチェックする時はデバッグのコンパイル、ステップインで見つけていくで良いでしょうか?

 はい。まず、これが基本だと思います。
 そのほか、ローカルウィンドウをみたり、あるいはイミディエイトウィンドウで、変数を表示させたり
 まぁ、いろいろあります。
 【VBA デバッグ方法】あたりで検索すると、いろいろでてきますので、わかりやすそうなページを通読してみるというのも
 有効だと思いますね。

(β) 2016/05/11(水) 11:58


>>そういうメソッドがあればいいのですがないので、自分でつくりました。
  つくれるんですか!!
  まだ理解できていないのでまずはメソッドについて調べてみます。

>>そもそも、TextBox5 に値が入った時、おそらく順番に入力させているでしょうから TextBox6 は空白ですよね。
  ほんとですね・・・
  やりたい動きとそのためにはどうすれば良いかをもう一度よく考えてみます。

>>プロパティでセットした値が表示されますよね?
  新規で作成してみたら、ちゃんと21文字ではいりました!

(β)様のを参考にさせてもらい、再度1からやってみます。
指摘していただけたことがとてもありがたく、がんばろうと思いました!
ありがとうございます!

(YAN) 2016/05/11(水) 15:13


 補足しておきます。メソッドがあればいいけどないのでつくりましたが、メソッドを作ったわけではなく
 自前の関数を作った というのが正しいです。

(β) 2016/05/11(水) 23:24


コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.