ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
楼主: 娃泰贤

[求助] EXCEL 时间函数难题 就高人指点

[复制链接]

TA的精华主题

TA的得分主题

 楼主| 发表于 2013-4-11 22:33 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
yygpdkkk 发表于 2013-4-11 02:09
为此题花了7、8个小时,晕死。
另:代码未经严格测试(短时间内考虑不到那么多细节数据)
代码更新:经再 ...

Sub lqxs()
Function MyTime(theStartDate As Variant, theEndDate As Variant) As Variant
Dim theDate1 As Date, theDate2 As Date, theTime1 As Date, theTime2 As Date, i&
MyTime = 0 '确保一次赋值
If Not IsDate(theStartDate) Or Not IsDate(theEndDate) Then '若非法日期,则
Print MyTime = CVErr(xlErrNA) '返回错误值
        Exit Function
    End If
    If theEndDate - theStartDate < 0 Then
        MyTime = CVErr(xlErrNA) '若发起时间大于结束时间,则返回错误值
        Exit Function
    End If
    If Weekday(theStartDate, vbMonday) > 5 Then '若发起时间为周六或周日,则进一步判断结束时间
        If Weekday(theEndDate, vbMonday) > 5 Then '若结束时间也为周六或周日,则进一步判断是否跨越了一周
            If theEndDate - theStartDate < 6 Then MyTime = 0 '若非跨一周,则返回0值
        End If
    End If
    theDate1 = DateSerial(Year(theStartDate), Month(theStartDate), Day(theStartDate))
    theTime1 = theStartDate - theDate1
    theDate2 = DateSerial(Year(theEndDate), Month(theEndDate), Day(theEndDate))
    theTime2 = theEndDate - theDate2
    Select Case theTime1 '确定发起时间(仅指时间部分,不含日期)
        Case Is < TimeValue("9:00:01") '若发起时间早于上午9点,则确定为9点起始
            theTime1 = TimeValue("9:00:00")
        Case Is < TimeValue("12:00:01") '若发起时间早于正午,则theTime1就是发起时间,不用调整
        Case Is < TimeValue("14:00:01") '若发起时间早于下午14点,则确定为12点起始(此处很重要)
            theTime1 = TimeValue("12:00:00")
        Case Is < TimeValue("18:00:01") '若发起时间早于下午18点,则theTime1就是发起时间,不用调整
        Case Else '否则确定为18:00:00
            theTime1 = TimeValue("18:00:00")
    End Select
    Select Case theTime2 '确定结束时间(仅指时间部分,不含日期)
        Case Is < TimeValue("9:00:01") '若结束时间早于上午9点,则确定为上午9:00:00
            theTime2 = TimeValue("9:00:00")
        Case Is < TimeValue("12:00:01") '若结束时间早于正午,则theTime2就是结束时间,不用调整
        Case Is < TimeValue("14:00:01") '若结束时间早于下午14点零1分,则确定为中午12点结束(此处很重要)
            theTime2 = TimeValue("12:00:00") '(承上述)此处故意把结束时间往早前推(不设为14:00:00),
            '从而与theTime1的12:00:00这一时间点重叠,巧妙地使后续代码的时间相减融为一体,从而不用再专门写代码进行修正
        Case Is < TimeValue("18:00:01") '若结束时间早于下午18点,则theTime2就是结束时间,不用调整
        Case Else '否则确定为18:00:00
            theTime2 = TimeValue("18:00:00")
    End Select
    If theDate1 = theDate2 Then '若发起日期与结束日期为同一天,则
        If Weekday(theDate1, vbMonday) < 6 Then '若日期为周一至周五,则
            If theTime1 < TimeValue("12:00:01") Then
                If theTime2 < TimeValue("14:00:01") Then
                    MyTime = theTime2 - theTime1 '两个时间均处于上午,则直接相减
                Else
                    MyTime = TimeValue("12:00:00") - theTime1 '先计算出上午时长
                    MyTime = MyTime + theTime2 - TimeValue("14:00:00") '再加上下午时长
                End If
            Else '否则,两个时间均处于下午
                 MyTime = theTime2 - theTime1 '仅下午时长
            End If
        End If
    Else '否则,发起日期与结束日期不为同一天
        If Weekday(theDate1, vbMonday) < 6 Then '先计算发起日的时长
            If theTime1 < TimeValue("12:00:01") Then
                MyTime = TimeValue("12:00:00") - theTime1 '先计算出上午时长
                MyTime = MyTime + TimeValue("4:00:00") '再加上下午时长
            Else '否则,计算发起日的下午时长
                MyTime = TimeValue("18:00:00") - theTime1 '仅存在下午时长
            End If
        End If
        If Weekday(theDate2, vbMonday) < 6 Then '再计算结束日的时长
            If theTime2 < TimeValue("12:00:01") Then '计算结束日的上午时长
                MyTime = MyTime + theTime2 - TimeValue("9:00:00") '仅存在上午时长
            Else '否则计算结束日的时长
                MyTime = MyTime + TimeValue("3:00:00") + theTime2 - TimeValue("14:00:00") '上午3小时和下午时长
            End If
        End If
    End If
    For i = theDate1 + 1 To theDate2 - 1 '介于发起日和结束日之间的其他天数必定为7小时
        If Weekday(i, vbMonday) < 6 Then
            MyTime = MyTime + TimeValue("7:00:00")
        End If
    Next i
End Function
End Sub

我点运行 提示 缺少 End Sub,但我实在 有在代码的后面 有加 ,所以不知道错在哪,嘿嘿

TA的精华主题

TA的得分主题

 楼主| 发表于 2013-4-11 22:36 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
yygpdkkk 发表于 2013-4-11 02:09
为此题花了7、8个小时,晕死。
另:代码未经严格测试(短时间内考虑不到那么多细节数据)
代码更新:经再 ...

Sub lqxs()
Function MyTime(theStartDate As Variant, theEndDate As Variant) As Variant
Dim theDate1 As Date, theDate2 As Date, theTime1 As Date, theTime2 As Date, i&
MyTime = 0 '确保一次赋值
If Not IsDate(theStartDate) Or Not IsDate(theEndDate) Then '若非法日期,则
Print MyTime = CVErr(xlErrNA) '返回错误值
        Exit Function
    End If
    If theEndDate - theStartDate < 0 Then
        MyTime = CVErr(xlErrNA) '若发起时间大于结束时间,则返回错误值
        Exit Function
    End If
    If Weekday(theStartDate, vbMonday) > 5 Then '若发起时间为周六或周日,则进一步判断结束时间
        If Weekday(theEndDate, vbMonday) > 5 Then '若结束时间也为周六或周日,则进一步判断是否跨越了一周
            If theEndDate - theStartDate < 6 Then MyTime = 0 '若非跨一周,则返回0值
        End If
    End If
    theDate1 = DateSerial(Year(theStartDate), Month(theStartDate), Day(theStartDate))
    theTime1 = theStartDate - theDate1
    theDate2 = DateSerial(Year(theEndDate), Month(theEndDate), Day(theEndDate))
    theTime2 = theEndDate - theDate2
    Select Case theTime1 '确定发起时间(仅指时间部分,不含日期)
        Case Is < TimeValue("9:00:01") '若发起时间早于上午9点,则确定为9点起始
            theTime1 = TimeValue("9:00:00")
        Case Is < TimeValue("12:00:01") '若发起时间早于正午,则theTime1就是发起时间,不用调整
        Case Is < TimeValue("14:00:01") '若发起时间早于下午14点,则确定为12点起始(此处很重要)
            theTime1 = TimeValue("12:00:00")
        Case Is < TimeValue("18:00:01") '若发起时间早于下午18点,则theTime1就是发起时间,不用调整
        Case Else '否则确定为18:00:00
            theTime1 = TimeValue("18:00:00")
    End Select
    Select Case theTime2 '确定结束时间(仅指时间部分,不含日期)
        Case Is < TimeValue("9:00:01") '若结束时间早于上午9点,则确定为上午9:00:00
            theTime2 = TimeValue("9:00:00")
        Case Is < TimeValue("12:00:01") '若结束时间早于正午,则theTime2就是结束时间,不用调整
        Case Is < TimeValue("14:00:01") '若结束时间早于下午14点零1分,则确定为中午12点结束(此处很重要)
            theTime2 = TimeValue("12:00:00") '(承上述)此处故意把结束时间往早前推(不设为14:00:00),
            '从而与theTime1的12:00:00这一时间点重叠,巧妙地使后续代码的时间相减融为一体,从而不用再专门写代码进行修正
        Case Is < TimeValue("18:00:01") '若结束时间早于下午18点,则theTime2就是结束时间,不用调整
        Case Else '否则确定为18:00:00
            theTime2 = TimeValue("18:00:00")
    End Select
    If theDate1 = theDate2 Then '若发起日期与结束日期为同一天,则
        If Weekday(theDate1, vbMonday) < 6 Then '若日期为周一至周五,则
            If theTime1 < TimeValue("12:00:01") Then
                If theTime2 < TimeValue("14:00:01") Then
                    MyTime = theTime2 - theTime1 '两个时间均处于上午,则直接相减
                Else
                    MyTime = TimeValue("12:00:00") - theTime1 '先计算出上午时长
                    MyTime = MyTime + theTime2 - TimeValue("14:00:00") '再加上下午时长
                End If
            Else '否则,两个时间均处于下午
                 MyTime = theTime2 - theTime1 '仅下午时长
            End If
        End If
    Else '否则,发起日期与结束日期不为同一天
        If Weekday(theDate1, vbMonday) < 6 Then '先计算发起日的时长
            If theTime1 < TimeValue("12:00:01") Then
                MyTime = TimeValue("12:00:00") - theTime1 '先计算出上午时长
                MyTime = MyTime + TimeValue("4:00:00") '再加上下午时长
            Else '否则,计算发起日的下午时长
                MyTime = TimeValue("18:00:00") - theTime1 '仅存在下午时长
            End If
        End If
        If Weekday(theDate2, vbMonday) < 6 Then '再计算结束日的时长
            If theTime2 < TimeValue("12:00:01") Then '计算结束日的上午时长
                MyTime = MyTime + theTime2 - TimeValue("9:00:00") '仅存在上午时长
            Else '否则计算结束日的时长
                MyTime = MyTime + TimeValue("3:00:00") + theTime2 - TimeValue("14:00:00") '上午3小时和下午时长
            End If
        End If
    End If
    For i = theDate1 + 1 To theDate2 - 1 '介于发起日和结束日之间的其他天数必定为7小时
        If Weekday(i, vbMonday) < 6 Then
            MyTime = MyTime + TimeValue("7:00:00")
        End If
    Next i
End Function
End Sub

我点运行 提示 缺少 End Sub,但我实在 有在代码的后面 有加 ,所以不知道错在哪,嘿嘿

TA的精华主题

TA的得分主题

发表于 2013-4-11 22:56 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
本帖最后由 yygpdkkk 于 2013-4-11 22:57 编辑
娃泰贤 发表于 2013-4-11 22:36
Sub lqxs()
Function MyTime(theStartDate As Variant, theEndDate As Variant) As Variant
Dim theDat ...


你VBA基础太欠缺,连函数和过程的区别都不知道!!!!

上课啦,扫肓啦:函数是以Function开头,以End Function结束,就如过程以Sub开头,以End Sub结束一样!

言归正传:
1.我写的是一个函数(俗称自定义函数,自己写的嘛,故谓之“自定义”)
2.我写的函数名称是“MyTime”,当然了,在工作表单元格中输入函数时不必太在意函数名称的大小写
3.既然是函数,直接参照平时输函数的习惯输入就行了,比如在C2单元格输入以等号开头的公式“=mytime(A2,B2)”
4.你无端地在一个自定义函数的代码上再套上Sub和End Sub,也不怕他人笑掉大牙

最后:给个在工作表界面下使用该函数的图例
未命名.jpg

TA的精华主题

TA的得分主题

发表于 2013-4-11 23:04 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
娃泰贤 发表于 2013-4-11 22:24
谢谢 高手的支持  因为才开始学习VBA  但代码复制进去 有问题
  你看 可不可以 发个文档呢! 再次谢谢

原以为你已经搞定了,所以上午就没有再回复了,下面的代码是处理了星期六及星期日的自定义函数,如果要处理法定节日,你还需要自行修改getLegalHoliday这个函数的处理过程,在此函数中已经有方法介绍了,你可以根据说明自已修改一下。

  1. Function WordDateDiff(ByVal Date1 As Date, ByVal Date2 As Date, Optional ByVal OutMode As Long = 0) As String
  2.   Dim lngTime   As Long, lngDay As Long, DateTemp As Date
  3.   
  4.   Select Case Hour(Date1)                     '重新调整起始日期中的时间
  5.     Case Is < 9:  Date1 = Format$(Date1, "YYYY-MM-DD") & " 09:00:00"
  6.     Case 12, 13:  Date1 = Format$(Date1, "YYYY-MM-DD") & " 14:00:00"
  7.     Case Is > 18: Date1 = Format$((Date1 + 1), "YYYY-MM-DD") & " 09:00:00"
  8.   End Select
  9.   
  10.   Select Case Hour(Date2)                     '重新调整终止日期中的时间
  11.     Case Is < 9:  Date2 = Format$((Date2 - 1), "YYYY-MM-DD") & " 18:00:00"
  12.     Case 12, 13:  Date2 = Format$(Date2, "YYYY-MM-DD") & " 12:00:00"
  13.     Case Is > 18: Date2 = Format$(Date2, "YYYY-MM-DD") & " 18:00:00"
  14.   End Select
  15.   If Date2 < Date1 Then                       '比较调整后的日期是否合法
  16.     WordDateDiff = "Error:错误的日期输入!"   '终止日期小于起始日期,返回错误提示
  17.   Else
  18.     lngDay = DateDiff("d", Date1, Date2) - getLegalHoliday(Date1, Date2) '计算相差的天数
  19.    
  20.     '计算出两个工作时间的相差值
  21.     Date1 = CDate(Format$(Date2, "YYYY-MM-DD") & " " & Format$(Date1, "HH:NN:SS"))
  22.     If Date1 > Date2 Then
  23.       lngDay = lngDay - 1
  24.      
  25.       DateTemp = CDate(Format$(Date2, "YYYY-MM-DD") & " 09:00:00")
  26.       lngTime = DateDiff("n", DateTemp, Date2) - IIf(Hour(Date2) > 13, 120, 0)
  27.      
  28.       DateTemp = CDate(Format$(Date2, "YYYY-MM-DD") & " 18:00:00")
  29.       lngTime = lngTime + DateDiff("n", Date1, DateTemp) - IIf(Hour(Date1) < 13, 120, 0)
  30.     Else
  31.       lngTime = lngTime + DateDiff("n", Date1, Date2)
  32.       If (Hour(Date1) < 14) And (Hour(Date2) > 13) Then lngTime = lngTime - 120
  33.     End If
  34.    
  35.     lngDay = lngDay + (lngTime \ 420&)
  36.     lngTime = lngTime Mod 420
  37.     Select Case OutMode           '根据OutMode指定的方式输出结果
  38.       Case 1:     WordDateDiff = Format$(lngDay, "#00:") & Format$(lngTime \ 60, "#00:") & Format(lngTime Mod 60, "00")
  39.       Case 2:     WordDateDiff = Format$(lngDay * 7 + (lngTime \ 60), "#00小时") & Format(lngTime Mod 60, "00分钟")
  40.       Case 3:     WordDateDiff = Format$(lngDay, "#00天") & Format$(lngTime \ 60, "#00小时") & Format(lngTime Mod 60, "00分钟")
  41.       Case Else:  WordDateDiff = Format$(lngDay * 7 + (lngTime \ 60), "#00:") & Format(lngTime Mod 60, "00")
  42.     End Select
  43.   End If
  44. End Function
  45. Private Function getLegalHoliday(ByVal Date1 As Date, ByVal Date2 As Date) As Long
  46.   Dim lngNoWorkDay  As Long
  47.   Dim DateTemp      As Date
  48.   '本函数目前只处理星期六和星期日,要注意的是每年的法定节日并不相同,如果要此函数能够
  49.   '       处理所有年份的节假日,则需要数据支持,即每一年的法定节日是怎么放的及调休的……
  50.   '       这个有点难处理,关键是在于你的假日数据来源是否是正确,否则永远都得不到正确值。
  51.   DateTemp = Date1
  52.   Do While DateTemp < Date2
  53.     Select Case Weekday(DateTemp, vbMonday)
  54.       Case Is > 5: lngNoWorkDay = lngNoWorkDay + 1
  55.     End Select
  56.     DateTemp = DateTemp + 1
  57.   Loop
  58.   getLegalHoliday = lngNoWorkDay
  59. End Function
复制代码

这个是测试文档: 时间函数.rar (12.04 KB, 下载次数: 29)

TA的精华主题

TA的得分主题

发表于 2013-4-12 12:04 | 显示全部楼层
本帖最后由 张三李四 于 2013-4-12 12:42 编辑

  1. 此函数还有问题,继续修改中。
  2. Function WeekHour(Firstday As Range, Lastday As Range)
  3.     If IsDate(Firstday) = False Then
  4.       WeekHour = False
  5.       Exit Function
  6.     End If
  7.     If IsDate(Lastday) = False Then
  8.       WeekHour = False
  9.       Exit Function
  10.     End If
  11.     If CDbl(Firstday) > CDbl(Lastday) Then
  12.       WeekHour = False
  13.       Exit Function
  14.     End If
  15. FirstH = Hour(Firstday)
  16. LastH = Hour(Lastday)
  17. FirstM = Minute(Firstday)
  18. LastM = Minute(Lastday)
  19. If FirstH < 9 Then FirstH = 9: FirstM = 0: FirstM = 0
  20. If FirstH > 12 And FirstH < 14 Then FirstM = 14: FirstM = 0
  21. If FirstH > 18 Then FirstH = 18: FirstM = 0: FirstM = 0
  22. If LastH < 9 Then LastH = 9: LastM = 0: LastM = 0
  23. If LastH > 12 And LastH < 14 Then LastH = 14: LastM = 0
  24. If LastH > 18 Then LastH = 18: LastM = 0: LastM = 0
  25. Myweekday = Empty
  26. For H = Firstday To Lastday
  27.   W = Weekday(H, 2)
  28.   If W >= 1 And W <= 5 Then
  29.     Myweekday = Myweekday + 1
  30.   End If
  31. Next H
  32. If Myweekday = 0 Then
  33.       WeekHour = 0
  34.       Exit Function
  35. Else
  36.           W = Weekday(Firstday, 2)
  37.           If W < 1 Or W > 5 Then FirstH = 9: FirstM = 0
  38.           W = Weekday(Lastday, 2)
  39.           If W < 1 Or W > 5 Then LastH = 18: LastM = 0
  40.           If FirstH >= 9 And FirstH <= 12 Then


  41.             FH = FirstH - 9
  42.           ElseIf FirstH >= 14 And FirstH <= 18 Then
  43.             FH = FirstH - 14 + 3
  44.           End If
  45.          W = Weekday(Lastday, 2)
  46.          If W < 1 Or W > 5 Then LastH = 18: LastM = 0
  47.           If LastH >= 9 And LastH <= 12 Then
  48.             LH = 12 - LastH + 4
  49.             If LastM <> 0 Then
  50.               LH = LH - 1
  51.               LM = 60 - LastM
  52.             End If
  53.           ElseIf LastH >= 14 And LastH <= 18 Then
  54.             LH = 18 - LastH
  55.             If LastM <> 0 Then
  56.               LH = LH + 1
  57.               LM = 60 - LastM
  58.             End If
  59.           End If
  60.           H = LH + FH
  61.           M = LM + FirstM
  62.           If M >= 60 Then
  63.             M = 60 - (M - 60)
  64.           Else
  65.             H = H + 1
  66.             M = 60 - M
  67.           End If         
  68.          WeekHour = Format(7 * Myweekday - H & ":" & Format(M, "00"), "h:mm")
  69. End If
  70. End Function
复制代码
时间函数.JPG

TA的精华主题

TA的得分主题

发表于 2013-4-12 18:47 | 显示全部楼层
我也上个比较图,供调试参考用:
未命名.jpg

TA的精华主题

TA的得分主题

发表于 2013-4-12 19:15 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2013-4-12 19:27 | 显示全部楼层
本帖最后由 yygpdkkk 于 2013-4-12 19:44 编辑
maditate 发表于 2013-4-12 19:15
再发张图吧。


你那是我代码运行的结果?深表怀疑!我相信,即便是我最早最早前上传的代码也不至于得到2:50的结果!!!

事后补:说到joforn版主,早下载他的代码用我的数据去测试了,果不其然,与本人写的代码运行结果有出入(指就当前测试数据而言,本人代码运行正确,其代码运行结果有的正确,有的不正确),由于某些原因,懒得去跟贴,你今拿他的代码运行结果与我的代码运行结果相比较,且有joforn版主代码正确的结论之嫌疑,故明言之。此外,到目前为止,本人坚信,没有他人的代码比我的代码运行结果还正确!!

下图才是我代码运行的结果:
未命名.jpg

忘了提醒:最后一行的“3:00:00”系4月4日至4月6日为清明节放假,4月7日虽为周日,但已为调休日!!特此声明,免得。。。。

TA的精华主题

TA的得分主题

发表于 2013-4-12 22:33 | 显示全部楼层
本帖最后由 joforn 于 2013-4-12 23:32 编辑

原来的主函数被我在上传前删除了十来行代码,结果运行结果会出错。这次上传了可以处理2013、2012年节假日的函数,原有Bug已经重新修正。

  1. Function WordDateDiff(ByVal Date1 As Date, ByVal Date2 As Date, Optional ByVal OutMode As Long = 0) As String
  2.   Dim lngTime   As Long, lngDay As Long, DateTemp As Date
  3.   
  4.   If IsLegalHoliday(Date1) Then                 '如果起始日期是节假日,推后起始日期至节假后第一天的上班时间
  5.     Do While IsLegalHoliday(Date1)
  6.       Date1 = Date1 + 1
  7.     Loop
  8.     Date1 = Format$(Date1, "YYYY-MM-DD") & " 09:00:00"
  9.   Else
  10.     Select Case Hour(Date1)                     '重新调整起始日期中的时间
  11.       Case Is < 9:  Date1 = Format$(Date1, "YYYY-MM-DD") & " 09:00:00"
  12.       Case 12, 13:  Date1 = Format$(Date1, "YYYY-MM-DD") & " 12:00:00"
  13.       Case Is > 17: Date1 = Format$(Date1, "YYYY-MM-DD") & " 18:00:00"
  14.     End Select
  15.   End If
  16.   
  17.   If IsLegalHoliday(Date2) Then                 '如果终止日期是节假日,推后起始日期至节假后第一天的上班时间
  18.     Do While IsLegalHoliday(Date2)
  19.       Date2 = Date2 + 1
  20.     Loop
  21.     Date2 = Format$(Date2, "YYYY-MM-DD") & " 09:00:00"
  22.   Else
  23.     Select Case Hour(Date2)                     '重新调整终止日期中的时间
  24.       Case Is < 9:  Date2 = Format$(Date2, "YYYY-MM-DD") & " 09:00:00"
  25.       Case 12, 13:  Date2 = Format$(Date2, "YYYY-MM-DD") & " 14:00:00"
  26.       Case Is > 17: Date2 = Format$(Date2, "YYYY-MM-DD") & " 18:00:00"
  27.     End Select
  28.   End If
  29.   
  30.   If Date2 < Date1 Then                       '比较调整后的日期是否合法
  31.     WordDateDiff = "Error:错误的日期输入!"   '终止日期小于起始日期,返回错误提示
  32.   Else
  33.     lngDay = DateDiff("d", Date1, Date2) - getLegalHoliday(Date1, Date2) '计算相差的天数
  34.    
  35.     '计算出两个工作时间的相差值
  36.     Date1 = CDate(Format$(Date2, "YYYY-MM-DD") & " " & Format$(Date1, "HH:NN:SS"))
  37.     If Date1 > Date2 Then
  38.       lngDay = lngDay - 1
  39.      
  40.       DateTemp = CDate(Format$(Date2, "YYYY-MM-DD") & " 09:00:00")
  41.       lngTime = DateDiff("n", DateTemp, Date2) - IIf(Hour(Date2) > 13, 120, 0)
  42.      
  43.       DateTemp = CDate(Format$(Date2, "YYYY-MM-DD") & " 18:00:00")
  44.       lngTime = lngTime + DateDiff("n", Date1, DateTemp) - IIf(Hour(Date1) < 13, 120, 0)
  45.     Else
  46.       lngTime = lngTime + DateDiff("n", Date1, Date2)
  47.       If (Hour(Date1) < 14) And (Hour(Date2) > 13) Then lngTime = lngTime - 120
  48.     End If
  49.    
  50.     lngDay = lngDay + (lngTime \ 420&)
  51.     lngTime = lngTime Mod 420
  52.     Select Case OutMode           '根据OutMode指定的方式输出结果
  53.       Case 1:     WordDateDiff = Format$(lngDay, "#00:") & Format$(lngTime \ 60, "#00:") & Format(lngTime Mod 60, "00")
  54.       Case 2:     WordDateDiff = Format$(lngDay * 7 + (lngTime \ 60), "#00小时") & Format(lngTime Mod 60, "00分钟")
  55.       Case 3:     WordDateDiff = Format$(lngDay, "#00天") & Format$(lngTime \ 60, "#00小时") & Format(lngTime Mod 60, "00分钟")
  56.       Case Else:  WordDateDiff = Format$(lngDay * 7 + (lngTime \ 60), "#00:") & Format(lngTime Mod 60, "00")
  57.     End Select
  58.   End If
  59. End Function

  60. Private Function getLegalHoliday(ByVal Date1 As Date, ByVal Date2 As Date) As Long
  61.   Dim lngNoWorkDay  As Long
  62.   Dim DateTemp      As Date
  63.   DateTemp = Date1
  64.   Do While DateTemp < Date2
  65.     If IsLegalHoliday(DateTemp) Then lngNoWorkDay = lngNoWorkDay + 1
  66.     DateTemp = DateTemp + 1
  67.   Loop
  68.   getLegalHoliday = lngNoWorkDay
  69. End Function

  70. Private Function IsLegalHoliday(ByVal Date1 As Date) As Boolean
  71.   '本函数目前只能处理2012年及2013年的法定假期,其它年份只判断是否为星期六、星期日。
  72.   '如果有需要,请自己参照下面的格式,添加其它年份的假期表
  73.   
  74.   Date1 = CDate(Format$(Date1, "YYYY-MM-DD"))
  75.   Select Case Year(Date1)
  76.     Case 2012
  77.       Select Case Date1
  78.         Case #1/1/2012# To #1/3/2012#:    IsLegalHoliday = True: Exit Function  '元旦
  79.         Case #1/22/2012# To #1/28/2012#:  IsLegalHoliday = True: Exit Function  '春节
  80.         Case #4/2/2012# To #4/4/2012#:    IsLegalHoliday = True: Exit Function  '清明节
  81.         Case #4/29/2012# To #5/1/2012#:   IsLegalHoliday = True: Exit Function  '劳动节
  82.         Case #6/22/2012# To #6/24/2012#:  IsLegalHoliday = True: Exit Function  '端午节
  83.         Case #9/30/2012# To #10/7/2012#:  IsLegalHoliday = True: Exit Function  '国庆、中秋节
  84.         Case #1/21/2012#, #1/29/2012#, #3/31/2012#, #1/4/2012#, #4/28/2012#, #9/29/2012#  '调体上班
  85.           IsLegalHoliday = False: Exit Function
  86.       End Select
  87.     Case 2013
  88.       Select Case Date1
  89.         Case #1/1/2013# To #1/3/2013#:    IsLegalHoliday = True: Exit Function  '元旦
  90.         Case #2/9/2013# To #2/15/2013#:   IsLegalHoliday = True: Exit Function  '春节
  91.         Case #4/4/2013# To #4/6/2013#:    IsLegalHoliday = True: Exit Function  '清明节
  92.         Case #4/29/2013# To #5/1/2013#:   IsLegalHoliday = True: Exit Function  '劳动节
  93.         Case #6/10/2013# To #6/12/2013#:  IsLegalHoliday = True: Exit Function  '端午节
  94.         Case #9/19/2013# To #9/21/2013#:  IsLegalHoliday = True: Exit Function  '中秋节
  95.         Case #10/1/2013# To #10/7/2013#:  IsLegalHoliday = True: Exit Function  '国庆节
  96.         Case #1/5/2013# To #1/6/2013#, #2/16/2013# To #2/17/2013#, #4/7/2013#, #4/27/2013# To #4/28/2013# _
  97.            , #6/8/2013# To #6/9/2013#, #9/22/2013#, #9/29/2013#, #10/12/2013#  '调体上班
  98.           IsLegalHoliday = False: Exit Function
  99.       End Select
  100.     'Case 2014      '2014年放假表
  101.     Case Else
  102.   End Select
  103.   IsLegalHoliday = Weekday(Date1, vbMonday) > 5
  104. End Function
复制代码
附上测试文档: 时间函数.rar (12.79 KB, 下载次数: 19)

TA的精华主题

TA的得分主题

发表于 2013-4-12 22:59 | 显示全部楼层
joforn 发表于 2013-4-12 22:33
原来的主函数被我在上传前删除了十来行代码,结果运行结果会出错。这次上传了可以处理2013、2012年节假日的 ...

还是有问题!
1.正常的日期误判为“错误的日期输入”,显然代码存在逻辑错误
2.下图工作表第10行的结果多计算了20分钟,显然代码也存在逻辑错误
未命名.jpg
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-11-19 20:27 , Processed in 0.040687 second(s), 7 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表