堕天使系列里番:用Excel自定义函数计算工作日2

来源:百度文库 编辑:偶看新闻 时间:2024/07/02 16:54:49
用Excel自定义函数计算工作日 文章来源:PCM    作者:其他   2006-10-20

 

▲用WorkDays函数计算两个日期值之间的工作日数
Function WorkDays(start_date As Date, end_date As Date, holidays As Range, nonholidays As Range)
  Dim cur_date As Date, date1 As Date, date2 As Date, day_count As Integer, day As Variant
  date1 = IIf(start_date <= end_date, start_date, end_date)
  date2 = IIf(start_date <= end_date, end_date, start_date)

  cur_date = date1
  day_count = 0
  Do While cur_date <= date2
    If Weekday(cur_date, 2) >= 1 And Weekday(cur_date, 2) <= 5 Then
      day_count = day_count + 1
    End If
    cur_date = cur_date + 1
  Loop
  For Each day In holidays
    If day >= date1 And day <= date2 Then
      If Weekday(day, 2) >= 1 And Weekday(day, 2) <= 5 Then
        day_count = day_count - 1
      End If
    End If
  Next
  For Each day In nonholidays
    If day >= date1 And day <= date2 Then
      If Weekday(day, 2) = 6 Or Weekday(day, 2) = 7 Then
        day_count = day_count + 1
      End If
    End If
  Next
  WorkDays = IIf(start_date <= end_date, day_count, -day_count)
End Function

说明:在以上代码中,首先计算开始日期start_date和终止日期end_date之间非周末的天数,然后通过检查holidays减去非周末的节假日天数,再通过检查nonholidays加上作为工作日的周末的天数,最后即可得到两个日期相隔的工作日数。值得注意的是,如果日期start_date大于end_date,结果将为负值。

▲用NextWorkDay函数计算相隔指定工作日数之前或之后的日期

Function NextWorkDay(start_date As Date, days As Integer, holidays As Range, nonholidays As Range)
  Dim cur_date As Date, day_count As Integer, flag As Boolean, day As Variant
  cur_date = start_date
  day_count = 0
  Do While day_count < Abs(days)
    cur_date = cur_date + Sgn(days)
    Select Case Weekday(cur_date, 2)
      Case 1 To 5
        flag = True
        For Each day In holidays
          If day = cur_date Then flag = False
        Next
        If flag Then day_count = day_count + 1
      Case 6, 7
        flag = True
        For Each day In nonholidays
          If day = cur_date Then flag = False
        Next
        If Not flag Then day_count = day_count + 1
    End Select
  Loop
  NextWorkDay = cur_date

End Function

说明:在以上代码中,通过日期逐次递增或递减的方法检查所得日期是否为工作日,如果是非周末则检查holidays,如果是周末则检查nonholidays,直至累计到指定的天数为止。

应用举例
    根据2006年春节的放假规定,1月29日-2月4日(农历大年初一至初七)放假,共7天。其中,29日、30日、31日为法定假日,将1月28日(星期六)、29日(星期日)、2月5日(星期日)三个公休日调至2月1日(星期三)、2日(星期四)、3日(星期五),2月4日(星期六)照常公休,1月28日、2月5日上班。因此在本例中,首先把2006年春节期间非周末的节假日存入到区域A2:A6中。由于1月29日、2月4日本来就是周末,所以该区域只需存放1月30日、31日、2月1日、2日和3日。接着再把作为工作日的周末存入到区域B2:B3中,该区域有1月28日和2月5日两天。然后据此在F2单元格中输入公式“=WorkDays(D2,E2,A2:A6,B2:B3)”,计算2006年1月6日至2006年3月1日之间的工作日数;并在F6单元格中输入公式“=NextWorkDay(D6,E6,A2:A6,B2:B3)”,以2006年1月6日为起始日期计算30个工作日后的日期。结果如下图所示。

输入起止日期工作日立即自动算出