IsDate関数はあいまいな日付も正常にしてしまう
VBAの日付形式の文字列が正しい日付であるのかをチェックする関数にIsDate関数があります。
ただし、日付としてあいまいなものを正常とみなす点や時刻も正常とみなす点があるため利用する際に注意が必要です。
あいまいな点を無くしてチェックする関数については後述しています。
IsDate関数は想定外の動作の検証コード
以下のソースは複数の日付形式文字列をIsDate関数で実行した結果です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
Sub IsDateTest() Dim i Dim ar(10) ar(0) = "2017/08/31" '// 正常 ar(1) = "2017/8/31" '// 正常(月1桁) ar(2) = "17/08/31" '// 正常(西暦2桁) ar(3) = "2017/08" '// 正常(日が無い) ar(4) = "2017" '// 不正★ ar(5) = "08/31" '// 正常(年が無い) ar(6) = "8/31" '// 正常(年が無い、月1桁) ar(7) = "08" '// 不正★ ar(8) = "2017/008/31" '// 正常(月3桁) ar(9) = "2017/08/031" '// 正常(日3桁) ar(10) = "0002017/08/31" '// 正常(年7桁) For i = 0 To UBound(ar) Call IsDateResult(ar(i)) Next End Sub Sub IsDateResult(s) If IsDate(s) = True Then Debug.Print "正常 : " & s Else Debug.Print "不正★ : " & s End If End Sub |
実行結果
1 2 3 4 5 6 7 8 9 10 11 |
正常 : 2017/08/31 正常 : 2017/8/31 正常 : 17/08/31 正常 : 2017/08 不正★ : 2017 正常 : 08/31 正常 : 8/31 不正★ : 08 正常 : 2017/008/31 正常 : 2017/08/031 正常 : 0002017/08/31 |
実行結果は5~15行目の各日付の右のコメントに書いた通りですが、これが正常になるの?と思うようなものがあります。
桁不足、桁超過、日不足、年不足、などでも正常となる場合があります。
そのため、その時々における条件で日付文字列をチェックしたい場合にはIsDate関数では正しくチェックできない恐れがあります。
8桁数字やyyyy/mm/dd形式用の日付チェック関数
IsDate関数をそのまま使うと問題がある場合は、個別の条件のみ正常とするチェック処理を別途作成する必要があります。
以下のソースは8桁数字の 20170831 や、スラッシュ区切りの 2017/08/31 に対しては正常と判定する関数です。
上記の IsDateTest関数の ar(0)の”2017/08/31″ のみが正常となり、他は全て不正として判定されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
Function IsDateEx(s) Dim i Dim sDate Dim sTemp sDate = "" '// 数字のみを抽出 For i = 0 To Len(s) sTemp = Mid(s, i + 1, 1) '// 数字の場合 If IsNumeric(sTemp) = True Then sDate = sDate & sTemp End If Next '// 数字8文字でない場合は不正とみなす If Len(sDate) <> 8 Then IsDateEx = False Exit Function End If '// 日付形式に変換 sDate = Format(sDate, "####/##/##") '// 日付チェック IsDateEx = IsDate(sDate) End Function |
使い方
使い方はIsDate関数と同じです。
引数sの型を未指定にしていますが、気になる方はString型を設定してください。
上記のテストコードを実行すると、1番目のみ正常となり、2番目以降は不正と判定します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
Sub IsDateTest() Dim i Dim ar(10) ar(0) = "2017/08/31" '// 正常 ar(1) = "2017/8/31" '// 不正 ar(2) = "17/08/31" '// 不正 ar(3) = "2017/08" '// 不正 ar(4) = "2017" '// 不正 ar(5) = "08/31" '// 不正 ar(6) = "8/31" '// 不正 ar(7) = "08" '// 不正 ar(8) = "2017/008/31" '// 不正 ar(9) = "2017/08/031" '// 不正 ar(10) = "0002017/08/31" '// 不正 For i = 0 To UBound(ar) Call IsDateResult(ar(i)) Next End Sub Sub IsDateResult(s) If IsDateEx(s) = True Then Debug.Print "正常 : " & s Else Debug.Print "不正★ : " & s End If End Sub |
実行結果
1 2 3 4 5 6 7 8 9 10 11 |
正常 : 2017/08/31 不正★ : 2017/8/31 不正★ : 17/08/31 不正★ : 2017/08 不正★ : 2017 不正★ : 08/31 不正★ : 8/31 不正★ : 08 不正★ : 2017/008/31 不正★ : 2017/08/031 不正★ : 0002017/08/31 |