ユーザーフォーム上の数値入力や日付入力の工夫

ユーザーフォーム上の入力では数字や日付でもテキストボックスを使用します。ワークシートのセルのように書式設定で編集する機能がありませんが、イベント記述で似たようなことを行なうことができます。

日付と数値(3桁カンマ編集)の入力支援のサンプルです。
フォーム上の数値、日付の編集
(画像をクリックすると、このサンプルがダウンロードできます)
立ち上げると、このようなユーザーフォームが表示されます。
「日付」項目は月日入力で年が自動的に付加されます。
「金額」項目は項目に入るとカンマがなくなり、項目から抜けると3桁ごとにカンマが付加されます。

それぞれ3項目ずつありますが、処理は共通プロシージャに集約しています。


Option Explicit
Const g_cnsDate = "YYYY/MM/DD"

' TextBoxのEnter,Exitイベントから共通処理を呼ぶ
Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
    Cancel = FP_DateEdit(TextBox1)
End Sub

Private Sub TextBox2_Enter()
    Call GP_NumEdit(TextBox2)
End Sub

Private Sub TextBox2_Exit(ByVal Cancel As MSForms.ReturnBoolean)
    Cancel = FP_NumEdit(TextBox2)
End Sub

Private Sub TextBox3_Exit(ByVal Cancel As MSForms.ReturnBoolean)
    Cancel = FP_DateEdit(TextBox3)
End Sub

Private Sub TextBox4_Enter()
    Call GP_NumEdit(TextBox4)
End Sub

Private Sub TextBox4_Exit(ByVal Cancel As MSForms.ReturnBoolean)
    Cancel = FP_NumEdit(TextBox4)
End Sub

Private Sub TextBox5_Exit(ByVal Cancel As MSForms.ReturnBoolean)
    Cancel = FP_DateEdit(TextBox5)
End Sub

Private Sub TextBox6_Enter()
    Call GP_NumEdit(TextBox6)
End Sub

Private Sub TextBox6_Exit(ByVal Cancel As MSForms.ReturnBoolean)
    Cancel = FP_NumEdit(TextBox6)
End Sub
まず、イベント記述ですが、各テキストボックスの「Enter」「Exit」(日付は「Exit」のみ)のイベントプロシージャを記述しますが、ここでは共通プロシージャをコントロール(オブジェクト)を引数にして呼び出すだけです。「Exit」プロシージャでは字類チェックを行なうので、エラー時は項目から抜けないようにCancelを戻り値にしたFunctionプロシージャを呼び出します。
実際は、この下に「TextBox3」〜「TextBox6」までの同じようなプロシージャが6つあります。

では、上記イベントプロシージャから呼ばれる共通プロシージャです。

' 数字項目入力用編集
Private Sub GP_NumEdit(objTextBox As MSForms.TextBox)
    ' 3桁カンマ付き表示を元に戻す
    objTextBox.Text = objTextBox.Tag
End Sub

' 数字項目表示用編集
Private Function FP_NumEdit(objTextBox As MSForms.TextBox) As Boolean
    Dim strNum As String
    Dim crnNum As Currency

    FP_NumEdit = False
    strNum = Trim$(objTextBox.Text)
    If IsNumeric(strNum) = True Then
        crnNum = CCur(strNum)
        ' 実数はTagに格納
        objTextBox.Tag = crnNum
        ' 3桁カンマ付きで編集
        objTextBox.Text = Format$(crnNum, "#,##0")
    Else
        MsgBox "数字ではありません。"
        objTextBox.Tag = 0
        FP_NumEdit = True
    End If
End Function

' 日付項目表示用編集
Private Function FP_DateEdit(objTextBox As MSForms.TextBox) As Boolean
    Dim strDate As String
    Dim dteDate As Date

    FP_DateEdit = False
    ' 左4桁が数字でない場合は年を付加
    strDate = Trim(objTextBox.Text)
    If IsNumeric(Left$(strDate, 4)) <> True Then
        strDate = Year(Date) & "/" & strDate
    End If
    If IsDate(strDate) = True Then
        dteDate = CDate(strDate)
        ' 実数はTagに格納
        objTextBox.Tag = CLng(dteDate)
        ' 3桁カンマ付きで編集
        objTextBox.Text = Format$(dteDate, g_cnsDate)
    Else
        MsgBox "日付ではありません。"
        objTextBox.Tag = 0
        FP_DateEdit = True
    End If
End Function

Private Sub UserForm_Initialize()
    TextBox1.Tag = CLng(Date)
    TextBox1.Text = Format$(TextBox1.Tag, g_cnsDate)
    TextBox2.Tag = 0
    TextBox2.Text = 0
    TextBox3.Tag = CLng(Date)
    TextBox3.Text = Format$(TextBox1.Tag, g_cnsDate)
    TextBox4.Tag = 0
    TextBox4.Text = 0
    TextBox5.Tag = CLng(Date)
    TextBox5.Text = Format$(TextBox1.Tag, g_cnsDate)
    TextBox6.Tag = 0
    TextBox6.Text = 0
End Sub
@
実数は「Tag」に書き込んであるので、その項目に入る時にカンマ編集を解除し実数だけの表示に戻します。
A
数値チェックがOKであれば、実数を「Tag」に書き込みます。
B
Text」は3桁カンマ編集に置き換えます。
C
数値チェックがNGの場合は、この項目脱出をCancelにします。Functionプロシージャなので「True」がイベントプロシージャの「Cancel」に通知されTabキー等での項目移動がキャンセルされます。
D
日付の「Exit」プロシージャからの共通処理では、まず、文字列の先頭に年4桁があるかを判断(4桁数値かどうか)し、年がない場合は現在年を付加します。
E
日付判定がOKであれば、シリアル値を「Tag」に書き込みます。
F
Text」は「YYYY/MM/DD」形式(g_cnsDate)編集に置き換えます。
フォームの初期化時に各「Tag」「Text」を初期化(初期値を埋め込む)しておいて下さい。

編集処理は共通プロシージャ化しているので合理化できたといえばそうですが、TextBoxをたくさん並べるような処理では記述が大変です。そこで、「Enter」「Exit」をクラス化してまとめてしまうことを考えているのが、次項です。