Public Sub 経過年月日設定()
Range("B4").Value = ktDATEDIF(Range("A4").Value, Range("B1").Value, "Y")
Range("C4").Value = ktDATEDIF(Range("A4").Value, Range("B1").Value, "YM")
Range("D4").Value = ktDATEDIF(Range("A4").Value, Range("B1").Value, "MD")
End Sub
Public Function ktDATEDIF(ByVal StartDate As Date, _
ByVal EndDate As Date, _
ByVal Interval As String) As Variant
' [Interval]
' YMD :"y年mヶ月d日"で編集(文字列)
' Y :期間内満年数
' M :期間内満総月数
' YM :年未満の端数の月数
' MD :月未満の端数の日数
' YD :年未満の端数の日数
' FR :年比率(Double型, YEARFRACモード)
'(注)
' Interval="FR"は、YEARFRAC関数の[基準:1(Actual/Actual)]に相当しますが、
' YEARFRACとは計算方法が異なり、『抽象的2月29日説』に基づいています。
' 実務規則に合致しているかを確認してから利用して下さい。
' (例)
' 2003/5/10 - 2007/6/20 → 4年41日間 → 4.1120218579 ( = 41/366)
' [2003/5/10(ex) - 2007/5/10(in)]で4年間。[2007/5/11(in) - 6/20(in)]で41日間。
' [2007/5/11(in) - 6/20 - 2008/5/10(in)]の間に2/29があるので366日/年。
'
' 2003/5/10 - 2008/6/20 → 5年41日間 → 5.1123287671 ( = 41/365)
' [2003/5/10(ex) - 2008/5/10(in)]で5年間。[2008/5/11(in) - 6/20(in)]で41日間。
' [2008/5/11(in) - 6/20 - 2009/5/10(in)]の間に2/29がないので365日/年。
Dim wkDate As Date
Dim lngMonth As Long '総月数(13ヶ月 など)
Dim intYear As Integer
Dim intMonth_in_Year As Integer '年未満の月数
Dim intDay_in_Month As Integer '月未満の日数
Dim intDay_in_Year As Integer '年未満の日数
Dim dblFrac As Double
Dim intFracDays As Integer '[年未満の日数]部分の初日から1年間の日数
'(その1年間に2/29がある→366、ない→365)
If (StartDate > EndDate) Then
ktDATEDIF = CVErr(xlErrValue)
'ktDATEDIF = "Error" 'OOo.BasicではCVErr(xlErrValue)が使えない
Exit Function
End If
'注)[DateDiff関数]自体は初日不算入で処理している
' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
If (Day(StartDate + 1) = 1) Then
'起算日が1日(開始日が月末日)の場合、月の大小閏に係わりなく
'[月末日]までで『丸Nヶ月』
'月の大小閏に影響されないように「月末日~終了日」を1日分シフトして
'「1日~(終了日+1)」で求める。
lngMonth = DateDiff("m", (StartDate + 1), (EndDate + 1))
intYear = lngMonth \ 12
intMonth_in_Year = lngMonth Mod 12
If (Day(EndDate + 1) = 1) Then '満了日(終了日)が月末か?
intDay_in_Month = 0
Else
intDay_in_Month = Day(EndDate)
End If
wkDate = DateAdd("yyyy", intYear, (StartDate + 1)) '(StartDate+1)は[1日]
intDay_in_Year = DateDiff("d", wkDate, (EndDate + 1))
If (intDay_in_Year > 0) Then
intFracDays = DateAdd("yyyy", 1, wkDate) - wkDate '365 or 366
End If
Else
'起算日≠1日の場合、「起算日の応当日前日」までで『丸Nヶ月』
lngMonth = DateDiff("m", StartDate, EndDate)
wkDate = DateAdd("m", lngMonth, StartDate)
If (wkDate > EndDate) Then
lngMonth = lngMonth - 1
wkDate = DateAdd("m", lngMonth, StartDate)
End If
intDay_in_Month = DateDiff("d", wkDate, EndDate)
intYear = lngMonth \ 12
intMonth_in_Year = lngMonth Mod 12
wkDate = DateAdd("yyyy", intYear, StartDate)
intDay_in_Year = DateDiff("d", wkDate, EndDate)
If (intDay_in_Year > 0) Then
intFracDays = DateAdd("yyyy", 1, wkDate) - wkDate '365 or 366
End If
End If
' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select Case UCase(Interval)
Case "YMD"
ktDATEDIF = intYear & "年" & intMonth_in_Year & "ヶ月" & intDay_in_Month & "日"
Case "Y"
ktDATEDIF = intYear
Case "M"
ktDATEDIF = lngMonth
Case "YM"
ktDATEDIF = intMonth_in_Year
Case "MD"
ktDATEDIF = intDay_in_Month
Case "YD"
ktDATEDIF = intDay_in_Year
Case "FR"
If (intDay_in_Year > 0) Then
dblFrac = intDay_in_Year / CDbl(intFracDays) '整数演算とならないように型変換
ktDATEDIF = CDbl(intYear + dblFrac)
Else
ktDATEDIF = CDbl(intYear) '年未満の日数が無いので小数は出ない
End If
Case Else
ktDATEDIF = CVErr(xlErrValue)
'ktDATEDIF = "Error" 'OOo.BasicではCVErr(xlErrValue)が使えない
End Select
End Function