EXCEL VBA でユーザーフォーム上のコントロールの未入力を検証する

Pocket

 今回はフォーム上のコントロールの形式的検証のうち,未入力のコントロールをチェックするコードを紹介します.フォーム上に入力・選択可能なコントロールとしては以下が挙げられます.

  • チェックボックス
  • オプションボタン
  • コンボボックス
  • リストボックス
  • テキストボックス

 オプションボタンおよびチェックボックスはフレーム内に配置してあるものとし,一つのフレーム内にオプションボタンとチェックボックスは混在していないと仮定しています.

UserForm1

未入力のコントロールを検証する関数を共通化する

 フォーム上のコントロールの未入力のチェックは複数のコマンドボタンから共通して呼び出される機能であるため,共通化したほうがコーディングの重複をなくせます.そのため標準モジュールを追加して関数として実装することにします.下記の関数で戻り値を Variant 型にしているのは未入力のコントロール名を文字列型で受けているためです.メッセージボックスを表示する必要がなければ戻り値を Boolean 型にした方がよいでしょう.また Select case 節でコントロールの種類を群別しているため case else 節でコントロール数を減算する処理を追加していますが,If … Then … ElseIf … 節で群別すればその記述は不要になります.

Option Explicit

Function CheckControls(myForm As MSForms.UserForm) As Variant
    Dim Ctrl        As MSForms.Control
    Dim CheckCnt    As Long
    Dim myCnt       As Long
    Dim CheckStr    As String
    CheckControls = False
    CheckCnt = 0
    myCnt = 0
    CheckStr = ""
    For Each Ctrl In myForm.Controls
        Select Case TypeName(Ctrl)
            Case "ComboBox"
                If Ctrl.ListIndex  -1 Then
                    myCnt = myCnt + 1
                Else
                    CheckStr = CheckStr & Ctrl.Name & vbCrLf
                End If
            Case "Frame"
                If CheckFrame(Ctrl) Then
                    myCnt = myCnt + 1
                Else
                    CheckStr = CheckStr & Ctrl.Name & vbCrLf
                End If
            Case "ListBox"
                If Ctrl.ListIndex  -1 Then
                    myCnt = myCnt + 1
                Else
                    CheckStr = CheckStr & Ctrl.Name & vbCrLf
                End If
            Case "TextBox"
                If Ctrl.Text  "" Then
                    myCnt = myCnt + 1
                Else
                    CheckStr = CheckStr & Ctrl.Name & vbCrLf
                End If
            Case Else
                CheckCnt = CheckCnt - 1
        End Select
        CheckCnt = CheckCnt + 1
    Next Ctrl
    If CheckCnt = myCnt Then
        CheckControls = True
    Else
        CheckControls = CheckStr
    End If
End Function

Function CheckFrame(myFrame As MSForms.Frame) As Boolean
    Dim FrmCnt  As Long
    Dim ChkCnt  As Long
    Dim OptCnt  As Long
    Dim tmpCtrl As Control
    CheckFrame = False
    FrmCnt = 0
    ChkCnt = 0
    OptCnt = 0
    For Each tmpCtrl In myFrame.Controls
        Select Case TypeName(tmpCtrl)
            Case "CheckBox"
                If tmpCtrl.Value Then
                    ChkCnt = ChkCnt + 1
                End If
            Case "OptionButton"
                If tmpCtrl.Value Then
                    OptCnt = OptCnt + 1
                End If
        End Select
    Next tmpCtrl
    FrmCnt = FrmCnt + 1
    If FrmCnt = OptCnt Or FrmCnt 

コマンドボタンに関数を呼び出すコードを記述する

 フォーム上のコマンドボタンには下記のコードを記述します.If ... Then 節には入力値の検証に合格した際の動作を記述します.

Option Explicit

Private Sub CommandButton1_Click()
    If TypeName(CheckControls(Me)) = "Boolean" Then
        
    Else
        MsgBox Prompt:=CheckControls(Me) & "上記項目が未入力です", Title:="未入力エラー"
        Exit Sub
    End If
End Sub

チェックボックスは NULL を取りうる

 さて,実はチェックボックスには面白い性質があります.オプションボタンでは TRUE と FALSE の 2 値しか取りませんが,チェックボックスの場合は更に NULL を加えた 3 値の真理値を取ることができます.しかしデータベース設計者にとって NULL は極めて扱いの難しい真理値であり,クエリが予想外の結果を返すことがあるためなるべく NULL を許容すべきではありません.3 値論理は関係モデルにとって急所なのです.TripleState プロパティで 3 値論理を認めるか否か変更できます.既定値は FALSE となっています.一方でオプションボタンにはそのようなプロパティは存在しません.

 上記の例文ではフレーム内のチェックボックスやリストボックスの選択肢から最低でも 1 つ選択されている,という前提でチェックをかけています.では,フレーム内ではなくフォーム上にチェックボックスが存在する場合はどうでしょうか.この場合,チェックボックスの値にかかわらず検証はパスします.ですが TRUE か FALSE かを必ず選択させるために 3 値論理を導入するのは行き過ぎかと思います.

3 値論理と選択肢の設定

 さらにチェックボックス,リストボックスいずれにも言えることですが,複数選択を許可するということは,どの選択肢も選択しないことをも許容することを意味します.つまり関係モデル上 1:n のリレーションのうち n = 0 も成り立つということです.とは言え,選択肢を注意深く設定することである程度は回避可能です.例えば年齢を 10 歳区分で区切る場合に両端の年代をどのように扱うかや,年収を 100 万円単位で区切る場合に最小群と最大群をどう設定するかなどです.数値で扱えない選択項目の場合,「その他」をどこまで許容するか,慎重に設計しなければなりません.一旦「その他」に放り込まれたデータを後から切り分けて取り出すことは不可能です.必要な項目を網羅した上でこれ以上はどう考えても不要である場合にのみ「その他」とする,つまり漏れがないように選択肢を設定すべきです.

参照:
インターフェースとしてのEXCEL VBAによるユーザーフォーム
Three-valued logic (Wikipedia)

Pocket

投稿者: admin

趣味:写真撮影とデータベース. カメラ:TOYO FIELD, Hasselblad 500C/M, Leica M6. SQL Server 2008 R2, MySQL, Microsoft Access.

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です