Mutable_Yunの業務改善ブログ

VBA勉強中の非エンジニア会社員向けのブログです。業務改善についても触れています。

VBA テキストボックスの基本|ユーザーフォームの使い方

この記事では、ユーザーフォームでテキストボックスを一工夫することによって気の利いたユーザーインタフェースにする事を目指します。エクセルVBAで自動化ツールを作成している非エンジニアの会社員を読者に想定しています。

目次

気の利いたユーザーフォームに仕上げる

今回はシンプルな機能のユーザーフォームに手を加え、誤入力に強いものに仕上げます。サンプルとして用意したユーザーフォームは下の図の通りです。

テキストボックスと登録ボタンのみのシンプルなユーザーフォーム
今回、完成度を高めるユーザーフォーム

ユーザー名を入力してもらい、登録ボタンを押すとA1セルにユーザー名が書き込まれるというシンプルな機能です。

ユーザーフォームを使うメリットを理解する

ユーザーフォームを使うに当たり、そのメリットを把握しておきましょう。

入力を制御できる

VBAで作るマクロツールの基本的な動きは、入力値を受け取り、何かの処理を行い、結果を出力する事です。

入力値を受け取り、何かの処理を行い、出力するイメージ
マクロツールのイメージ

入力値をユーザーに入力してもらう場合、人が作業する以上、意図と違う操作をされてしまう可能性があります。ユーザーフォームを使う事によって、意図せぬ値を入力された時の処理を予めプログラムとして組み込んでおくことができる事がユーザーフォームのメリットです。

使い勝手を向上させられる

もう一つのメリットとして視覚的に分かりやすく、使い勝手のいいツールを作成出来ることです。ユーザーとプログラムをつなぐ部分をユーザーインターフェースと言います。ユーザーインタフェースにメッセージボックスやインプットボックスを使うより細かな設計や細かな挙動のプログラムが可能になる為、使い勝手の良いツールに仕上げることが可能となります。

意図せぬ操作によるエラーを防ぐ

それでは一点目のメリットである意図せぬ操作によるエラーを防ぐ方法を具体的に見て行きます。具体的には、下記の機能を盛り込みます。

  • 数値のみの入力なら再入力を促す
  • ユーザー名を入力するテキストボックスが空欄の状態で登録ボタンを押すと入力を促すテキストを表示出して処理を止める
  • ユーザ-名が1文字なら最低二文字以上でないと登録できない旨のテキストを表示する

まず、上記の3点を盛り込むために設計を考えます。処理の順序としては下記の通りです。

  1. 文字数を判定する
  2. 入力値が文字列かどうか判定
  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で値を設定するでは、さらに一工夫加えてユーザーフォームの完成度を高めます。