(Excel用)1年に満たない端数期間の日数を平年日と閏年日に分けて計算する自作関数 FRACDAYS

1年に満たない端数期間の日数を、平年日と閏年日に分けて計算するユーザー定義関数 FRACDAYS を作りました。
例えば、平成26年12月1日から平成28年8月1日までの期間について考えると、①まず平成26年12月1日から平成27年11月30日までが1年間で、1年に満たない端数期間は平成27年12月1日から平成28年8月1日となります。②このうち、平成27年は平年、平成28年閏年ですので、端数期間のうち平年日は平成27年12月1日から平成27年12月31日まで31日間、端数期間のうち閏年日は平成28年1月1日から平成28年8月1日まで214日間となります。これを関数一つで計算するのが、この FRACDAYS 関数です。(Excel用)裁判所における計算方法に従った利息計算を行う自作関数 INTCAL - 法律事務雑記帳と併せてお使いください。
なお、INTCAL と同じく、ktDATEDIF(http://addinbox.sakura.ne.jp/Excel_Tips05.htm#ktDATEDIF2)が必要です。

使い方

=FRACDAYS(期間開始日, 期間終了日, [平年閏年の指定, ][初日算入の指定])

「平年閏年の指定」以下は省略可です。省略した場合、「平年閏年の指定」は「平年」、「初日算入の指定」は「初日不算入(片端入れ)」となります。
「平年閏年の指定」には、0又は1を入力してください。0の場合は「平年」、1の場合は「閏年」となります。
「初日算入の指定」には、0又は1を入力してください。0の場合は「初日不算入(片端入れ)」、1の場合は「初日算入(両端入れ)」となります。

使用例

平成26年12月1日から平成28年8月1日までの期間(初日算入〔両端入れ〕)について
(1) 1年に満たない端数期間の平年日を調べるとき

=FRACDAYS("2014/12/1", "2016/8/1", 0, 1) → 31

(2) 1年に満たない端数期間の閏年日を調べるとき

=FRACDAYS("2014/12/1", "2016/8/1", 1, 1) → 214

FRACDAYS のコード本体

'端数の日数を平年・閏年に分けて計算する関数 FRACDAYS
Function FRACDAYS(期間開始日 As Date, 期間終了日 As Date, Optional 平年閏年の指定 As Integer = 0, _
                    Optional 初日算入の指定 As Integer = 0)
    'opt4 平年閏年の指定
    '       0(default)  平年
    '       1           閏年
    'opt2 初日算入の指定
    '       0(default)  初日不算入(片端入れ)
    '       1           初日算入(両端入れ)
    
    date_begin = 期間開始日
    date_end = 期間終了日
    opt4 = 平年閏年の指定
    opt2 = 初日算入の指定
    
    '初日算入の処理
    date_begin = date_begin - opt2
    
    Dim y, d As Integer
    Dim common_year_days As Integer '平年の日数
    Dim leap_year_days As Integer '閏年の日数
  
    y = ktDATEDIF(date_begin, date_end, "Y")
    date_recent = DateAdd("yyyy", y, date_begin)
    
    '端数期間が同じ年の場合
    If year(date_recent) = year(date_end) Then
        d = ktDATEDIF(date_begin, date_end, "YD")
        If IsLeapYear(year(date_end)) Then '端数期間が閏年のとき
            common_year_days = 0
            leap_year_days = d
        Else '端数期間が平年のとき
            common_year_days = d
            leap_year_days = 0
        End If
        
    '端数期間が別の年の場合
    Else
        days_first = ktDATEDIF(date_recent, DateSerial(year(date_recent), 12, 31), "YD")
        days_second = ktDATEDIF(DateSerial(year(date_recent), 12, 31), date_end, "YD")
        
        '最初の期間が閏年のとき
        If IsLeapYear(year(date_recent)) Then
            common_year_days = days_second
            leap_year_days = days_first
        '後の期間が閏年のとき
        ElseIf IsLeapYear(year(date_end)) Then
            common_year_days = days_first
            leap_year_days = days_second
        'いずれも平年のとき
        Else
            common_year_days = ktDATEDIF(date_begin, date_end, "YD")
        End If
        
    End If
    
    Select Case opt4
    Case 0
        FRACDAYS = common_year_days
    Case 1
        FRACDAYS = leap_year_days
    End Select
    
    'optが指定の数字以外の場合にエラーを出す
    If Not (((opt2 = 0) Or (opt2 = 1)) And ((opt4 = 0) Or (opt4 = 1))) Then
        FRACDAYS = CVErr(xlErrValue)
    End If

End Function

'閏年判定
Function IsLeapYear(yyyy As Integer) As Boolean
    Dim b As Boolean
    If ((yyyy Mod 4) = 0 And (yyyy Mod 100) <> 0 Or (yyyy Mod 400) = 0) Then
        b = True
    Else
        b = False
    End If
    IsLeapYear = b
End Function

「関数ライブラリ」からダイアログボックスにより FRACDAYS 関数を利用する

Sub RegisterFRACDAYS()
  
    Application.MacroOptions Macro:="FRACDAYS", _
    Description:="1年に満たない端数部分につき、平年の日数又は閏年の日数を返します。", _
    Category:="日付/時刻", ArgumentDescriptions:=Array( _
              "には対象となる期間の開始日を指定します。", _
              "には対象となる期間の終了日を指定します。", _
              "0: 平年(default)" & vbCrLf & "1: 閏年", _
              "0: 初日不算入(片端入れ)(default)" & vbCrLf & "1: 初日算入(両端入れ)"), _
    HelpFile:=""
    
End Sub