ユーザーがinputBoxで日付範囲を入力すると、結果をDictionary オブジェクトに格納して返す関数

ユーザーが 「YYYY/MM/DD～YYYY/MM/DD」 形式で日付範囲を入力すると、その開始日・終了日を分解して Dictionary オブジェクトに格納して返すプログラムを作成する。
入力がキャンセルされた場合や、無効な日付形式が入力された場合には適切なメッセージを表示し、処理を終了させる。

プログラムの完成品はこちら
```vb
' 日付をInputBoxで入力してもらい、入力データをDictionaryへ格納する関数
' プロパティ ⇒ "startYear", "startMonth", "startDay", "endYear", "endMonth", "endDay",
Function GetDateRangeDict() As Object
    Dim dic As Object
    Dim dateRange As String
    Dim todayStr As String
    Set dic = CreateObject("Scripting.Dictionary")
    
    ' 今日の日付をデフォルト値に設定
    todayStr = Format(Date, "yyyy/mm/dd") & "～" & Format(Date, "yyyy/mm/dd")
    dateRange = InputBox("日付範囲を指定してください。(YYYY/MM/DD)", "日付範囲入力", todayStr)
    
    ' キャンセル時は終了
    If dateRange = "" Then
        MsgBox "入力がキャンセルされました。", vbExclamation, "終了"
        Exit Function
    End If
    
    ' ParseDateRange の結果を受け取る
    Set dic = ParseDateRange(dateRange)
    If dic Is Nothing Then
        MsgBox "無効な日付範囲です" & vbCrLf & _
                      "YYYY/MM/DD～YYYY/MM/DD" & vbCrLf & _
                      "の形式で入力してください。", vbExclamation, "エラー"
        Exit Function
    End If
    
    Set GetDateRangeDict = dic
End Function

' dateRangeを解析（パース）して Dictionary へ変換して返す関数
Function ParseDateRange(dateRange As String) As Object
    Dim parts As Variant, startParts As Variant, endParts As Variant
    Dim dic As Object
    Set dic = CreateObject("Scripting.Dictionary")
    
    ' "～"で分割し、2つの要素があるか確認
    parts = Split(dateRange, "～")
    If UBound(parts) <> 1 Then Exit Function
    
    ' 開始日と終了日をそれぞれ"/"で分割 （例：startParts(0) ⇒ "2025"）
    startParts = Split(Trim(parts(0)), "/")
    endParts = Split(Trim(parts(1)), "/")
    
    ' 正しいフォーマットかチェック
    If UBound(startParts) <> 2 Or UBound(endParts) <> 2 Then Exit Function
    If Not (IsNumeric(startParts(0)) And IsNumeric(startParts(1)) And IsNumeric(startParts(2))) Then Exit Function
    If Not (IsNumeric(endParts(0)) And IsNumeric(endParts(1)) And IsNumeric(endParts(2))) Then Exit Function
    
    ' dic に追加
    dic.Add "startYear", CInt(startParts(0))
    dic.Add "startMonth", CInt(startParts(1))
    dic.Add "startDay", CInt(startParts(2))
    dic.Add "endYear", CInt(endParts(0))
    dic.Add "endMonth", CInt(endParts(1))
    dic.Add "endDay", CInt(endParts(2))
    
    Set ParseDateRange = dic
    
End Function

Sub test()
    Dim result As Object
    Set result = GetDateRangeDict()
    
    If result Is Nothing Then Exit Sub
    
    MsgBox "開始日: " & result("startYear") & "年" & result("startMonth") & "月" & result("startDay") & "日" & vbCrLf & _
           "終了日: " & result("endYear") & "年" & result("endMonth") & "月" & result("endDay") & "日"
End Sub

```
### 1：実際に処理するための関数を定義する
```vb
Function GetDateRangeDict() As Object
```
最終的にオブジェクトとして返したいので As Object で宣言。
日付入力用のimputBoxもこの関数内で作成するため、引数は必要ない。

#### 1-1：変数を定義する
```vb
Dim dic As Object 
Dim dateRange As String
Dim todayStr As String
Set dic = CreateObject("Scripting.Dictionary")
```
dic → 分解された日付データをDictionaryで格納するための変数
dateRange → ユーザーによって入力されたデータを格納するための変数
todayStr → 入力フォーマットのデフォルトを格納
Set で dic をインスタンス化する

#### 1-2：入力フォーマットのデフォルトを作成する
```vb
todayStr = Format(Date, "yyyy/mm/dd") & "～" & Format(Date, "yyyy/mm/dd")
```
Date を使って今日の日付を取得し、「YYYY/MM/DD～YYYY/MM/DD」 形式の文字列を作成。
Now にすると時間データも含まれるが、今回は必要としないため Date で設定している。

#### 1-3：ユーザーに日付範囲を入力させる
```vb
dateRange = InputBox("日付範囲を指定してください。(YYYY/MM/DD)", "日付範囲入力", todayStr)
```
ユーザーが InputBox で日付範囲を入力。

#### 1-4：キャンセル時の処理
```vb
If dateRange = "" Then
    MsgBox "入力がキャンセルされました。", vbExclamation, "終了"
    Exit Function
End If
```
InputBox で何も入力せずに「キャンセル」した場合は、警告メッセージを表示して終了。
※空白で OK した場合もこのプログラムに該当する。

1-5：日付範囲を解析済みのオブジェクトを変数に格納
```vb
Set dic = ParseDateRange(dateRange)
```
ParseDateRange() を使って Dictionary に変換。
（ParseDateRange()の詳細は2-1から解説）

1-6：無効な日付範囲のチェック
```vb
If dic Is Nothing Then
    MsgBox "無効な日付範囲です" & vbCrLf & _
        "YYYY/MM/DD～YYYY/MM/DD" & vbCrLf & _
        "の形式で入力してください。", vbExclamation, "エラー"
    Exit Function
End If
```
ParseDateRange()は日付に変換できた場合のみオブジェクトとして返すので、 Nothing の場合は日付範囲の指定が無効になっている。

1-7：Dictionary を返す
```vb
Set GetDateRangeDict = dic
```
解析結果を関数の戻り値として返す。

### 2：GetDateRangeDict() から渡された dateRange を解析する。
```VB
Function ParseDateRange(dateRange As String) As Object
```
GetDateRangeDict() から渡された dateRange を解析し、開始日・終了日をそれぞれ Dictionary に格納する。

#### 2-1：変数を定義
```vb
Dim parts As Variant, startParts As Variant, endParts As Variant
Dim dic As Object
Set dic = CreateObject("Scripting.Dictionary")
```
parts → 開始日と終了日を分けて格納するための変数
startParts → 開始日を年・月・日を分けて格納するための変数
endParts → 終了日を年・月・日を分けて格納するための変数
dic → 分解された日付データを格納するためのオブジェクト変数

#### 2-2：日付範囲を"～" で分割
```vb
parts = Split(dateRange, "～")
If UBound(parts) <> 1 Then Exit Function
```
Split()を使って日付範囲を"～"で分解する。
If 文で日付範囲が2つの要素に分解されているかチェックする。
分解できていない場合はこのまま ParseDateRange() から抜ける。（オブジェクトを返さない）

#### 2-3：開始日・終了日を "/" で細分化
```vb
startParts = Split(Trim(parts(0)), "/")
endParts = Split(Trim(parts(1)), "/")
```
ユーザーの入力に余分なスペースが含まれている可能性があるため、データの前後に空白があれば Trim() で削る。

#### 2-4 格納されたデータが正しいフォーマットになっているかチェック
```vb
If UBound(startParts) <> 2 Or UBound(endParts) <> 2 Then Exit Function
If Not (IsNumeric(startParts(0)) And IsNumeric(startParts(1)) And IsNumeric(startParts(2))) Then Exit Function
If Not (IsNumeric(endParts(0)) And IsNumeric(endParts(1)) And IsNumeric(endParts(2))) Then Exit Function
```
startParts と endParts の要素数が 3 でなければ終了。（オブジェクトを返さない）
各要素が数値でなければ終了。

#### 2-5：dic にデータを格納
```vb
dic.Add "startYear", CInt(startParts(0))
dic.Add "startMonth", CInt(startParts(1))
dic.Add "startDay", CInt(startParts(2))
dic.Add "endYear", CInt(endParts(0))
dic.Add "endMonth", CInt(endParts(1))
dic.Add "endDay", CInt(endParts(2))
```
CInt() を使って Integer に変換し、Dictionary に追加。

#### 2-6：Dictionary を返す
```vb
Set ParseDateRange = dic
```
作成した Dictionary を返す。

### 3：実際に使ってみる
```vb
Sub test()
```
この Sub は GetDateRangeDict() を呼び出し、結果を MsgBox で表示する。

#### 3-1：変数を定義
```vb
Dim result As Object
```
result → 返ってきた dictionary を格納するための変数

#### 3-2 関数の呼び出し
```vb
Set result = GetDateRangeDict()
If result Is Nothing Then Exit Sub
```
GetDateRangeDict で帰ってきた dictionary を result に格納。
Nothing が返ってきた場合（キャンセルまたは無効な入力）は Exit Sub で終了。

#### 3-3：結果を MsgBox で表示
```vb
MsgBox "開始日: " & result("startYear") & "年" & result("startMonth") & "月" & result("startDay") & "日" & vbCrLf & _
        "終了日: " & result("endYear") & "年" & result("endMonth") & "月" & result("endDay") & "日"
```
Dictionary から取得した値を MsgBox で表示。

### 課題
解説は異常であるが、このプログラムの問題点として13月や32日の存在を排除できていないことがあげられる。完璧を期すのであれば対策のプログラムを作成することが望まれる。