【Excelの仕様?】Excelの日付とVBAの日付の思わぬ落とし穴

Excelで入力している日付をVBAで処理したい時ってありますよね。特定の日付のデータを検索して、そのデータに対して処理をするだったり、データの日付が特定の範囲内に収まっているか調べるだったりと。

実は、Excelの日付とVBAの日付では同じ日付に見えても、異なる日付として処理されてしまう日付が存在します。このことを知らないと思わぬところで落とし穴に落ちる可能性があります。

今回はExcelの日付とVBAの日付の変な仕様について解説します。

実演

まずはじめに、ExcelのA1セルに 2000/1/1 と入力します。

続いて、VBAで日付を比較するコードを書きます。

Sub DiffDate()

    Dim a_date As Date
    
    a_date = CDate("2000/1/1") '日付文字列をDate型に変換
    
    If a_date = Range("A1").Value Then '日付文字列を変換したDateとA1セルの日付を比較
        MsgBox "同じ日です。"
    Else
        MsgBox "違う日です。"
    End If
    
End Sub

コードは、以下のような内容です。

  1. 日付の文字列をCDateでDate型に変換
  2. 変換した日付とA1セルに入力された日付を比較

上記のコードを実行してみると、

当たり前ですが同じ日と判定されます。では、次にA1セルの日付を 2000/1/1 から、 1900/1/1 に変更してみます。また、VBAのコードも 1900/1/1 に変更します。

Sub DiffDate()

    Dim a_date As Date
    
    a_date = CDate("1900/1/1") '日付文字列をDate型に変換
    
    If a_date = Range("A1").Value Then '日付文字列を変換したDateとA1セルの日付を比較
        MsgBox "同じ日です。"
    Else
        MsgBox "違う日です。"
    End If
    
End Sub

上記のコードを実行してみます。普通に考えると同じ日と判定されますが、

違う日と判定されてしまいました。

調査

どちらも 1900/1/1 のはずなのに、違う日と判定された謎を調査するためVBAの実行を途中で止めて、A1セルの値とDate型の値を確認してみます。

何故かA1セルの値が 1899/12/31 になっています。理由が全くわからなかったため、WEB検索してみると、Excelのバグ(仕様?)が原因であることがわかりました。


原因

A1セルの値が 1899/12/31とされる原因は、Excelが1900年を閏年だと誤って想定しているためとのこと。1900 年が閏年であると誤って想定Excel

詳しく説明すると、Excelの日付はシリアル値という1からの連番で日付を扱っています。そして、Excelが1900年を閏年だと誤って想定しているため以下のようになっています。

  • 1900/1/1 = 1
  • 1900/1/2 = 2
  • 1900/2/28 = 59
  • 1900/2/29 = 60
  • 1900/3/1 = 61

しかし 1900/2/29 は存在しない日付なので、VBA側で 1899/12/31 を 1 として処理することによって、以下のように調整しています。

  • 1899/12/31 = 1
  • 1900/1/1 = 2
  • 1900/1/2 = 3
  • 1900/2/28 = 60
  • 1900/3/1 = 61

そのため、A1セルの値 1900/1/1(シリアル値 1 )がVBAでは 1899/12/31 と判定されていました。 1900年を閏年だと誤って想定していることが原因のため、1900/3/1 以降の日付(最初に試した 2000/1/1 等)では正しく判定することができます。

また、この問題をMicrosoftがなぜ修正しないか上記のページに色々と書いていますが、修正すると色々な問題が発生するのに対して、修正しなかった場合は 1900/3/1 より前の日付がずれるだけで、この問題は稀だから修正しない。とのこと。


まとめ

今回は日付に関するExcelのバグ(仕様?)について、解説しました。

Microsoftが言うように 1900/3/1 よりも前の日付を扱うことはあまりないかもしれませんが、もし扱う事がある場合は、1900/1/1 ~ 1900/2/28 のシリアル値を-1する等の処理を入れないと正しく動作しないので気をつけましょう。

Excel 業務をもっとカンタンに