3日がかりのその仕事、3分で終わらせる方法教えます!
パソコンスキルの心技体

1900年3月より前での、VBAの日付型変数の値とエクセルに出力される日付との違いとその原因について

2014年10月14日
  • このエントリーをはてなブックマークに追加
  • follow us in feedly

達人養成塾 小川です。

とある受講生からこんな質問がありました。

セルへの出力の場合、違った結果が表示されるのですね。
1900/1/1より前の日付だからでしょうか?…
http://www.exvba.com/comment_detail.php?comment_id=2704

何かというと。
たとえば、以下のコードを実行すると、セルA1には、「1900年1月0日 0:00」を意味する値が入る。

Dim d As Date
Range(“A1”).Value = d

ところが、以下のマクロを実行すれば分かるとおり、Visual Basic Editor上で比較すると、 初期値のままの日付型変数の値は、 1899年12月30日 0:00 と同値となっている。

    Dim d As Date
    If d = #1899/12/30# Then '[1]
        Debug.Print "一致"
    Else
        Debug.Print "不一致"
    End If

    'ただし、[1]の行の#シャープ#でくくられた部分は、
    '編集を終えた瞬間、以下のように置き換わってしまう。
    '#12:00:00 AM#

そこで、この点について整理して書いてみた。

ポイントは、以下。
○エクセルのうるう年の処理が間違っている(「1900年2月29日」という、ありえない日付がエクセルには存在する)
○そのため、1900年3月1日より後と1900年2月28日より前とでは、VBの中で日付型変数が持っている日付の値とそれを出力したときのエクセルでの日付が異なることがある。その逆もまた同様。

この件を明らかにするため、以下のマクロを書きました。

ただし、.text はセルに表示されている文字列をそのまま取得し、
.value はセルに入っている値を取得するという違いに留意しましょう。

Sub hoge1()
    Columns("B:C").ColumnWidth = 14
    Columns("B:C").NumberFormatLocal = "yyyy/m/d h:mm;@"

    Dim d As Date
    Dim c As Long
    
    If d = #12:00:00 AM# Then
        Debug.Print "一致"
    Else
        Debug.Print "不一致"
    End If
    For c = 1 To 3
        Range("A" & c).Value = c - 1
        Range("B" & c).Formula = "=A" & c
        With Range("C" & c)
            .Value = DateAdd("d", c - 1, d)
            Debug.Print c & "行目"
            Debug.Print vbTab & "excel value: " & .Offset(, -1).Value
            Debug.Print vbTab & "excel text : " & .Offset(, -1).Text
            Debug.Print vbTab & "dateadd    : " & DateAdd("d", c - 1, d)
            Debug.Print vbTab & "vba .value : " & .Value
            Debug.Print vbTab & "vba .text  : " & .Text
            Debug.Print vbNewLine
        End With
    Next
    For c = 60 To 62
        Range("A" & c).Value = c - 1
        Range("B" & c).Formula = "=A" & c
        With Range("C" & c)
            .Value = DateAdd("d", c - 1, d)
            Debug.Print c & "行目"
            Debug.Print vbTab & "excel value: " & .Offset(, -1).Value
            Debug.Print vbTab & "excel text : " & .Offset(, -1).Text
            Debug.Print vbTab & "dateadd    : " & DateAdd("d", c - 1, d)
            Debug.Print vbTab & "vba .value : " & .Value
            Debug.Print vbTab & "vba .text  : " & .Text
            Debug.Print vbNewLine
        End With
    Next
End Sub

このマクロの実行結果は、以下の通りです。

X202_000056

○出力結果

1行目
    excel value: 0:00:00
    excel text : 1900/1/0 0:00
    dateadd    : 0:00:00
    vba .value : 0:00:00
    vba .text  : 1900/1/0 0:00


2行目
    excel value: 1899/12/31
    excel text : 1900/1/1 0:00
    dateadd    : 1899/12/31
    vba .value : 1899/12/31
    vba .text  : 1900/1/1 0:00


3行目
    excel value: 1900/01/01
    excel text : 1900/1/2 0:00
    dateadd    : 1900/01/01
    vba .value : 1900/01/01
    vba .text  : 1900/1/2 0:00


60行目
    excel value: 1900/02/27
    excel text : 1900/2/28 0:00
    dateadd    : 1900/02/27
    vba .value : 1900/02/27
    vba .text  : 1900/2/28 0:00


61行目
    excel value: 1900/02/28
    excel text : 1900/2/29 0:00
    dateadd    : 1900/02/28
    vba .value : 1900/02/28
    vba .text  : 1900/2/29 0:00


62行目
    excel value: 1900/03/01
    excel text : 1900/3/1 0:00
    dateadd    : 1900/03/01
    vba .value : 1900/03/01
    vba .text  : 1900/3/1 0:00

キーワード

コメント

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

最新の記事

人気記事

最新記事

カテゴリ

最新コメント

タグクラウド