[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]
『テキストボックスで間違った入力をした時元のテキストボックスへ戻るには』(中途半端)
フォーム上のテキストボックスで本来求める形式で入力されなかった場合、
vbaで元へ戻るコードを書いても次のコントロールへ移動してしまいます。
(例)If Not IsNumeric(Tx1) then
Tx1=""
Tx1.SetFocus
End If
しかし次のコントロールへ? 簡単な方法で何とかなりませんか!
関連して、MsgBoxの結果次第で直接Formを閉じたり、Excelを終了させる事は可能でしょうか?
(例)If MsgBox("PassWordが違います。終了しますか?",VbYesNo) = VbYes Then
Unload Me
End If
この結果はエラーになります。コマンドボタンを追加して終了処理をしなければなりません。
MsgBoxで意向確認した後、更に終了ボタンを押さなければならないなんて不自然! 私としては結果次第で即終了したいのです。
どうか力添えをお願いします。
< 使用 Excel:Excel2010、使用 OS:Windows7 >
上記は TextBox1_Exit で書いているとして、内部で TextBox1 にフォーカスしても その後の処理で、次のフォーカスへ移動してしまいます。 If 文の中でイベント処理後に継続処理をしないよう Cancel=True を追加してください。
Unload Me に関しては提示のコードでエラーなく動作しましたが、どのようなケースで なんと言うエラーになるのでしょうか。 Me がユーザフォームを指していれば問題ないと思いますが、 UnLoad UserForm1 のように明記してもエラーになるでしょうか。 (Mook) 2014/06/26(木) 13:46
私はイベント AfterUpdate を使っていた為に UnLoad Me とするとオートメーションエラー云々 となっていたのです。☆ Exit イベントの意味が良く分かりません。使い分け方法が・・・
早速、Tx_AfterUpdate → Tx_Exit へ書直して思い通りの動作となりました。
Private Sub Tx_Exit(ByVal Cancel As MSForms.ReturnBoolean) Dim PW As String Const Msg = "パスワードが違います" & vbCr & "再入力しますか?"
If UCase(Tx.Value) = "HAJIMEMASU" Then
Unload Me
Else
If MsgBox(Msg, vbYesNo, "") = vbYes Then
Tx = ""
Cancel = True '追加しました。
Else
Unload Me '←この時も即終了したいのですがもう一度回って来ます。
End If
End If
End Sub
[VbNo]でも終わらせる事も可能でしょうか? (中途半端) 2014/06/27(金) 04:52
イベントはこういったところをいろいろと検索で探して読んでみると良いと思いますが、 http://home.att.ne.jp/zeta/gen/excel/c04p30.htm AfterUpdate は変更があった場合、Exit は変更の有無に関係なく、といった違いだと思います。
Unload の挙動はこちらでは再現しないので、他の部分が関係していると思うのですが、 UserForm はシンプルな1フォームの構成でしょうか。
Unload フォーム名 はダメだったということでしょうか?
(Mook) 2014/06/27(金) 09:44
現象は、確認しました(Excel2010)。
Excelユーザーフォームって、バグっぽいのが多いんです、本当に!! この回避方法はいくつか方法がありそうですが、一例です。
Private Sub Textbox1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
Static stopev As Boolean
Dim PW As String
Const Msg = "パスワードが違います" & vbCr & "再入力しますか?"
If Not stopev Then
With Txt
If UCase(.Value) = "HAJIMEMASU" Then
unload Me
Else
If MsgBox(Msg, vbYesNo, "") = vbYes Then
.Value = ""
Cancel = True '追加しました。
Else
stopev = True
unload Me
End If
End If
End With
Else
stopev = False
End If
End Sub
ところで・・・。
拝見したコードを見た限りの推測ですが、提示されたコードは、
パスワードをユーザーに入力させてその内容をチェックするという機能ですよね?
これが掲示板用の例題仕様ならよいですが、
Unloadしてしまったら、パスワード入力が正常になされたのか 失敗して終わったのかわかりませんよね?
( ichinose) 2014/06/27(金) 12:48
Mookさん ichinoseさん
このフォームはファイルを開いた時に動作しています。つまり単独フォームです。 Unload フォーム名・・・も試しましたが同じでした。
パスワードが合致した時の Unload Me はフォームを即終了します。 [VbNo] の時の Unload Me → Application.Quit と変更した所、即座にエクセルを終了します。 ↑の場合はこのラインへ来た時に再度 Tx_Exit のイベント処理となっています。
★只、テキストボックス1個だけでは、Tx_Exitイベントでフォームを閉じるのは 出来ないのですね。×ボタンでの終了も出来ませんでした。 何かフォーカスを得る事の出来るコントロールが必要のようです。
特に支障が無いのですが疑問だけが残りました。 つまらない事に拘ってすみません・・・
ichinoseさんのご指摘とStopEvの追加は良くわかりました。 実際に成功した時はファイルを開くし、間違った時のメッセージも出していますが・・・
有難うございました。
( 中途半端) 2014/06/27(金) 13:24
>実際に成功した時はファイルを開くし、間違った時のメッセージも出していますが とうことは、
>Private Sub Textbox1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
> Static stopev As Boolean
> Dim PW As String
> Const Msg = "パスワードが違います" & vbCr & "再入力しますか?"
> If Not stopev Then
> With Txt
> If UCase(.Value) = "HAJIMEMASU" Then
'ここでそのファイルを開くという処理を行っているのですよね?
> unload Me
> Else
> If MsgBox(Msg, vbYesNo, "") = vbYes Then
> .Value = ""
> Cancel = True '追加しました。
> Else
> stopev = True
> unload Me
> End If
> End If
> End With
> Else
> stopev = False
> End If
>End Sub
パスワードを入力させるという機能って よく使いそうな機能ですよね?
この機能を汎用的に作っておけば、次回に同じような事がしたい場合は、そのプログラムを 呼び出せばよいだけにしておきたいと 思いませんか? 汎用的に使えるようにするためには、ユーザーフォームの中でパスワードが正しく入力された 時の後の処理(ここでは、ファイルを開くという処理)をしてしまうと次回に同じことをするときに 又、その処理用にユーザーフォームを書き換えなければなりません。 私たちがExcel/VBAで使用しているオブジェクトと呼ばれるプログラムを作るための部品は、 処理に応じて、中のプログラムを作り直さなければならない なんてことはないですよね。
そのオブジェクトの持つプロパティやメソッドを使うことで、汎用的に活用できますよね!! ユーザーフォームもオブジェクトです。プロパティやメソッドをうまく使えば、汎用性を高めることが出来ます。
新規ブックにて、ユーザーフォームを作成してください(UserForm1)。
コントロールは、テキストボックスを一つだけ配置してください(TextBox1)。
UserForm1及び、TextBox1の大きさや位置は、コードで調整しますから、初期配置は、適当でよいです。
このUserForm1は、パスワードの入力を促し、これを予め設定されているパスワードと比較し、 正しいか否かを判断します。
プロパティ
InitMes テキストボックスに初期表示するメッセージを登録します。
PassWord 比較するパスワードを登録します。
Result 設定されたパスワードと入力された文字列を比較し、結果を返します。
True パスワードと一致した
False パスワードと一致しない又は、閉じるボタンが押された
メソッド
show パスワードチェックダイアログを表示し、パスワードチェックを行います。
このUserForm1は、上記のインターフェースで操作します。
ではコードです。
UserForm1のモジュール
'====================================================================
Option Explicit
Private imes As String
Private psw As String
Private Judgment As Boolean
Private stopev As Boolean
'====================================================================
Property Let InitMes(mes As Variant)
imes = mes
End Property
'====================================================================
Property Let PassWord(mes As Variant)
psw = mes
End Property
'====================================================================
Property Get Result() As Boolean
Result = Judgment
End Property
'====================================================================
Private Sub TextBox1_Change()
If Not stopev Then
With TextBox1
If .Value = "" Then
stopev = True
.PasswordChar = ""
.Value = imes
.SelStart = 0
.SelLength = Len(.Value)
stopev = False
.setfocus
Else
.PasswordChar = "*"
End If
End With
End If
End Sub
'====================================================================
Private Sub UserForm_Activate()
With TextBox1
stopev = True
.Value = imes
stopev = False
.SelStart = 0
.SelLength = Len(.Value)
.setfocus
End With
End Sub
'====================================================================
Private Sub UserForm_Initialize()
With Me
.Width = 280
.Height = 108
With .TextBox1
.Left = 54
.Top = 30
.Width = 156
.Height = 24
.PasswordChar = ""
.Font.Size = 14
End With
End With
Judgment = False
End Sub
'====================================================================
Private Sub textbox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
Dim PW As String
Const Msg = "パスワードが違います" & vbCr & "再入力しますか?"
If KeyCode = vbKeyReturn Then
With TextBox1
If UCase(.Value) = UCase(psw) Then
Judgment = True
Me.Hide
Else
If MsgBox(Msg, vbYesNo, "") = vbYes Then
.Value = ""
KeyCode = 0
Else
Judgment = False
Me.Hide
End If
End If
End With
Else
TextBox1.PasswordChar = "*"
End If
End Sub
'====================================================================
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
If CloseMode = 0 Then
Judgment = False
Cancel = True
Me.Hide
End If
End Sub
標準モジュールに
'===========================================================================
Sub test()
With UserForm1
.InitMes = "パスワード" '初期表示文字列の登録
.PassWord = "ichinose" 'パスワードの登録
.Show 'UserForm1の表示
If .Result Then '入力文字列がパスワードと一致
MsgBox "ok" 'ここでファイルを開く処理
Else '閉じるボタンが押されたか パスワードと不一致
MsgBox "パスワードは、認識できません"
End If
End With
unload UserForm1
End Sub
testを実行してみてください、ダイアログが表示されますから、パスワード ichinose を入力したり 間違った文字列を入力して試してください。入力確定は、Enterキーです。
入力文字列は、*でマスクされます。
このように作成しておくと、UserForm1は、入力文字列チェック用に他の場面でも使えますよね!! バグがない限りは・・・。
又、UserForm1は、文字列をチェックするという機能だけを考慮して、機能拡張を考えることも この機能として独立しているのですから、考えがまとまりやすいと思いますよ!!
( ichinose) 2014/06/27(金) 21:09
先月27日の自分の投稿が最後と思っていたのと、病気で入院していた事でこちらを見ていませんでした。
ichinoseさんのコードを見て感激しました。スラスラと書かれていて私にはとっても出来無い事です。
私の質問でテキストボックスの入力間違いが有った場合、同じテキストボックスに戻る方法について
(1)[AfterUpdate]では[Cancel]の引数がないので再度のフォーカス取得は出来ないのでしょうか?
可能であるならばご指導ください。
(2)このサンプルの様に[textbox1_Change][textbox1_KeyDown] の2つイベント処理をすれば出来るのでは?
これから試したいと思います。
( 中途半端) 2014/07/18(金) 12:33
>[AfterUpdate]では[Cancel]の引数がないので再度のフォーカス取得は出来ないのでしょうか?
既投稿のTextbox1_Exitイベントと同じような動作なら・・・、
ユーザーフォームのモジュールに
Option Explicit
Private Sub TextBox1_AfterUpdate()
Const Msg = "パスワードが違います" & vbCr & "再入力しますか?"
With TextBox1
If UCase(.Value) = "HAJIMEMASU" Then
Me.Hide
Else
If MsgBox(Msg, vbYesNo, "") = vbYes Then
.Value = ""
Application.OnTime Now(), "'ctrl_SetFocus """ & Me.Name & """,""TextBox1""'"
Else
Me.Hide
End If
End If
End With
End Sub
標準モジュールに
Sub test()
UserForm1.Show
Unload UserForm1
End Sub
'=============================================================================
Sub ctrl_SetFocus(ByVal frmnm As String, ByVal ctrlnm As String)
Dim frm As Object
For Each frm In UserForms
If UCase(frm.Name) = UCase(frmnm) Then
frm.Controls(ctrlnm).SetFocus
Exit For
End If
Next
End Sub
これでtestを実行してみてください。
>このサンプルの様に[textbox1_Change][textbox1_KeyDown] の2つイベント処理をすれば出来る ExitイベントやAfterUpdateイベントでは、中途半端さんが記述されたように
>★只、テキストボックス1個だけでは、Tx_Exitイベントでフォームを閉じるのは >出来ないのですね。×ボタンでの終了も出来ませんでした。 >何かフォーカスを得る事の出来るコントロールが必要のようです。
という事になってしまいます。よって、テキストボックスの他にフォーカスを持つコントロールが ない場合の事例として、投稿したのがKeydownイベントを使ったコードです。
この場合、データのチェックやテキストボックスに再入力を促すコードは、すべてKeydownイベントが行っています。Changeイベントは、テキストボックスの初期表示文字列の始末をしているだけです。
確認してみてください
(ichinose) 2014/07/23(水) 00:29
KeyDownイベントの事例が難しすぎたかもしれません。 もうちょっと、仕様を簡単にしました。
>新規ブックにて、ユーザーフォームを作成してください(UserForm1)。
>コントロールは、テキストボックスを一つだけ配置してください(TextBox1)。
>UserForm1及び、TextBox1の大きさや位置は、コードで調整しますから、初期配置は、適当でよいです。
>このUserForm1は、パスワードの入力を促し、これを予め設定されているパスワードと比較し、
>正しいか否かを判断します。
>プロパティ
InitMes UserForm1の左上に表示するメッセージを登録します。
>PassWord 比較するパスワードを登録します。
>Result 設定されたパスワードと入力された文字列を比較し、結果を返します。
True パスワードと一致した
False パスワードと一致しない又は、閉じるボタンが押された
>メソッド
>show パスワードチェックダイアログを表示し、パスワードチェックを行います。
>このUserForm1は、上記のインターフェースで操作します。
というようにInitMesというプロパティの機能をちょっとかえるだけで少し簡単になり、 KeyDownイベントの役割が見えてきます。
UserForm1のモジュールに
Private psw As String
Private Judgment As Boolean
Private stopev As Boolean
'====================================================================
Property Let InitMes(mes As Variant)
Me.Caption = mes
End Property
'====================================================================
Property Let PassWord(mes As Variant)
psw = mes
End Property
'====================================================================
Property Get Result() As Boolean
Result = Judgment
End Property
'====================================================================
Private Sub UserForm_Initialize()
With Me
.Width = 280
.Height = 108
With .TextBox1
.Left = 54
.Top = 30
.Width = 156
.Height = 24
.PasswordChar = "*"
.Font.Size = 14
End With
End With
Judgment = False
End Sub
'====================================================================
Private Sub textbox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
Dim PW As String
Const Msg = "パスワードが違います" & vbCr & "再入力しますか?"
If KeyCode = vbKeyReturn Then
With TextBox1
If UCase(.Value) = UCase(psw) Then
Judgment = True
Me.Hide
Else
If MsgBox(Msg, vbYesNo, "") = vbYes Then
.Value = ""
KeyCode = 0
Else
Judgment = False
Me.Hide
End If
End If
End With
End If
End Sub
'====================================================================
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
If CloseMode = 0 Then
Judgment = False
Cancel = True
Me.Hide
End If
End Sub
標準モジュールに
'===========================================================================
Sub test()
With UserForm1
.InitMes = "パスワード" '初期表示文字列の登録
.PassWord = "ichinose" 'パスワードの登録
.Show 'UserForm1の表示
If .Result Then '入力文字列がパスワードと一致
MsgBox "ok" 'ここでファイルを開く処理
Else '閉じるボタンが押されたか パスワードと不一致
MsgBox "パスワードは、認識できません"
End If
End With
unload UserForm1
End Sub
以上です。testを実行してみてください。 (ichinose) 2014/07/23(水) 06:21
[ 一覧(最新更新順) ]
YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki.
Modified by kazu.