1桁月日の変換
VBAで日付を扱う際に、月や日が1桁になることがあります。2020/1/8 とかですね。
これを0埋めして 2020/01/08 としたいことがあります。
対応方法にはFormat関数を利用する方法とRight関数を利用する方法の2通りがあります。
Format関数での対応方法
Format関数で年月日の書式を固定長にすると0埋めした状態の日付が取得できます。
変換前の引数の日付文字列が日付として正しいのかチェックした上でFormat関数で書式を揃えます。
1 2 3 4 5 6 7 8 9 10 11 |
'// (IN) sDate 日付文字列 yyyy/m/d 形式 '// (OUT) sEdit 編集後日付文字列 yyyy/mm/dd 形式 Sub DateZeroPadding(sDate As String, sEdit As String) '// 日付文字列として不正の場合は処理しない If (IsDate(sDate) = False) Then sEdit = "" Exit Sub End If sEdit = Format(sDate, "yyyy/mm/dd") End Sub |
Format関数対応の使用例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
Sub DateZeroPaddingTest() Dim sEdit As String Call DateZeroPadding("2017/11", sEdit) Debug.Print sEdit Call DateZeroPadding("2017/1/1", sEdit) Debug.Print sEdit Call DateZeroPadding("17/11/2", sEdit) Debug.Print sEdit Call DateZeroPadding("17/1", sEdit) Debug.Print sEdit Call DateZeroPadding("2017/12/11", sEdit) Debug.Print sEdit Call DateZeroPadding("20117/12/11", sEdit) Debug.Print sEdit End Sub |
処理結果
2017/11/01
2017/01/01
2017/11/02
2017/01/17
2017/12/11
(空文字が出力)
4行目は年月のみで日がありませんが、一日とみなして処理されています。
6行目は1桁月日に対して0埋めが行われています。
8行目は年が2桁ですが正しく処理されています。
10行目は年が2桁で日がありませんが、年は正しく変換され、日は一日とみなして処理されています。
12行目は変換が不要のため元文字列のまま出力されています。
14行目は5桁の年が不正とされています。それほど頻度は無いと思いますが、5桁の年度を扱う場合は別の考慮が必要になります。
Right関数での対応方法
元の文字列に0をつけて、あとで必要な桁数だけ切り出す方法です。
Format関数での方法と比べて、いくつかの考慮が必要になります。
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 30 31 32 33 34 35 36 37 38 |
'// 引数 '// (IN) sDate 日付文字列 yyyy/m/d 形式 '// (OUT) sEdit 編集後日付文字列 yyyy/mm/dd 形式 Sub DateZeroPadding2(sDate As String, sEdit As String) '// 日付文字列として不正の場合は処理しない If (IsDate(sDate) = False) Then sEdit = "" Exit Sub End If Dim v '// 日付文字列を年、月、日に分ける v = Split(sDate, "/") Dim sYear Dim sMonth Dim sDay Dim iLen iLen = UBound(v) '// 年に20を付与して4桁切り出す sYear = Right("20" & v(0), 4) '// 月に0を付与して2桁切り出す sMonth = Right("0" & v(1), 2) '// 日を指定されている場合 If (iLen >= 2) Then '// 日に0を付与して2桁切り出す sDay = Right("0" & v(2), 2) Else '// 日が指定されなかった場合は固定で01日とする sDay = "01" End If sEdit = sYear & "/" & sMonth & "/" & sDay End Sub |
Right関数対応の使用例
テスト内容はFormat関数版と同じです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
Sub DateZeroPaddingTest2() Dim sEdit As String Call DateZeroPadding2("2017/11", sEdit) Debug.Print sEdit Call DateZeroPadding2("2017/1/1", sEdit) Debug.Print sEdit Call DateZeroPadding2("17/11/2", sEdit) Debug.Print sEdit Call DateZeroPadding2("17/1", sEdit) Debug.Print sEdit Call DateZeroPadding2("2017/12/11", sEdit) Debug.Print sEdit Call DateZeroPadding2("20117/12/11", sEdit) Debug.Print sEdit End Sub |
Format版とRight版のどちらがよいか
Format版とRight版、どちらも同じ動作をしますが、結論から言うとFormat版を利用した方がよいです。1番の理由はコードが単純なためです。
もう一つはほんの少しだけですがRight版よりも処理速度が速いためです。以下のコードで処理速度を検証したのですが、10回程度実行しましたが、平均すると若干Format版の方が速いようです。ただ、Right版が速いこともありました。
いずれにしてもどちらも高速に処理は行われているため、処理速度は気にしなくてもいいと考えます。
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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
Sub DateZeroSpeed() Dim tmStart As Double '// 計測開始時間 Dim tmEnd As Double '// 計測終了時間 Dim tmDiff As Double '// 計測経過時間 Dim i Dim s As String Debug.Print s '// Format tmStart = Timer For i = 0 To 10000 Call DateZeroPadding("2017/1/1", s) Next tmEnd = Timer tmDiff = tmEnd - tmStart Debug.Print "Format関数版で掛かる時間:" & tmDiff & "秒" '// Right tmStart = Timer For i = 0 To 10000 Call DateZeroPadding2("2017/1/1", s) Next tmEnd = Timer tmDiff = tmEnd - tmStart Debug.Print "Right関数版で掛かる時間:" & tmDiff & "秒" '// Format tmStart = Timer For i = 0 To 10000 Call DateZeroPadding("2017/1/1", s) Next tmEnd = Timer tmDiff = tmEnd - tmStart Debug.Print "Format関数版で掛かる時間:" & tmDiff & "秒" '// Right tmStart = Timer For i = 0 To 10000 Call DateZeroPadding2("2017/1/1", s) Next tmEnd = Timer tmDiff = tmEnd - tmStart Debug.Print "Right関数版で掛かる時間:" & tmDiff & "秒" End Sub |
計測結果
Format関数版で掛かる時間:0.203125秒
Right関数版で掛かる時間:0.20166015625秒
Format関数版で掛かる時間:0.18896484375秒
Right関数版で掛かる時間:0.189453125秒