어느 날짜가 공휴일이면 이후 첫번째 근무일을 찾는 경우가 있습니다.
이를 함수로 구현해 봅니다.
함수의 인수로는 지정일자, 주말휴일, 공휴일 목록, 검색방향 4개를 사용합니다.
주말 휴일은 NetWorkDays.Intl함수에서와 같은 주말휴일 옵션을 사용합니다.
Public Function FindWorkDay(StartDate As Date, _
Optional Weekend As Variant = 1, _
Optional Holidays As Variant, _
Optional Direction As Integer = 1)
내부적으로 사용할 변수를 지정합니다.
Dim sWeekend As String '// 요일별 근무일/휴무일 지정
Dim vHolidays As Variant '// 휴일 목록
Dim d As Date '// 점검할 날짜
Dim iWeekday As Integer '// 점검할 날짜의 요일
함수에 입력된 인수들을 점검합니다.
휴일목록이 입력되지 않으면 Empty로 기본값을 설정하고, 범위를 지정했으면 배열로 전환합니다.
범위나 배열이 아닌 경우 강제로 배열로 만들어 이후 처리를 배열로만 처리하도록 조정합니다.
'// 인수 점검
If IsMissing(Holidays) Then Holidays = Empty
If TypeName(Holidays) = "Ragne" Then vHolidays = Holidays.Value2 Else vHolidays = Holidays
If Not isArray(vHolidays) Then ReDim vHolidays(0): vHolidays(0) = Holidays
주말지정이 근무일을 표시하는 "0"과 휴일을 표시하는 "1"로만 구성된 "0000011"형태가 아니면 오류 처리
'// 주말을 "0000011"형태의 문자열 인수 형태로 통일
If Application.isNumber(Weekend) Then
Select Case CLng(Weekend) '// 1비근무일, 0근무일 -> NetWorkDay.Intl 함수의 옵션과 같음
Case 1: sWeekend = "0000011" '//토,일
Case 2: sWeekend = "1000001" '//일,월
Case 3: sWeekend = "1100000" '//월,화
Case 4: sWeekend = "0110000" '//화,수
Case 5: sWeekend = "0011000" '//수,목
Case 6: sWeekend = "0001100" '//목,금
Case 7: sWeekend = "0000110" '//금,토
Case 11: sWeekend = "0000001" '//일
Case 12: sWeekend = "1000000" '//월
Case 13: sWeekend = "0100000" '//화
Case 14: sWeekend = "0010000" '//수
Case 15: sWeekend = "0001000" '//목
Case 16: sWeekend = "0000100" '//금
Case 17: sWeekend = "0000010" '//토
Case Else: FindWorkDay = CVErr(xlErrValue): Exit Function
End Select
Else
'// 문자열로 강제 변경하고 변경이 안되는 것은 오류 처리
On Error Resume Next
sWeekend = CStr(Weekend)
If Err.Number <> 0 Then FindWorkDay = CVErr(xlErrValue): Exit Function
On Error GoTo 0
'// "0"과 "1"로만 구성되어 있지 않으면 오류처리
If Not IsNumeric(sWeekend) Then FindWorkDay = CVErr(xlErrValue): Exit Function
If Replace(Replace(sWeekend, "0", ""), "1", "") <> "" Then FindWorkDay = CVErr(xlErrValue): Exit Function
End If
If sWeekend = "1111111" Or Len(sWeekend) <> 7 Then FindWorkDay = CVErr(xlErrValue): Exit Function
진행방향에 따라 날짜를 하루씩 변경해가며서 근무일이면 날짜를 출력하고, 근무일을 못찾고 1년을 경과하면 오류 처리합니다. (ArrayExist 함수는 여기 참조)
For d = StartDate To StartDate + IIf(Direction > 0, 365, -365) Step IIf(Direction > 0, 1, -1)
iWeekday = Weekday(d, vbMonday)
If Not ArrayExists(Holidays, d) Then
If Mid(sWeekend, iWeekday, 1) = "0" Then
FindWorkDay = d
Exit Function
End If
End If
Next d
FindWorkDay = CVErr(xlErrNA)
End Function
진행방향을 명확히 지정하는 NextWorkDay와 PrevWorkDay라는 Wrapper 함수도 만들어 줍니다.
Public Function NextWorkDay(StartDate As Date, Optional Weekend As Variant = 1, Optional Holidays As Variant)
NextWorkDay = FindWorkDay(StartDate, Weekend, Holidays, 1)
End Function
Public Function PrevWorkDay(StartDate As Date, Optional Weekend As Variant = 1, Optional Holidays As Variant)
PrevWorkDay = FindWorkDay(StartDate, Weekend, Holidays, -1)
End Function
'Excel - VBA' 카테고리의 다른 글
Outlook을 이용하여 Email 발송하기 (0) | 2023.08.03 |
---|---|
Chart의 이벤트를 사용하기 (0) | 2023.08.01 |
대량의 목록을 한 번에 VLOOKUP 조회하는 mass VLOOKUP (0) | 2023.07.26 |
Naver 파파고 API를 이용한 번역함수 만들기 (0) | 2023.07.11 |
Google 번역 앱을 이용한 번역 함수 만들기 (0) | 2023.07.11 |