Access VBA質問箱 IV

当質問箱は、有志のボランティア精神のおかげで成り立っています。
問題が解決したら、必ずお礼をしましょうね。
本サイトの基本方針をまとめました。こちら をご一読ください。

投稿種別の選択が必要です。ご注意ください。
迷惑投稿防止のため、URLの入力を制限しています。ご了承ください。


260 / 2272 ツリー ←次へ | 前へ→

【12358】複数のテキストボックスに入力した値の重複確認について ちゃぴんこくん 13/6/27(木) 0:17 質問[未読]
【12359】Re:複数のテキストボックスに入力した値の... hatena 13/6/27(木) 10:17 回答[未読]
【12360】【御礼】複数のテキストボックスに入力した... ちゃぴんこくん 13/6/28(金) 19:19 お礼[未読]
【12361】Re:【御礼】複数のテキストボックスに入力... hatena 13/6/28(金) 19:50 回答[未読]

【12358】複数のテキストボックスに入力した値の重...
質問  ちゃぴんこくん  - 13/6/27(木) 0:17 -

引用なし
パスワード
   初めまして!
部品問屋のイメージで得意先からの要求に対して出庫処理を登録するDBを作っています。

フォーム上には、部品コードと該当する部品の数量を入力するテキストボックスを各20個配置しています。
入力が終わった後、登録ボタンをクリックして、ループ処理で登録します。
ただ人が入力するため、同じ部品を重複してテキストボックスに入力してしまうことがあるため、登録前にチェックして重複を促して処理を中断するか、各テキストボックスに部品コードを入力した際に、先に入力したテキストボックスの値との重複確認させて改めたいと考えています。

ACCESS 2010
テキストボックス
  ・部品コード入力用:txt_BHN_1〜txt_BHN_20
  ・数量入力用   :txt_SU_1〜txt_SU_20

出来れば部品コードが入力された後にその他の19個のテキストボックスの値と重複チェックを行いその都度修正したいと考えています。
重複していればメッセージを表示して、入力したテキストボックスをクリアし、SetFocusしたいと思います。

当初は各テキストボックスのAfterUpdate処理に、以下のようにループを使ってテキストボックス名もカウントアップしてその他のテキストボックスを確認しようと考えました。

Private Sub txt_BOX_1_AfterUpdate()

  Dim i As Integer
  Dim N As Integer
  Dim intN As Integer

  i = 1
  N = 2

  For i = 1 To 20
  intN = "Me.txt_BOX_'" & N & ".value'"

  If IsNull(intN) = True Or intN = "" Then
  ’チェックするテクストボックスが空白ならば何もしない。

  Else

    If Me.txt_BOX_1.Value = intN Then

    MsgBox "部品コードが重複しています!", vbCritical, "警告"
    txt_BOX_1.SetFocus
    CMD_ADD.Visible = False     ’登録ボタンを非表示にする
    txt_BOX_1.BackColor = 8421631  ' 重複しているテキストボックスの背景を赤に
    Exit Sub
    
    End If
  
  End If

  N = N + 1
  i = i + 1

  Next

End Sub


これだと1個目のテキストボックスに対しては、その他のテキストボックスのチェックは可能なように思いますが、2番目以降のテキストボックスに対してチェックする場合に、自身を含めずにチェックするイメージが湧かず行き詰ってしまいました。

重複チェックといえば、レコードに登録されていないかのチェックの質問が多く
類似した質問を見つけることができず、どうかご教示の程、よろしくお願い申し上げます。

【12359】Re:複数のテキストボックスに入力した値...
回答  hatena  - 13/6/27(木) 10:17 -

引用なし
パスワード
   まず、

 intN = "Me.txt_BOX_'" & N & ".value'"

のコードでエラーになりますね。

"Me.txt_BOX_'" & N & ".value'" は、"Me.txt_BOX_2.value" というような文字列になりますが、それを数値型の変数に代入はできませんので。
コントロールの名称(文字列)でコントロールの値を参照すには、下記のような式になります。

Me.Controls("txt_BOX_1").Value

あるいは、Controls は規定のプロパティなので省略することもできます。

Me("txt_BOX_1").Value

次に、入力チェックするときのイベントは、更新後処理ではなく更新前処理の方がいいです。条件違反のときは、イベントをキャンセルすれば他のコントロールに移動しません。

自分以外のテキストボックスの重複値をチェックするという処理は共通なので、共通で使える関数を作成して、それを書くテキストボックスに関連付けるのがいいでしう。

フォームモジュールに下記の関数を作成します。

Private Function TyoufukuCheck()
  Dim i As Integer
  Dim N As Integer
  Dim V As Integer
  Dim ctl As Control

  For i = 1 To 5
    Me("txt_BOX_" & i).BackColor = vbWhite '背景色を初期化
  Next
  
  Set ctl = Me.ActiveControl '自分自身のコントロール
  If IsNull(ctl.Value) Then Exit Function '未入力なら何もしない
  N = Val(Mid(ctl.Name, 9)) '自分自身の番号
  V = ctl.Value
  For i = 1 To 20
    If i = N Then
    ElseIf V = Me("txt_BOX_" & i).Value Then
      Me("txt_BOX_" & i).BackColor = 8421631 '背景色を赤
      MsgBox "部品コードが重複しています!", vbCritical, "警告"
      ctl.SelStart = 0: ctl.SelLength = 255 '入力文字列を全選択
      DoCmd.CancelEvent       'イベントをキャンセル
      Exit For
    End If
  Next

End Function

フォームのデザインビューで部品コード入力用のテキストボックスをすべて選択した状態で、
プロパティの「更新前処理」欄に下記のように設定します。

=TyoufukuCheck()

これで重複した部品コードを入力した場合は、それを修正するまでテキストボックスから抜け出せません。


なお、部品コードは数値型との前提です。また、数値以外を入力した場合のチェックも追加したほうがいいでしょう。

【12360】【御礼】複数のテキストボックスに入力し...
お礼  ちゃぴんこくん  - 13/6/28(金) 19:19 -

引用なし
パスワード
   早速のご教示ありがとうございます。

初めてVBAのようなものを見よう見真似で手掛けてみたので
全てがイベントプロシージャーとして記述していました。

Function プロシージャーとしてこんなふうに記述できるんですね。
お蔭様で複数個のテキストボックスのイベントプロシージャーを変更せずに済んで
大助かりです。

各txt_BOX名の数値部分を増加するループで処理できるのではと考えたイメージは
あっていたみたいで、ちょびっとほっこりしています。
その取得にVal関数とMid関数で数値部分を取得するって考えには及びませんでしたけど・・・

>  N = Val(Mid(ctl.Name, 9))

また、SelStartプロパティでカーソルの位置を取得したり、位置を設定したり、
SelLengthプロパティでは、文字数を得ることができることを知りました。

CancelEventメソッドで引数Cancelを呼び出すなど、勉強させていただきました。

実際に部品コードは、アルファベットを含みますのでもう一ひねりしてみます。

この度は、誠にありがとうございました。

【12361】Re:【御礼】複数のテキストボックスに入...
回答  hatena  - 13/6/28(金) 19:50 -

引用なし
パスワード
   ▼ちゃぴんこくん さん:
>実際に部品コードは、アルファベットを含みますのでもう一ひねりしてみます。

ということは部品コードはテキスト型なんですね。

ならば、最初の変数宣言で、

Dim V As String

とすればいいだけです。

260 / 2272 ツリー ←次へ | 前へ→
ページ:  ┃  記事番号:
1078190
(SS)C-BOARD v3.8 is Free