VBAの落とし穴回避!IsNumericで金額欄を厳格にチェックする方法
VBAでユーザーフォームを作成し、金額入力欄を設けたものの、「ユーザーが数字以外を入力してしまい、計算処理がおかしくなる!」「思わぬ形式の数字がすり抜けてしまう…」といった経験はありませんか?
特に、入力チェックによく使われるIsNumeric関数は非常に便利ですが、金額入力のバリデーションにおいては、その「寛容さ」が大きな落とし穴となることがあります。
この記事では、IsNumericの落とし穴を解説し、金額欄を厳格にチェックするための実用的なVBAコードをご紹介します。
コピペで動く!金額欄の厳格な入力チェックコード
まずは、ユーザーフォームの金額入力欄(例: TextBox1)の値をチェックする、コピペで使える実務的なVBAコードです。
「登録」ボタン(例: CommandButton1)のクリックイベントに記述することを想定しています。
このコードでは、カンマ区切り(例: "1,000")を許容しつつ、指数表記や記号などの不正な入力を厳しく排除します。
Private Sub CommandButton1_Click()
Dim inputValue As String
inputValue = Me.TextBox1.Value
If IsStrictlyNumericForCurrency(inputValue) Then
MsgBox "金額は正しく入力されています: " & inputValue, vbInformation
' ここに金額を使った計算処理などを記述
' 例: Dim amount As Double
' amount = CDbl(Replace(inputValue, ",", ""))
' MsgBox "計算用数値: " & amount
Else
MsgBox "金額の入力が不正です。数字、カンマ、ピリオドのみを使用し、正の値を入力してください。(例: 1,234.50)", vbCritical
Me.TextBox1.SetFocus ' 不正入力の場合、TextBoxにフォーカスを戻す
End If
End Sub
' 金額欄用の厳格な数値チェック関数
' IsNumericの落とし穴を回避し、金額として妥当な形式かを判断します。
Function IsStrictlyNumericForCurrency(ByVal inputValue As String) As Boolean
IsStrictlyNumericForCurrency = False ' 初期値は不正とする
' 1. 空文字は不正とする (必要に応じてTrueに変更)
If Len(inputValue) = 0 Then Exit Function
' 2. IsNumericによる大まかな数値チェック (これが落とし穴の原因になることも)
If Not IsNumeric(inputValue) Then Exit Function
' 3. 指数表記 (例: "1E3") を排除
' IsNumeric("1E3") は True になりますが、金額としては通常不適切です。
If InStr(1, UCase(inputValue), "E") > 0 Then Exit Function
' 4. 数字、カンマ、ピリオド以外の文字を排除
' IsNumeric("$1,000") や IsNumeric(" 100 ") もTrueになるため、より厳格にチェックします。
Dim i As Long
Dim char As String
For i = 1 To Len(inputValue)
char = Mid(inputValue, i, 1)
' ASCIIコードで数字、カンマ、ピリオドのみを許可
If Not ((char >= "0" And char <= "9") Or char = "," Or char = ".") Then
Exit Function
End If
Next i
' 5. カンマを除去した文字列で再度IsNumericチェック
' "1,,000" のような不正なカンマの使用や、"1.2.3" のような不正なピリオドの使用 (既にIsNumericが弾くが念のため) を排除
Dim cleanedValue As String
cleanedValue = Replace(inputValue, ",", "") ' カンマを除去
If Not IsNumeric(cleanedValue) Then
Exit Function
End If
' 6. 数値変換を試みて、エラーが発生しないか最終確認
' これにより、VBが実際に数値として扱える形式か保証します。
On Error Resume Next
Dim currencyValue As Double
currencyValue = CDbl(cleanedValue) ' CDblで変換を試みる
If Err.Number <> 0 Then
On Error GoTo 0 ' エラーハンドラをリセット
Exit Function
End If
On Error GoTo 0 ' エラーハンドラをリセット
' 7. 金額として負の数を許容しない場合
If currencyValue < 0 Then Exit Function
IsStrictlyNumericForCurrency = True ' 全てのチェックを通過したらTrue
End Function
IsNumericの「緩さ」と金額欄チェックの落とし穴
VBAのIsNumeric関数は、指定された値が数値として認識できるかどうかを判断するのに非常に便利な関数です。
しかし、その「数値として認識できる」の定義が、私たちが金額欄に求める厳格なチェックとは異なる場合があります。
落とし穴1: カンマ付きの数字
IsNumeric("1,000") の結果は何だと思いますか?
多くの場合、Trueが返されます。IsNumericはカンマ区切りの数字を「数値」と判断するのです。
これは金額入力においては望ましい挙動に見えますが、例えば「1,,000」のような不正なカンマの並びも、IsNumeric単体では「数値」と誤認してしまう可能性があり、後続の計算でエラーを招く原因となりえます。
落とし穴2: 指数表記
IsNumeric("1E3") の結果はどうでしょうか?
これもまたTrueを返します。「1E3」は10の3乗、つまり1000を意味する指数表記の数値です。
しかし、金額入力欄に「1E3」と入力されることを想定しているケースはほとんどないでしょう。このような入力がすり抜けると、ユーザー体験の低下や、意図しない値がデータベースに格納される原因となります。
その他の落とし穴
さらに、IsNumericは以下のような文字列もTrueと判断することがあります。
- 通貨記号付きの数字 (例:
"$100") - 前後の空白を含む数字 (例:
" 100 ")
これらの文字列は、VBAの内部で数値に変換できるためTrueとなりますが、金額欄としては不適切な入力です。
⚠️ 警告! IsNumericの過信は危険
金額欄のように厳密な数値チェックが求められる場面では、IsNumeric単体での判定は避けるべきです。
上記のコードのように、複数の条件を組み合わせて、より厳格なバリデーションを行うことを強く推奨します。
ご紹介したIsStrictlyNumericForCurrency関数は、これらのIsNumericの「緩さ」を補うために、以下の追加チェックを行っています。
- 指数表記の排除: 「E」や「e」が含まれていないかをチェックします。
- 不正な文字の排除: 数字、カンマ、ピリオド以外の文字が含まれていないかを厳しくチェックします。これにより、通貨記号や空白などを排除できます。
- カンマ除去後の再チェック: カンマを除去した文字列が再度
IsNumericで妥当かをチェックすることで、「1,,000」のような不正なカンマ区切りを捕捉します。 - 数値変換による最終確認:
CDbl関数で実際に数値に変換できるかエラーハンドリングを行いながら確認することで、VBAが数値として処理できることを保証します。 - 負の数の排除: 金額は通常、正の値であるため、負の数が入力された場合にエラーとします。
まとめ
VBAのIsNumeric関数は便利ですが、金額入力欄のような厳格なバリデーションが求められる場面では、その「緩さ」が予期せぬエラーの原因となりえます。
今回ご紹介したIsStrictlyNumericForCurrency関数を使用することで、カンマ区切り("1,000")を許容しつつ、指数表記("1E3")や記号、不要な空白といったIsNumericが拾ってしまう落とし穴を効果的に回避できます。
ぜひこのコードをあなたのVBAフォーム開発に活用し、堅牢なアプリケーションを構築してください。