この記事では、ユーザーフォームでテキストボックスを一工夫することによって気の利いたユーザーインタフェースにする事を目指します。エクセルVBAで自動化ツールを作成している非エンジニアの会社員を読者に想定しています。
目次
気の利いたユーザーフォームに仕上げる
今回はシンプルな機能のユーザーフォームに手を加え、誤入力に強いものに仕上げます。サンプルとして用意したユーザーフォームは下の図の通りです。
ユーザー名を入力してもらい、登録ボタンを押すとA1セルにユーザー名が書き込まれるというシンプルな機能です。
ユーザーフォームを使うメリットを理解する
ユーザーフォームを使うに当たり、そのメリットを把握しておきましょう。
入力を制御できる
VBAで作るマクロツールの基本的な動きは、入力値を受け取り、何かの処理を行い、結果を出力する事です。
入力値をユーザーに入力してもらう場合、人が作業する以上、意図と違う操作をされてしまう可能性があります。ユーザーフォームを使う事によって、意図せぬ値を入力された時の処理を予めプログラムとして組み込んでおくことができる事がユーザーフォームのメリットです。
使い勝手を向上させられる
もう一つのメリットとして視覚的に分かりやすく、使い勝手のいいツールを作成出来ることです。ユーザーとプログラムをつなぐ部分をユーザーインターフェースと言います。ユーザーインタフェースにメッセージボックスやインプットボックスを使うより細かな設計や細かな挙動のプログラムが可能になる為、使い勝手の良いツールに仕上げることが可能となります。
意図せぬ操作によるエラーを防ぐ
それでは一点目のメリットである意図せぬ操作によるエラーを防ぐ方法を具体的に見て行きます。具体的には、下記の機能を盛り込みます。
- 数値のみの入力なら再入力を促す
- ユーザー名を入力するテキストボックスが空欄の状態で登録ボタンを押すと入力を促すテキストを表示出して処理を止める
- ユーザ-名が1文字なら最低二文字以上でないと登録できない旨のテキストを表示する
まず、上記の3点を盛り込むために設計を考えます。処理の順序としては下記の通りです。
- 文字数を判定する
- 入力値が文字列かどうか判定
- 数値でなければ、文字数に応じて処理分岐
入力データの型を制限する
それでは入力データの方を制限する部分を、入力値の文字数のカウント部分から作成していきます。
◆ 文字数を判定する
Private Sub 登録cb_Click() Dim 入力された値の文字数 As Long 入力された値 = 入力tb.Value 入力された値の文字数 = Len(入力された値) Select Case 入力された値の文字数 Case 0 'ここにテキストボックスが空欄の時の処理 Case 1 'ここにテキストボックスの値が1文字時の処理 End Select End Sub
なお、今回はユーザーフォームの解説なのでそのままSubプロシジャに記述しています。本来は処理内容や判定をする記述を別のSubプロシジャやFunctionプロシジャに記述して、イベントプロシジャはそれらを呼び出すだけ、と言うようなシンプルな記述するような工夫を行います。
想定外の入力の場合、正しい対応を促す
◆文字列の設定されていないラベルを設置する
メッセージボックスを表示させる事によって、正しい入力を促すことも考えられます。しかし、メッセージボックスはユーザーがOKや右上の×を押して消さなければなりませんので、ややストレスがあります。ここは、ユーザーの操作性を考えて、ユーザーフォーム内にテキストを表示させるようにします。
ラベルをユーザーフォーム内に設置します。
次にラベルのプロパティを設定します。表示⇒プロパティウィンドウでプロパティウィンドウを表示させて下さい。デフォルトでは何も表示させる必要がないため、Captionプロパティは空白にしておきます。目立つように文字の色は赤にしました。
オブジェクト名は分かりやすい様に「エラーメッセージ」としました。
◆ 文字数を判定して処理を分岐する。
次にSelect Case文の中身を作成します。
Private Sub 登録cb_Click() Dim 入力された値 As String Dim 入力された値の文字数 As Long 入力された値の文字数 = Len(入力tb.Value) Select Case 入力された値の文字数 Case 0 エラーメッセージ.Caption = "ユーザー名が入力されていません。" Exit Sub Case 1 エラーメッセージ.Caption = "ユーザー名は2文字以上で入力して下さい。" Exit Sub End Select End Sub
ポイントはエラーメッセージ.Captionの部分です。プロパティを予め設定しておくのではなく、プログラムの処理の中で設定することができます。この方法で、ユーザーの操作に応じて動的に表示させるメッセージを変えることができます。
もう一点、忘れてはいけないのはExit Subです。ここでイベントプロシジャを終了しないと、その後の処理が実行されてしまうので、不具合のある入力データの場合はExit Subを使ってそれ以上プログラムが進まないようにしておきます。
実行してみるとこのようになります。
◆ 入力値が文字列かどうかを確認して適切に処理する
次に123のような数値が入力されると困るので値が文字列かどうかを判定します。
Private Sub 登録cb_Click() Dim 入力された値 As String Dim 入力された値の文字数 As Long 入力された値の文字数 = Len(入力tb.Value) Select Case 入力された値の文字数 Case 0 エラーメッセージ.Caption = "ユーザー名が入力されていません。" Exit Sub Case 1 エラーメッセージ.Caption = "ユーザー名は2文字以上で入力して下さい。" Exit Sub End Select If IsNumeric(入力tb.Value) Then エラーメッセージ.Caption = "数値のみの名前は無効です" 入力tb.Value = "" 入力tb.SetFocus Exit Sub Else 入力された値 = 入力tb.Value End If End Sub
Isnumeric関数を使ってテキストボックス内の値の型が数値かどうかを判定します。数値の場合はIsnumeric関数がTrueを返すので、その時は「数値のみの名前は無効です」と表示させています。
その次の行の、入力tb.Value = "" の記述はテキストボックスの中身を空白に戻しています。この処理は必須ではありません。しかし、ユーザーの気持ちを考えると、入力が受け付けられなかったら、修正する為に入力した値を消すはずです。よって、ユーザーの気持ちになって、再入力がしやすいように値を初期化しておくのが親切です。
さらに、一工夫加えています。入力tb.SetFocusの部分です。登録を押した瞬間に選択されたコントロールが登録ボタンに移ります。これではユーザーが再入力の為にテキストボックスを再度クリックする必要があり、手間が掛かります。と言うわけで、テキストボックスにカーソルを移動しています。このカーソルが当たっている事をフォーカスが当たっていると言います。フォーカスを当てるメソッドがSetFocusです。
仕上げを行う
最後にA1セルにユーザーが入力した値を書き込む命令を記述します。
Private Sub 登録cb_Click() Dim 入力された値 As String Dim 入力された値の文字数 As Long 入力された値の文字数 = Len(入力tb.Value) Select Case 入力された値の文字数 Case 0 エラーメッセージ.Caption = "ユーザー名が入力されていません。" Exit Sub Case 1 エラーメッセージ.Caption = "ユーザー名は2文字以上で入力して下さい。" Exit Sub End Select If IsNumeric(入力tb.Value) Then エラーメッセージ.Caption = "数値のみの名前は無効です" 入力tb.Value = "" 入力tb.SetFocus Exit Sub Else 入力された値 = 入力tb.Value End If エラーメッセージ.Caption = "" Sheets(1).Cells(1, 1) = 入力された値 End Sub
End Subの直前に2行を加えただけです。エラーメッセージ.Caption = ""がポイントです。これがないと、空白や数値のみのエラーが起きた後に修正して有効な値を入力しても、エラーメッセージが残るので不自然です。もしくはUnload Meを使って、ユーザーフォームを終了しても構いません。
このように工夫次第でユーザーフォームはどんどん使い勝手の良いユーザーインターフェースになっていきます。次回の記事テキストボックスにInitializeで値を設定するでは、さらに一工夫加えてユーザーフォームの完成度を高めます。