VB.NETのIsNumericは全角でもTrueを返す

データを入力してSQLサーバーに記録するソフトをVB.NETで作成していますが、エラーが出て登録できないと言われました。
数値を登録する部分でエラーが出ていて、入力時にIsNumericを使って入力文字が数値かどうかを判断していたのですが、この方法では不足していたようです。
表題に書いた通り、IsNumericは全角の数字でもTrueを返します。そのままSQL文を作って発行すると当然エラーになります。
日ごろから表計算ソフトを使ったりプログラムを書いたりしていると、数値は半角で入力するものとの思い込みがあったので、考えが及ばなかったのですが、 コンピュータに不慣れな人ならIMEがONの状態では全角で入力してしまうこともあるのかと思いました。

IsNumericは他にも「,」(コンマ)が入っていても無視してTrueを返します。
数値を正しく入力しているか判断するため、いくつか方法を試してみました。

IsNumeric

IsNumeric(TextBox1.Text)でTextBox1内の文字列が数値かどうかを判断できます。
全角でもTrueを返します。「,」(コンマ)が入っていてもTrueを返します。「1E2」もTrueを返します。
更に、「\100」「&hA0」もTrueを返します。

Double.Parse

Double.Parse(TextBox1.Text)でTextBox1内の文字列をDoubleに変換できます。失敗すればエラーになるのでTryで囲んでエラーが出るかどうかで判断できます。
全角だとエラーになります。

正規表現

If System.Text.RegularExpressions.Regex.IsMatch(TextBox1.Text, "^[.0-9]+$") Then
のような感じで判定します。この条件だと半角0から9と「.」以外の文字があるとFalseを返します。
「.」が複数あったり、「.」のみの場合にもTrueになります。
もっと良い書き方があるのかも知れませんが、正規表現はよく解りません。

色々な値を入れて試してみました

IsNumericDouble.Parse^[.0-9]+$
空白FalseErrorFalse
123True123True
123TrueErrorFalse
1.23True1.23True
1..23FalseErrorTrue
1.23TrueErrorFalse
1.2.3FalseErrorTrue
.23True0.23True
1,23True123False
1,,,,23True123False
+123True123False
+123TrueErrorFalse
++123FalseErrorFalse
-123True-123False
1+23FalseErrorFalse
1e2True100False
1E2True100False
1E2TrueErrorFalse
¥123TrueErrorFalse
¥123TrueErrorFalse
&hA0TrueErrorFalse
&HA0FalseErrorFalse

作成

VB2010を使用しました。
まず「,」は使わないことにします。いちいち3桁ごとに区切って入力する人はいなそうだし、そんなことをする人ならエラーを出せば「,」が要らないことは分かると思うからです。
むしろ小数点を打とうとして間違って「,」を入れてしまう可能性が考えられます。
次にIsNumericでチェックした後、全角を半角に変換して、Double.Parseで再チェックの方針にしました。

サンプルコードです。
空白の場合はエラーは出しません。何か文字を書いた場合、数値として認識できなければフォーカス移動ができなくなるという迷惑なコードです。

    Private Sub TextBox1_Validating(sender As Object, e As System.ComponentModel.CancelEventArgs) Handles TextBox1.Validating
        Dim err As Boolean = False
        If TextBox1.Text = "" Then
        ElseIf TextBox1.Text.IndexOf(",") >= 0 Then
            err = True
        Else
            If IsNumeric(TextBox1.Text) Then
                TextBox1.Text = StrConv(TextBox1.Text, Microsoft.VisualBasic.VbStrConv.Narrow, &H411)
                Try
                    TextBox1.Text = Double.Parse(TextBox1.Text).ToString
                Catch ex As Exception
                    err = True
                End Try
            Else
                err = True
            End If
        End If
        If err Then
            MsgBox("入力値が数値ではありません")
            e.Cancel = True
        End If
    End Sub


おまけ

今回のことで、他のコードの数値入力部分のチェックも書き直しが必要になりました。
まさか数値を全角で打ち込む人がいるとは...と言ってはいけないのでしょう。
反省の意味も込めて記事にしてみました。
あと、VB NETのTextBoxにはIMEコントロール機能もあるので、数値入力の時はIMEをOFFにするよう心がけた方がよさそうです。

TOPに戻る
2016/9/17