【実務・中級編】【ユーザー対話】MsgBoxとInputBoxの戻り値判定による安全な条件分岐設計 – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク

【ユーザー対話】MsgBoxとInputBoxの戻り値判定による安全な条件分岐設計

現場で動く業務自動化ツールを開発していると、避けて通れないのが「ユーザーとの対話」だ。
処理の実行前に確認を促す、あるいは処理に必要なパラメータを動的に入力させる。この要件を満たすために、VBScriptでは `MsgBox` と `InputBox` というプリミティブな関数が用意されている。

しかし、多くの開発現場のコードを見て、私はいつも冷や汗をかく。
`If MsgBox(…) = vbYes Then` とだけ書き、ユーザーがダイアログを閉じた挙動や、想定外の入力値をノーガードで受け入れているコードがなんと多いことか。

VBScriptは動的型付け言語であり、エラーハンドリングの仕組みが極めて脆弱だ。だからこそ、「ユーザーは何をしでかすか分からない」という前提に立ち、戻り値を完璧に制御・検証する設計が求められる。

今回は、実務の現場でバグの温床にならない、堅牢なユーザー対話フローの構築手法を伝授しよう。

1. なぜ「甘い判定」が業務を止めるのか?

初心者がやりがちな実装のアンチパターンを見てほしい。

‘ 【悪例】戻り値の全パターンを網羅していない典型例
Dim ret
ret = MsgBox(“データを削除しますか?”, vbYesNo, “確認”)
If ret = vbYes Then
‘ 削除処理
Call DeleteDatabase()
End If

このコードの何が問題か?
`vbYesNo` を指定した場合、ユーザーの選択肢は「はい(`vbYes` = 6)」と「いいえ(`vbNo` = 7)」だけだと思いがちだが、Windowsの仕様上、ダイアログ右上の「×」ボタンが押された場合も `vbNo` が返る。
さらに、もしこれが `vbAbortRetryIgnore` や `vbYesNoCancel` だった場合、キャンセル(`IDCANCEL` = 2)が押されたときの挙動が抜けていると、意図しないデフォルトルートに落ち、最悪の場合は誤ったデータ更新を引き起こす。

InputBoxにいたっては、さらに深刻だ。未入力で「OK」を押した空文字(`””`)と、「キャンセル」を押したときの長さ0の文字列の区別、さらには型不一致やメモリ溢れを誘発する巨大な文字列の入力など、ノーガードでは実用に耐えない。

プロダクション環境に耐えうるコードとは、「あり得ない入力」をすべて想定内として処理するコードである。

2. MsgBoxの戻り値を完全制御する設計パターン

まずは `MsgBox` だ。重要なのは、ボタンの組み合わせ(ボタンスタイル)に応じたすべての戻り値を網羅し、`Select Case` 構造によって明示的に分岐させることである。

以下の表は、主要なボタン定数と戻り値の対応だ:

| 定数名 | 値 | 意味 |
| :— | :— | :— |
| `vbOK` | 1 | [OK] がクリックされた |
| `vbCancel` | 2 | [キャンセル] がクリックされた |
| `vbAbort` | 3 | [中止] がクリックされた |
| `vbRetry` | 4 | [再試行] がクリックされた |
| `vbIgnore` | 5 | [無視] がクリックされた |
| `vbYes` | 6 | [はい] がクリックされた |
| `vbNo` | 7 | [いいえ] がクリックされた |

実務における「破壊的な処理(ファイル削除やDB書き込みなど)」の前に配置すべき、安全な `MsgBox` の実装パターンを見てほしい。

Option Explicit

Sub ExecuteDangerousOperation()
Dim intResult

‘ 危険な操作の前に [はい/いいえ/キャンセル] の3択を強制する
‘ vbYesNoCancel (3) + vbExclamation (48:警告アイコン) + vbDefaultButton2 (256:デフォルトを「いいえ」にする防衛策)
intResult = MsgBox(“選択されたすべてのレコードをデータベースから削除します。” & vbCrLf & _
“この操作は取り消せません。本当に実行しますか?”, _
vbYesNoCancel + vbExclamation + vbDefaultButton2, _
“【警告】データ削除の確認”)

Select Case intResult
Case vbYes
‘ 厳格な確認を経たため、処理を実行
WScript.Echo “削除処理を実行します…”
‘ Call DeleteLogic()

Case vbNo
‘ ユーザーが明確に拒否した場合
WScript.Echo “処理を中断しました(データは保護されました)。”
Exit Sub

Case vbCancel, 0
‘ キャンセル、または「×」ボタンによる強制終了
WScript.Echo “操作がキャンセルされました。”
Exit Sub

Case Else
‘ 想定外のフォールバック
WScript.Echo “予期せぬエラーが発生しました。”
WScript.Quit 1
End Select
End Sub

Call ExecuteDangerousOperation()

ここで重要なテクニックが、`vbDefaultButton2` の付与だ。デフォルトのフォーカスを「はい」ではなく「いいえ」にしておくことで、キーボードの「Enter」連打による誤爆を防ぐ。これがプロのUI/UX配慮というものだ。

3. InputBoxの型判定と空白・キャンセルバリデーション

次に `InputBox` だ。ユーザーに文字列や数値を入力させる際、最大の敵は 「未入力(空文字)」「キャンセル押下」 である。

VBScriptの `InputBox` は、ユーザーが「キャンセル」を押したときも、テキストボックスが空のまま「OK」を押したときも、どちらも長さ0の文字列 `””` を返す。そのため、純粋な値の比較だけでは、ユーザーの意図(キャンセルしたのか、単に未入力なのか)を判別できない。

ここで、さらに実務で頻出する「数値入力のバリデーション」を組み込んだ堅牢な関数設計を見てみよう。

Option Explicit

Sub Main()
Dim strInput, lngTargetID

‘ ユーザーからの入力を受け取る
strInput = InputBox(“処理対象のID(数値)を入力してください:”, “パラメータ入力”, “”)

‘ 1. 【最重要】キャンセルの検知
‘ InputBoxでキャンセルが押された、または空文字が返された場合の判定
If Not ValidateInput(strInput) Then
Exit Sub
End If

‘ 2. 型チェック(数値であるかどうかの厳密な検証)
If Not IsNumeric(strInput) Then
MsgBox “エラー: 入力された値は数値ではありません。”, vbCritical, “型不一致エラー”
Exit Sub
End If

‘ 3. 型変換とビジネスロジックへの受け渡し
lngTargetID = CLng(strInput)

MsgBox “正常にID: ” & lngTargetID & ” を受け付けました。”, vbInformation, “処理継続”
‘ Call ProcessWithID(lngTargetID)

End Sub

‘ —————————————————————–
‘ 入力値の基本バリデーション関数
‘ 戻り値: True (有効な入力), False (キャンセルまたは未入力)
‘ —————————————————————–
Function ValidateInput(ByVal inputVal)
‘ そもそも変数未定義や空文字の場合
If VarType(inputVal) = vbEmpty Then
ValidateInput = False
Exit Function
End If

‘ ユーザーがキャンセルを押した場合、InputBoxは長さ0の文字列を返す
If inputVal = “” Then
MsgBox “操作がキャンセルされたか、値が入力されませんでした。”, vbExclamation, “中断”
ValidateInput = False
Exit Function
End If

‘ 前後の空白を除去しても空っぽの場合の対策
If Trim(inputVal) = “” Then
MsgBox “空白のみの入力は受け付けられません。”, vbExclamation, “入力エラー”
ValidateInput = False
Exit Function
End If

ValidateInput = True
End Function

Call Main()

この設計の優れている点

1. 関数の分離(関心事の分離): バリデーションロジックを `ValidateInput` 関数として独立させ、メインの業務ロジックを汚さない。
2. Trimによる空白文字対策: ユーザーがスペースだけを入力して突破しようとするのを防ぐ。
3. `IsNumeric` による型担保: データベースやファイル操作に渡す直前で確実に数値型(`CLng`)へキャストすることで、SQLインジェクションや型ミスマッチエラーを未然に防ぐ。

4. プロダクションコード:安全な対話型バッチ処理の全体像

それでは、ここまで解説した知見を統合し、実務でそのままコピー&ペーストしてモジュールとして組み込める「安全なユーザー対話型ファイル処理スクリプト」の完成形を提示しよう。

‘ ==============================================================================
‘ スクリプト名: SecureDialogTemplate.vbs
‘ 概要: ユーザー対話を挟んだ安全なパラメータ入力と実行確認のテンプレート
‘ 開発者: チーフアーキテクト
‘ ==============================================================================

Option Explicit

‘ メイン処理の実行
Call MainProcess()

Sub MainProcess()
Dim strFilePath, intConfirm

‘ 1. InputBoxによるファイルパスの取得
strFilePath = InputBox(“処理対象のファイル名(またはパス)を入力してください:”, _
“ファイル処理ウィザード”, “C:\Data\target.csv”)

‘ 入力チェック&キャンセル検知
If Not IsValidStringInput(strFilePath) Then
WScript.Echo “プロセスはユーザーによって中断されました。”
Exit Sub
End If

‘ 2. MsgBoxによる最終確認(防御的UI設計)
intConfirm = MsgBox(“以下のファイルを処理します。よろしいですか?” & vbCrLf & vbCrLf & _
“パス: ” & strFilePath, _
vbYesNo + vbQuestion + vbDefaultButton2, _
“実行前最終確認”)

If intConfirm <> vbYes Then
MsgBox “処理をキャンセルしました。”, vbInformation, “終了”
Exit Sub
End If

‘ 3. 実処理の呼び出し(ここではシミュレーション)
On Error Resume Next
Call ExecuteFileProcess(strFilePath)
If Err.Number <> 0 Then
MsgBox “致命的なエラーが発生しました: ” & Err.Description, vbCritical, “実行時エラー”
Err.Clear
Else
MsgBox “すべての処理が正常に完了しました。”, vbInformation, “完了”
End If
On Error GoTo 0

End Sub

‘ —————————————————————–
‘ 文字列入力の厳格な検証関数
‘ —————————————————————–
Function IsValidStringInput(ByVal val)
‘ キャンセルまたは未入力(長さ0)の判定
If Trim(val & “”) = “” Then
IsValidStringInput = False
Exit Function
End If

‘ 必要に応じてここで危険な文字(例: パストラバーサル対策など)の検知も可能
‘ If InStr(val, “..”) > 0 Then …

IsValidStringInput = True
End Function

‘ —————————————————————–
‘ 実処理シミュレーション
‘ —————————————————————–
Sub ExecuteFileProcess(ByVal path)
‘ FileSystemObject等を用いた実処理をここに記述
‘ Dim fso: Set fso = CreateObject(“Scripting.FileSystemObject”)
‘ If Not fso.FileExists(path) Then Err.Raise 1001, , “ファイルが存在しません。”

WScript.Echo “処理中: ” & path
End Sub

5. アーキテクトからの最後のアドバイス

VBScriptは古い技術だと言われる。しかし、Windows環境下において、追加のランタイムインストールなしで瞬時に動作するWSH/VBScriptは、今なお現場の自動化において最強の武器になり得る。

だからこそ、「動けばいいや」という場当たり的なコードを書くべきではない。
今回解説したように、

  • MsgBoxの戻り値は `Select Case` で全網羅する
  • InputBoxの空文字は「キャンセル」と「未入力」の両面からガードする
  • 業務ロジックに渡す前に必ず型と空白のバリデーションを挟む

この鉄則をあなたのコードに組み込むだけで、システム障害やユーザーの誤操作によるトラブルは劇的にゼロに近づく。
プロフェッショナルとして、美しく、そして鉄壁の守りを持つコードベースを築き上げてほしい。

タイトルとURLをコピーしました