配列に日付を格納して、オーバーフローしたお話(失敗談)

先日、このような表を受け取った。
f:id:Infoment:20190629150345p:plain

A列には、何が入っているのだろう?一つ選択してみると、8桁の数字が入ってい
た。セルの幅が狭すぎて、このような表示になったようだ。
※書類のレイアウト上、この列のために広い幅を確保できないとのこと。
f:id:Infoment:20190629151449p:plain

システムから出力された値を、Excelで開いたものらしい。「出荷」は出荷日とのことで、8桁の数字で表されている。これを「m/d」の形式で表示したい。
そこで、8桁の数字を日付データに変換することにした。

Function ToDate(val As String) As Date
    If Len(val) = 8 Then
        ToDate = DateSerial(Left(val, 4), _
                            Mid(val, 5, 2), _
                            Right(val, 2))
    End If
End Function

単体でテストしたところ、意図したとおり、8桁の数字が日付に変換された。
よしよし。
f:id:Infoment:20190629151737p:plain

それでは、これらの日付をまとめて変換してみる。

Sub test()
    Dim TargetRange As Range
    Set TargetRange = Range("A2:A5")
    Dim arr As Variant
        arr = TargetRange

    Dim i As Long
        For i = 1 To UBound(arr)
            arr(i, 1) = ToDate(CStr(arr(i, 1)))
        Next
        TargetRange = arr
        TargetRange.NumberFormatLocal = "m/d"
End Sub

何の問題もない、はずだった。しかし、ここでエラーが発生した。
f:id:Infoment:20190629152106p:plain

オーバーフロー?たったこれだけのデータで??
確認すると、配列に値を格納する段階で、既にエラーが発生していた。
f:id:Infoment:20190629152206p:plain

従って、今回作成したToDate関数は悪くない。

色々と調べてみたが、理由が分かったのは偶然だった。セルの幅を広げても、表示が「###」のままだったのだ。
f:id:Infoment:20190629152415p:plain

書式を調べてみて、理由が判明した。セルが既に、日付として書式設定されていたためだった。
例えばセルに10000と入力して、書式を日付にすると、1927年5月18日になる。10000日を365日で割ると、27.3973年と算出できることから見れば、多分そういうことなのだろうと推測できる(1は、1900年1月1日となる)。
f:id:Infoment:20190629152901p:plain

20190610は西暦57216年となるため、配列に入るとか入らない以前に、日付として扱えないのだろう。確認してみると、9999年12月31日が限界のようだ。
f:id:Infoment:20190629154041p:plain

ということで、原因が分かったので対策してみた。といっても、配列に格納する前に、書式を標準に戻すという単純な対策だ。

Sub test()
    Dim TargetRange As Range
    Set TargetRange = Range("A2:A5")
    
        ' エラー回避のため、一旦標準書式とする。
        TargetRange.NumberFormat = "G/標準"
    
    Dim arr As Variant
        arr = TargetRange

    Dim i As Long
        For i = 1 To UBound(arr)
            arr(i, 1) = ToDate(CStr(arr(i, 1)))
        Next
        TargetRange = arr
        TargetRange.NumberFormatLocal = "m/d"
End Sub

結果、無事に求める結果を得ることが出来た。
f:id:Infoment:20190629154632p:plain

参考まで。