はじめに
ExcelVBAの日付型は、ある日時を起点にしたシリアル値であるため、常に何か値を保持しており、初期化を「0」や「無し」にする事はできません。
このため、日付型を利用する際はある値で初期化するという事は避ける必要があります。
文字列から日付型の変数に代入するような場合、CDate関数を使いますが不具合が生じないように、一旦 IsDate関数で日付に変換できるか確認してから代入するようにします。
IsDate関数で日付型への代入が可能か調べる
受け取った値が日付型に代入できるかを確かめるには、IsDate関数を使います。
IsDate関数の返り値が True であれば日付型に代入できます。
以下は、ユーザーフォームでテキストボックスに日付を入力してもらうプログラムです。

「OK」ボタンが、CommandButton1 です。
'/// このコードはUserForm1に書きます。 ///
Private Sub CommandButton1_Click()
Dim myDate As Date
If IsDate(Me.TextBox1.Text) Then
myDate = Me.TextBox1.Text
MsgBox myDate
Else
MsgBox "日付に変換できません。"
End If
End Sub
このプログラムでは、テキストボックスの内容を直接日付型に代入していますが、以下のようにCDate関数を使った方が、意図がはっきりするので、丁寧な書き方と言えるでしょう。
myDate = CDate(Me.TextBox1.Text)
バリアント変数を使う
未確定の値を一旦バリアント型の変数で受けてしまう方法もよく使われます。
日付型に変換する場合、IsDate関数で日付型への変更が可能かを調べるのは同じですが、変更できない場合でもその値を他で利用したい時などに便利です。
'/// このコードはUserForm1に書きます。 ///
Private Sub CommandButton1_Click()
Dim myDate As Date
Dim val As Variant
val = Me.TextBox1.Text
If IsDate(val) Then
myDate = CDate(val)
MsgBox myDate
Else
MsgBox val & "は日付に変換できません。"
End If
End Sub
日付型を 0 で初期化
VBAの日付型は特殊な型で、「1900年1月1日」を起点としたシリアル値(数値)で管理されています。
このため値の無い状態を表現できません。つまり初期化という概念がないのです。
日付型はシリアル値なので、 0 を代入する事ができます。
日付型 = 0 の時、「1900年1月1日」と記憶していたのですが、実際には違ったようです。
以下のようなプログラムを書いてみました。
Sub testDate()
Dim myDate As Date
myDate = 0
Debug.Print myDate '0:00:00
Debug.Print Year(myDate) '1899
Debug.Print Month(myDate) '12
Debug.Print Day(myDate) '30
myDate = 1
Debug.Print myDate '1899/12/31
Debug.Print Year(myDate) '1899
Debug.Print Month(myDate) '12
Debug.Print Day(myDate) '31
myDate = 2
Debug.Print myDate '1900/01/01
Debug.Print Year(myDate) '1900
Debug.Print Month(myDate) '1
Debug.Print Day(myDate) '1
End Sub
これは、単に Excel のバグが原因のようです。
・Excel では、1900 年が閏年であると誤って想定しています
このような事もあるので、日付型を一旦 0 で初期化しておくという事はしない方がいいでしょう。
まとめ
ExcelVBAの日付型は、ある日付(1900/01/01)を起点としたシリアル値で初期化という概念がありません。
特に繰り返し処理を行う場合などで初期化したいケースでは、注意が必要です。
(この場合は仕方ないので、その後の条件文で引っ掛からない適当な日付を使いましょう。)
また、日付らしき文字列でも日付型に変換できないケースもありますから、IsDate関数を使って調べる事が大事です。
安易に日付型に値を代入するとエラーとなりプログラムが止まってしまいます。
CDate関数を使う場合は同様です。
エラーの回避には、On Error Resume Next を使う方法もありますが、プログラムの意図をはっきりさせるためにも、日付型の調査は IsDate関数を使って調べた方が良いでしょう。