営業日数を取得するVBScript（Excel の〔WORKDAY関数〕〔NETWORKDAYS関数〕の代替）

土日祝日を飛ばして計算すればよいだけなので、コード自体はさして難しくはない。
問題は祝日のデータをどうするかで、祝日リストを配列もしくはコレクションとして持ちたいが、VBScriptには`Collection`オブジェクトがない。
`CreateObject("System.Collections.ArrayList")`を使えばコレクションを作ることができるが、.Net Framework3.5 が必要。
また、祝日リストを直接配列にするのも、ひとつひとつの祝日データにいちいちインデックスを与えるのが面倒だ。
よって、

1. 祝日リストを一旦文字列データにする。
2. `Split`関数で文字列データの配列にする。
3. `DateValue`関数でそれぞれの要素を日付データに変換して日付（祝日）データの配列にする。

こうすることで、祝日リストに変更があった場合も文字列データを増減・修正するだけでよい。

```vb:GetWorkdays.vbs
Option Explicit

'// テスト結果
Msgbox GetNetWorkdays(#2021/4/28#, #2021/5/7#)
' ⇒ 4
Msgbox GetWorkday(#2021/4/28#, 3)
' ⇒ 2021/05/07
```

```vb
'// 開始日（start_date）から終了日（end_date）までの営業日数を返す
Function GetNetWorkdays(ByVal start_date, ByVal end_date)

	Dim n: n = 0

	Do
		If Not IsHoliday(start_date) Then n = n + 1
		start_date = start_date + 1
	Loop While start_date <= end_date

	GetNetWorkdays = n

End Function
```

```vb
'// 起算日（start_date）から d 営業日後の日付を返す
Function GetWorkday(ByVal start_date, ByVal d)

    Dim n: n = 0

    If d > 0 Then
    	'// d が正なら d 営業日後の日付を返す
        Do While n < d
            start_date = start_date + 1
            If IsHoliday(start_date) = False Then
                n = n + 1
            End If
        Loop
    Else
    	'// d が負なら d 営業日前の日付を返す
        Do While n > d
            start_date = start_date - 1
            If IsHoliday(start_date) = False Then
                n = n - 1
            End If
        Loop
    End If

    GetWorkday = start_date

End Function
```

```vb
'// 与えられた日付が土日祝日かを判定する
Function IsHoliday(ByVal tgt_date)

	Dim holiday

	IsHoliday = False

    If Weekday(tgt_date) = 1 Then IsHoliday = True: Exit Function
    If Weekday(tgt_date) = 7 Then IsHoliday = True: Exit Function

	For Each holiday In GetHolidays
    	If tgt_date = holiday Then IsHoliday = True: Exit Function
    Next

End Function
```

```vb
'// 祝日の配列を返す
Function GetHolidays()

	Dim i, holidayAry, holidays: holidays = ""
	
	holidays = "2021/01/01"
	holidays = holidays & vbCrLf & "2021/01/11"
	holidays = holidays & vbCrLf & "2021/02/11"
	holidays = holidays & vbCrLf & "2021/02/23"
	holidays = holidays & vbCrLf & "2021/03/20"
	holidays = holidays & vbCrLf & "2021/04/29"
	holidays = holidays & vbCrLf & "2021/05/03"
	holidays = holidays & vbCrLf & "2021/05/04"
	holidays = holidays & vbCrLf & "2021/05/05"
	holidays = holidays & vbCrLf & "2021/07/22"
	holidays = holidays & vbCrLf & "2021/07/23"
	holidays = holidays & vbCrLf & "2021/08/08"
	holidays = holidays & vbCrLf & "2021/08/09"
	holidays = holidays & vbCrLf & "2021/09/20"
	holidays = holidays & vbCrLf & "2021/09/23"
	holidays = holidays & vbCrLf & "2021/11/03"
	holidays = holidays & vbCrLf & "2021/11/23"
	holidays = holidays & vbCrLf & "2022/01/01"
	holidays = holidays & vbCrLf & "2022/01/10"
	holidays = holidays & vbCrLf & "2022/02/11"
	holidays = holidays & vbCrLf & "2022/02/23"
	holidays = holidays & vbCrLf & "2022/03/21"
	holidays = holidays & vbCrLf & "2022/04/29"
	holidays = holidays & vbCrLf & "2022/05/03"
	holidays = holidays & vbCrLf & "2022/05/04"
	holidays = holidays & vbCrLf & "2022/05/05"
	holidays = holidays & vbCrLf & "2022/07/18"
	holidays = holidays & vbCrLf & "2022/08/11"
	holidays = holidays & vbCrLf & "2022/09/19"
	holidays = holidays & vbCrLf & "2022/09/23"
	holidays = holidays & vbCrLf & "2022/10/10"
	holidays = holidays & vbCrLf & "2022/11/03"
	holidays = holidays & vbCrLf & "2022/11/23"
	holidays = holidays & vbCrLf & "2023/01/01"
	holidays = holidays & vbCrLf & "2023/01/02"
	holidays = holidays & vbCrLf & "2023/01/09"
	holidays = holidays & vbCrLf & "2023/02/11"
	holidays = holidays & vbCrLf & "2023/02/23"
	holidays = holidays & vbCrLf & "2023/03/21"
	holidays = holidays & vbCrLf & "2023/04/29"
	holidays = holidays & vbCrLf & "2023/05/03"
	holidays = holidays & vbCrLf & "2023/05/04"
	holidays = holidays & vbCrLf & "2023/05/05"
	holidays = holidays & vbCrLf & "2023/07/17"
	holidays = holidays & vbCrLf & "2023/08/11"
	holidays = holidays & vbCrLf & "2023/09/18"
	holidays = holidays & vbCrLf & "2023/09/23"
	holidays = holidays & vbCrLf & "2023/10/09"
	holidays = holidays & vbCrLf & "2023/11/03"
	holidays = holidays & vbCrLf & "2023/11/23"
	holidays = holidays & vbCrLf & "2024/01/01"
	holidays = holidays & vbCrLf & "2024/01/08"
	holidays = holidays & vbCrLf & "2024/02/11"
	holidays = holidays & vbCrLf & "2024/02/12"
	holidays = holidays & vbCrLf & "2024/02/23"
	holidays = holidays & vbCrLf & "2024/03/20"
	holidays = holidays & vbCrLf & "2024/04/29"
	holidays = holidays & vbCrLf & "2024/05/03"
	holidays = holidays & vbCrLf & "2024/05/04"
	holidays = holidays & vbCrLf & "2024/05/05"
	holidays = holidays & vbCrLf & "2024/05/06"
	holidays = holidays & vbCrLf & "2024/07/15"
	holidays = holidays & vbCrLf & "2024/08/11"
	holidays = holidays & vbCrLf & "2024/08/12"
	holidays = holidays & vbCrLf & "2024/09/16"
	holidays = holidays & vbCrLf & "2024/09/22"
	holidays = holidays & vbCrLf & "2024/09/23"
	holidays = holidays & vbCrLf & "2024/10/14"
	holidays = holidays & vbCrLf & "2024/11/03"
	holidays = holidays & vbCrLf & "2024/11/04"
	holidays = holidays & vbCrLf & "2024/11/23"

	holidayAry = Split(holidays, vbCrLf)

	For i = LBound(holidayAry) To UBound(holidayAry)
		holidayAry(i) = DateValue(holidayAry(i))
	Next

	GetHolidays = holidayAry

End Function
```
---
＜更新履歴＞
- 2022/05/23
  + GetWorkday関数の引数dが負の場合の不等号の向きを修正