お絵かきロジックアナライザ開発記   その3

続いて入力値に対するエラーチェックを行い、使い勝手を向上させていきます。入力エラーについては「入力値が数値ではない」「数値が整数でない」「上限値である150を越えている」などが考えられますが、これらのチェックをパスし数値データとして問題がなければシート作成に移ることになります。

入力値のエラーチェック

取りあえずシートを作ることのみについてのコーディングに留まっているので、ここからは設定値にエラーがないかどうかのチェック機能について考えます。入力値は正の整数でなければならず、小数や負数、数値以外が入力された場合には処理を進めないようにしなければなりません。また150マスまでと決めた上限を越えた場合も、エラー扱いにする必要があります。

OKがクリックされたときにエラーチェックするのは当然ですが、それ以外に入力欄の内容が確定した段階でもチェックを行うようにすると一段とユーザビリティが向上します。サイズ入力欄に数値を入力しEnterキーを押す(またはマウスクリックでフォーカスが他に移る)と、各コントロールにおけるExitイベントが発生しますので、これを利用してみます。

フォーカスが移ったときのチェック

Exitイベントはコントロールがフォーカスロストする直前に発生します。具体的にはFieldWidthオブジェクトのExitイベントプロシージャはFieldWidthがフォーカスを失うときに実行されます。ここで入力値にエラーがなければそのまま何もしないのですが、もしエラーを見付けたらフォーカスの移動が無効になるようにしてみましょう。


Private Sub FieldWidth_Exit(ByVal Cancel As MSForms.ReturnBoolean)
' フィールド横サイズチェック
  Dim ErrorNumber As Long                         'エラー番号保存
  Dim FieldWidthInput As Single                   '入力値保存
  On Error Resume Next
  FieldWidthInput = Me.FieldWidth.Text            '入力値取得
  ErrorNumber = Err.Number                        'エラー番号取得
  On Error GoTo 0
  If ErrorNumber <> 0 Or FieldWidthInput <> Int(FieldWidthInput) _
    Or FieldWidthInput < 5 Or FieldWidthInput > 150 Then
    Me.FieldWidth.Text = vbNullString             '5〜150の整数以外は無効
    Cancel = True
  End If
End Sub

Private Sub FieldHeight_Exit(ByVal Cancel As MSForms.ReturnBoolean)
' フィールド縦サイズチェック
  Dim ErrorNumber As Long                         'エラー番号保存
  Dim FieldHeightInput As Single                  '入力値保存
  On Error Resume Next
  FieldHeightInput = Me.FieldHeight.Text          '入力値取得
  ErrorNumber = Err.Number                        'エラー番号取得
  On Error GoTo 0
  If ErrorNumber <> 0 Or FieldHeightInput <> Int(FieldHeightInput) _
    Or FieldHeightInput < 5 Or FieldHeightInput > 150 Then
    Me.FieldHeight.Text = vbNullString            '5〜150の整数以外は無効
    Cancel = True
  End If
End Sub

横と縦の入力値チェックをまとめて掲載していますが、オブジェクト名や変数名が違うだけで、プログラムの構造は全く同一です。

このプロシージャでミソになるのは数値型の変数に、入力欄であるテキストボックスのTextプロパティを直接代入しているところです。VBAでは両辺の変数型が異なる代入式の場合、代入先の変数型(この場合Single型)に自動で変換してくれる機能があります。つまりMe.FieldWidth.TextプロパティをSingle型に変換してFieldWidthInputに代入しようとします。ここで文字列なんかが入力されていると、型変換に失敗してエラーが発生するので、代入式実行の時だけOn Error Resume Nextステートメントでエラー処理(VBAのエラー表示)をさせないようにしています。代入の結果がエラーだった場合Err.Numberプロパティにエラーコードがセットされるので、ゼロチェックをすることで文字列入力などについてはトラップできます。ただしErr.NumberプロパティはOn Error Goto 0ステートメントで初期化されてしまうので、エラーを有効にする前に予めErrorNumberに保存しておきます。

Cansel引数をFalseにしているのは、Exitイベントプロシージャ後に次のタブオーダーへフォーカス移動するのをキャンセルするためです。フォーカスの強制的な制御で思い付くのが先述のSetFocusメソッドですが、Exitイベントがフォーカスロスト直前に発生することを思い出して下さい。つまりここでSetFocusを実行しても、放っておけばプロシージャ終了時のVBAによる「次のタブオーダーへのフォーカス移動」は結局処理されてしまい、思ったような結果を得られません。VBAがフォーカスを移動させるのを抑制するという解決法が適正です。

数値以外についてのチェックが終了したら、整数チェックと数値範囲チェックを行っています。整数チェックは元の数値とInt関数で整数化した数値が等しいかどうかで行います。ここで整数チェックさせるなら、FieldWidthInputFieldHeightInputを始めからIntegerなどの整数型で宣言して、文字列チェックと同時に小数点のある数値を排除できないのかという疑問が浮かびますが、実際にInteger型で変数宣言すると、代入式の部分で小数が四捨五入によって整数化されてしまいます。当然エラーにならないのでこの方法では小数をエラー扱いにできません。

上限値を150にしているのは前述の理由によりますが、下限を5にしたのは、5×5未満のサイズでできたお絵かきロジックが現実的ではないためです。お絵かきロジックは5マスごとに太線で区切られ、基本的に5の倍数マスで作られます。一番小さな5の倍数を下限値にしているワケです。当然ながら0や負数が入力された場合も、この下限値チェックではねられます。

サイズチェックの動作確認

マクロが完成したらFieldSizeDialogを実行してみてエラーチェックの動作確認をしてみましょう。文字列や小数を含む数値、5〜150以外の数値を入力してEnterを押しても、入力欄がクリアされてフォーカスがロックされるのが解ります。しかしここで問題が発生しました。サイズ入力欄に何も入力せずキャンセルボタンをクリックしても、正しい数値が入力されていないと判定され先に進まなくなってしまっています(×クリックだけは有効です)。ロジックシート作成自体を取り止める際にはサイズが空欄でキャンセルボタンをクリックすることが予想されるのでこれは問題です。各Exitイベントプロシージャの先頭で、TextプロパティがNullならチェックそのものを行わないようにする必要があります。空欄のままのタブ移動なども容認される形になります。


Private Sub FieldWidth_Exit(ByVal Cancel As MSForms.ReturnBoolean)
' フィールド横サイズチェック
  If Me.FieldWidth.Text = vbNullString Then Exit Sub
  Dim ErrorNumber As Long                         'エラー番号保存
  Dim FieldWidthInput As Single                   '入力値保存
    ....

Private Sub FieldHeight_Exit(ByVal Cancel As MSForms.ReturnBoolean)
' フィールド縦サイズチェック
  If Me.FieldHeight.Text = vbNullString Then Exit Sub
  Dim ErrorNumber As Long                         'エラー番号保存
  Dim FieldHeightInput As Single                  '入力値保存
    ....

ただしこの場合、空欄のままでのOKボタンクリックも許可されてしまうので、OKクリック時にも入力値のチェックが必要になります。フォームでの入力動作としてはひとまずこれで問題ないでしょう。


Private Sub OkClick_Click()
' OKクリックイベント
  With Me
    If FieldWidth.Text = vbNullString Then        '横サイズ欄チェック
      .FieldWidth.SetFocus
      Exit Sub
    End If
    If FieldWidth.Text = vbNullString Then        '縦サイズ欄チェック
      .FieldHeight.SetFocus
      Exit Sub
    End If
  End With
  Dim FieldX As Byte                              'フィールドサイズ
  Dim FieldY As Byte
    ....

エラーメッセージ表示

サイズ入力値をチェックするところまで進みましたが、「なぜエラーなのか」を表示してやることで、より使いやすくなります。エラーメッセージを表示させる最も手軽な方法として思い付くのはMsgBox関数です。試しに横サイズ入力値チェックでMsgBoxを追加し、動作を確認してみましょう。


Private Sub FieldWidth_Exit(ByVal Cancel As MSForms.ReturnBoolean)
' フィールド横サイズチェック
  If Me.FieldHeight.Text = vbNullString Then Exit Sub
  Dim ErrorNumber As Long                         'エラー番号保存
  Dim FieldWidthInput As Single                   '入力値保存
  On Error Resume Next
  FieldWidthInput = Me.FieldWidth.Text            '入力値取得
  ErrorNumber = Err.Number                        'エラー番号取得
  On Error GoTo 0
  If ErrorNumber <> 0 Or FieldWidthInput <> Int(FieldWidthInput) _
    Or FieldWidthInput < 5 Or FieldWidthInput > 150 Then
    MsgBox "5〜150の整数を入力して下さい" _
      , vbOKOnly + vbExclamation, "サイズ入力値エラー"
    Me.FieldWidth.Text = vbNullString             '5〜150の整数以外は無効
    Cancel = True
    ....

横サイズ入力値欄で文字列や小数、5〜150の範囲を超える数値を入力しEnterを押すとエラーメッセージが表示されます。縦サイズチェックも同様にMsgBox関数を追加しておきましょう。

ESCキーでキャンセル

Windowsを操作していると、ESCキーでダイアログを閉じる場面があると思います。現状ではキャンセルボタンや×ボタンでSetFieldSizeフォームを閉じることはできますが、キーボード操作でフォームを閉じることはできません。イベントプロシージャでキーボードをトラップしてみましょう。キー操作をフックするにはKeyPressイベントを利用します。KeyPressイベントはフォーカスのあるオブジェクトに対して発生するので、SetFieldSizeフォームでは入力用テキストボックスのFieldWidthオブジェクトとFieldHeightオブジェクト、ボタンであるOkClickオブジェクトとCancelClickが対象となり、総てにKeyPressイベントを設定しなければなりません。SetFieldSizeのコードに次の記述を追加して下さい。


Private Sub FieldWidth_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
' 横サイズ入力欄ESCキートラップ
  If KeyAscii = &H1B Then
    Unload Me
  End If
End Sub

Private Sub FieldHeight_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger) ' 縦サイズ入力欄ESCキートラップ If KeyAscii = &H1B Then Unload Me End If End Sub
Private Sub OkClick_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger) ' OKボタンESCキートラップ If KeyAscii = &H1B Then Unload Me End If End Sub
Private Sub CancelClick_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger) ' キャンセルボタンESCキートラップ If KeyAscii = &H1B Then Unload Me End If End Sub

オブジェクト名が違うだけで内容は全く同じです。KeyAsciiパラメータが&H1B(ESCのASCIIコード)であればUnloadコマンドでフォームを閉じます。FieldSizeDialogを実行しESCキーを押してみて下さい。

← 前へ   → 次へ ▲ ページトップ