Wordのユーザーフォームでは、ユーザーからデータを取得することがよく使用されますが、入力ミス、スペルは正しいものの無効な値、あるいはコントロールが空白のままになっているなど、ドキュメントが使い物にならなくなる可能性があります。幸いなことに、VBAコードを少し追加するだけで、入力値が特定の属性に適合しているかどうかを確認できます。この記事では、入力値をドキュメントにコミットする前に検証する簡単な例を見ていきます。
この記事のサンプルフォームとコントロールは、Wordのユーザーフォームオブジェクトに関する基本的な知識があることを前提としています。ユーザーフォームの作成方法がわからない場合は、この記事を読み進める前に「宛名書き用Wordユーザーフォームを作成する10ステップ」をお読みください。例を簡素化するため、ここでは手法に必要なプロパティのみを変更します。ご自身のユーザーフォームを作成することも、デモ用の.docmファイルまたは.docファイルをダウンロードすることもできます。
注意:一部の Web ベースの文字はエラーを返すため、この Web ページからコードをコピーして貼り付けないでください。
レベルの検証
データの検証はドアを開けることに例えることができます。そのドアとは次のようなものです。
- 開ける
- 半開き
- 閉鎖
名前はオープンコントロールの最も一般的な用途です。ドアが開いているため、任意の名前をドキュメントに渡すことができます。入力値を表示し、確定する前にユーザーに確認を求めることは有効ですが、それ以上に、このタイプの入力を検証することはほとんどできません。ユーザーが入力した内容はすべてドアを通過できるからです。
半開きのコントロールは、値が収まる限り通過させます。値はコードによって通過を許可される前に、いくつかのテストに合格する必要があります。例えば、米国の郵便番号の入力をチェックする場合、各文字が数字であること、そして文字数が5文字(または9文字)であることを確認することができます。しかし残念ながら、入力された郵便番号が対応する住所の正しい郵便番号であるかどうかを確認することはできません。
閉じたコントロールは、ユーザーにリストから項目を選択させるように強制します。これにより、ユーザーがキーボードから新しい値や一意の値を入力することがなくなり、入力ミスや無効な入力からデータを保護できます。ユーザーが利用可能な選択肢から値を選択した場合にのみ、Word はドアを開けて値を入力します。しかし、残念ながら、ユーザーが間違った項目を選択する可能性は依然としてあります。
参照: Excel のデータ検証機能を使用してデータ入力ミスを防ぐ方法
例を開く
オープンコントロールは、不正なデータがドキュメントに入り込むための扉を開いてしまう可能性があります。他に選択肢がない場合にのみ使用してください。前述のように、名前は良い例です。プログラムで名前を制限すると、避けたい落とし穴に陥ってしまうからです。図Aは、 2つのテキストボックスコントロールと1つのコマンドボタンを含むシンプルなユーザーフォームを示しています。(フォームとコントロールのプロパティについては、表Aを参照してください。)
図A
新しい名前の値を受け入れるには、単純なテキスト ボックス コントロールを使用します。
表A
少なくとも、ユーザーの入力をそのまま繰り返し、値を目的の目的にコミットする前に確認を求めることで、ユーザーに入力ミスを修正する機会を与えることができます。この例を拡張するために、姓と名の両方の入力を求めるビジネスルールも適用します。これらは、フォームのデータをドキュメントにコミットするコマンドボタンから実行できます。これを実現するには、コマンドボタンをダブルクリックし、リストAのコードをモジュールに追加します。
リストA
Private Sub cmdSendtoDocument_Click()
'Last ditch validation before committing input values to document.
Dim booConfirmation As Boolean
'Check for first and last name values; both are required.
If Len(txtLastName) = 0 Or Len(txtFirstName) = 0 Then
MsgBox "Both first and last names are required.", vbOKOnly, "Input Error"
If Len(txtLastName) = 0 Then
txtLastName.SetFocus
Else
txtFirstName.SetFocus
End If
Exit Sub
End If
'Display name so user can check and confirm.
booConfirmation = MsgBox("Is the name " & txtFirstName & " " _
& txtLastName & " correct?", vbYesNo)
If booConfirmation Then
'This is where you'd add code that commits the input values to the document.
Exit Sub
Else
txtLastName.SetFocus
End If
End Sub
どちらかの Len() 関数が 0 を返す場合、VBA は図 Bに示すメッセージを表示し、ユーザーがエラーを修正できるように空白のコントロールを選択して、プロシージャを終了します ([マクロの実行] をクリックするか、F5 キーを押してユーザー フォームを実行し、テスト値を入力できます)。両方のコントロールにテキストが含まれている場合は、図 Cに示すように、次のスニペットで名前が表示されます。[はい] をクリックすると、名前がドキュメントにコミットされます。現時点では、この例には実際の目的がないため、コードは他に何も行いません。[いいえ] をクリックすると、フォーカスが txtLastName に戻り、ユーザーはどちらの名前も変更できます。このコードは、どちらの名前 (名または姓) を修正する必要があるかを直感的に判断できるほどではありません。
図B
ユーザーがどちらかの名前コントロールを空白のままにした場合、エラー メッセージを表示します。
図C
ユーザーに名前の確認を依頼します。
名前の値をチェックするためにコマンドボタンを使用したのは、1つではなく2つの値を考慮しているためです。ユーザーの意図に合わせてチェックを調整するのはほぼ不可能です。適用したビジネスルールにもかかわらず、ユーザーは片方または両方の名前に意味不明な文字列を入力する可能性があります。次の例では、もう少し厳密にすることができます。
半開きの例
先ほど説明した郵便番号の例は、半角のコントロールを説明するのに最適です。ここでは、数字を5文字だけ入力できるコードを使用します。これを実現するには、ユーザーフォームにテキストボックスを追加し、コントロールの名前をtxtZIPに設定し、TabIndexプロパティを2に設定します。次に、txtZIPをダブルクリックし、リストBに示すコードをモジュールに追加します。
リストB
Private Sub txtZIP_Exit(ByVal Cancel As MSForms.ReturnBoolean)
'Validate ZIP code entries. Each must have five numeric digits.
Dim bytLength As Byte
Dim booNumeric As Boolean
'Must be 5 AND True to be a valid ZIP code.
bytLength = Len(txtZIP)
booNumeric = IsNumeric(txtZIP)
If bytLength <> 5 Then
MsgBox "You must enter a five-digit ZIP Code.", vbOKOnly, "ZIP Code error"
txtZIP.SetFocus
Exit Sub
ElseIf booNumeric = False Then
MsgBox "Your ZIP Code value contains alpha characters.", vbOKOnly, _
"ZIP Code errors"
txtZIP.SetFocus
Exit Sub
End If
End Sub
コントロールを終了するとイベントがトリガーされます。図Dは、英文字と文字数が多すぎる(あるいは少なすぎる)場合の結果を示しています。ドアを少し閉じたため、一部の値だけが通過することになります。ただし、ユーザーが入力した5桁の郵便番号が実際の郵便番号であるか、または対応するレコードの正しい郵便番号であるかを保証する方法はありません。
図D
コードは無効なエントリを拒否します。
参照: Excel でプログラム的に検証コントロール リストを更新してアルファベット順に並べる方法
閉じた例
可能であれば、閉じたコントロールを使用してください。そうすれば、ユーザーが間違った値を選択したとしても、実際の値が正しいことがわかります。リストコントロールとオプションコントロールは、このニーズに最も適しています。閉じたコントロールを説明するために、コンボボックスコントロールを追加し、そのリストに「はい」、「いいえ」、「未定」の3つの項目を入力します。
まず、コンボボックスコントロールを追加し、cboClosedという名前を付け、 TabIndex を 3 に設定し、 MatchRequired プロパティを True に設定します(デフォルトでは、このコントロールはキーボード入力を受け付けます)。次に、ユーザーフォームの背景(コンボボックスではありません)をダブルクリックし、リストCに示すコードをユーザーフォームのモジュールに追加します。フォームを実行すると、この手順によってコンボボックスのリストにデータが設定されます。
リストC
Private Sub UserForm_Initialize()
'Populate list.
With cboClosed
.AddItem "Yes"
.AddItem "No"
.AddItem "Undecided"
End With
End Sub
ユーザーはキーボードから値を入力できません。コントロールはリスト内の項目のみを受け入れます。ここで止めることもできますが、まだ考慮すべき点があります。リストには3つの項目がありますが、4つ目の選択肢としてnull値があります。このままでは、ユーザーは何も選択できません。
NULL値自体は問題ではありませんが、許容するのであれば、適切に対応する必要があります。そうしないと、式や関数の結果が変わってしまうなど、予期せぬ結果が生じる可能性があります。さらに、並べ替えやフィルタリングされたデータセットでは、NULL値が見落とされてしまう可能性があります。Word文書ではこのような問題が発生する可能性は低いですが、少なくとも文書の途中に空のフィールドが存在する可能性があります。コントロールのExitプロシージャにNULL値のチェックを追加するには、コントロールのモジュールを開き、リストDに示すコードを入力します。
リストD
Private Sub cboClosed_Exit(ByVal Cancel As MSForms.ReturnBoolean)
'Check for selected item; user must select an item from the list.
If cboClosed = "" Then
MsgBox "You must choose an item from the list.", vbOKOnly, _
"Input Error"
Cancel = True
cboClosed.SetFocus
End If
End Sub
ユーザーがコントロールを空のままにした場合、このコードは図Eに示す情報メッセージを表示します。ユーザーがリストから適切な値を選択するまで、ドアは閉じられたままです。ただし、ユーザーがレコードに対して正しい項目を選択することを保証する方法はありません。
図E
このコントロールは、コンボ ボックス コントロールのリストから値を選択するように強制します。
検証は始まりです
ユーザー入力を検証する際には、想定される応答内容を考慮し、可能な限り柔軟に対応すると同時に、データの妥当性、ひいてはそこから得られる情報の妥当性も確保する必要があります。この議論から、重要な点に気づきましたか?最善を尽くすことはできますが、多くのことはユーザー次第です。最善を尽くしたとしても、ユーザーは間違いを犯す可能性があります。データ検証は必要不可欠であり、データ保護に大きく貢献しますが、エラーを完全に防ぐものではありません。
最も効率的(邪魔にならない)フローを選択することをお勧めします。つまり、どこで、いつデータを検証するかということです。最初の例では、コマンドボタンをクリックして検証コードを実行します。2つ目と3つ目の例では、コントロールを終了するとコードが実行されます。入力されたエントリをすぐに検証することも、データ入力タスクが完了してから値をドキュメントにコミットする前に検証することもできます。多くの場合、1つのユーザーフォームで両方を使用します。
適切なエラー処理を必ず含めてください。例にはエラー処理が含まれていません。ドアの例えは私独自のもので、プロパティやメソッドに記載されている技術的な参考資料ではありません。
Officeに関するご質問をお送りください
読者からの質問には可能な限りお答えしますが、必ずお答えできるとは限りません。リクエストがない限り、ファイルは送信しないでください。添付ファイル付きの初回サポートリクエストは未読のまま削除されます。ご質問を明確にするために、データのスクリーンショットを送信していただくことも可能です。お問い合わせの際は、できるだけ具体的にご記入ください。例えば、「ワークブックのトラブルシューティングを行い、問題点を修正してください」という質問では返答がないかもしれませんが、「この数式が期待どおりの結果にならない理由を教えていただけますか?」という質問であれば、回答が得られる可能性があります。ご使用のアプリとバージョンを明記してください。読者サポートにあたり、TechRepublicから時間や専門知識の報酬を受け取ることはありません。また、サポートした読者から料金を請求することもありません。お問い合わせは[email protected]までお願いいたします。
また読んでください…
- Outlookをモバイルデバイスと同期するための10のヒント
- Office Q&A: Word の表の書式設定にかかる時間を節約する方法
- Excelシートのグループを簡単(だけど珍しい)な方法で使用する6つのヒント
- Outlook の予定表ビューを仕事のルーチンに合わせて設定する