ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

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

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

[复制链接]

TA的精华主题

TA的得分主题

发表于 2013-4-10 19:53 | 显示全部楼层 |阅读模式
计算 例如:发起时间(4月8号 11点01分)到 结束时间(4月9号 15点23分) 所花费的时间? 最终时间是  9小时22分
(只计算以下时间范围内的时间:----工作日(周一到周五)---工作时间段(9点~12点,14点~18点))
用函数 怎么写啊  
还需要补充的一点是
发起时间(4月8号 12点)到 结束时间(4月9号 20点) 时间只计算4月8号(14点~18点)--4小时;4月9号 工作时间段(9点~12点,14点~18点)---7小时
时间为13小时,
18点到20点 不在工作时间内 不计算

有时间的高人 可查看附件

时间函数.7z

1.9 KB, 下载次数: 19

TA的精华主题

TA的得分主题

发表于 2013-4-10 21:50 | 显示全部楼层
这个复杂的计算式,呵呵

TA的精华主题

TA的得分主题

发表于 2013-4-11 02:09 | 显示全部楼层
本帖最后由 yygpdkkk 于 2013-4-13 11:12 编辑

为此题花了7、8个小时,晕死。
另:代码未经严格测试(短时间内考虑不到那么多细节数据)
代码更新:经再次分析、理顺思路,修改了部分代码,进而发现修正时长的代码不再必要,故代码逻辑应该严谨了些
代码再次更新:再次删减了些代码,同时增加了处理2003年法定节假日及调休日的函数代码

最新说明:本楼判断是否工作日的代码在速度上大大逊色于joforn的写法(提示:若跨越日期很长,就看出显著区别了。尽管实际应用中不可能出现日期跨越4万多天,但代码毕竟表现出了速度上的区别),故于27楼处对本楼代码作了相应修改,也改为Select结构,直接列示节假日。此外,直接列示的节假日采用日期文字还有个好处,即增加了语言上的可移植性。




  1. Function MyTime(theStartDate As Variant, theEndDate As Variant) As Variant
  2.     Dim theDate1 As Date, theDate2 As Date, theTime1 As Date, theTime2 As Date, i&
  3.     MyTime = 0 '确保一次赋值
  4.     If Not IsDate(theStartDate) Or Not IsDate(theEndDate) Then '若非法日期,则
  5.         MyTime = CVErr(xlErrNA) '返回错误值
  6.         Exit Function
  7.     End If
  8.     If theEndDate - theStartDate < 0 Then
  9.         MyTime = CVErr(xlErrNA) '若发起时间大于结束时间,则返回错误值
  10.         Exit Function
  11.     End If
  12.     theDate1 = DateSerial(Year(theStartDate), Month(theStartDate), Day(theStartDate))
  13.     theTime1 = theStartDate - theDate1
  14.     theDate2 = DateSerial(Year(theEndDate), Month(theEndDate), Day(theEndDate))
  15.     theTime2 = theEndDate - theDate2
  16.     Select Case theTime1 '确定发起时间(仅指时间部分,不含日期)
  17.         Case Is < TimeValue("9:00:01") '若发起时间早于上午9点,则确定为9点起始
  18.             theTime1 = TimeValue("9:00:00")
  19.         Case Is < TimeValue("12:00:01") '若发起时间早于正午,则theTime1就是发起时间,不用调整
  20.         Case Is < TimeValue("14:00:01") '若发起时间早于下午14点,则确定为12点起始(此处很重要)
  21.             theTime1 = TimeValue("12:00:00")
  22.         Case Is < TimeValue("18:00:01") '若发起时间早于下午18点,则theTime1就是发起时间,不用调整
  23.         Case Else '否则确定为18:00:00
  24.             theTime1 = TimeValue("18:00:00")
  25.     End Select
  26.     Select Case theTime2 '确定结束时间(仅指时间部分,不含日期)
  27.         Case Is < TimeValue("9:00:01") '若结束时间早于上午9点,则确定为上午9:00:00
  28.             theTime2 = TimeValue("9:00:00")
  29.         Case Is < TimeValue("12:00:01") '若结束时间早于正午,则theTime2就是结束时间,不用调整
  30.         Case Is < TimeValue("14:00:01") '若结束时间早于下午14点零1分,则确定为中午12点结束(此处很重要)
  31.             theTime2 = TimeValue("12:00:00") '(承上述)此处故意把结束时间往早前推(不设为14:00:00),
  32.             '从而与theTime1的12:00:00这一时间点重叠,巧妙地使后续代码的时间相减融为一体,从而不用再专门写代码进行修正
  33.         Case Is < TimeValue("18:00:01") '若结束时间早于下午18点,则theTime2就是结束时间,不用调整
  34.         Case Else '否则确定为18:00:00
  35.             theTime2 = TimeValue("18:00:00")
  36.     End Select
  37.     If theDate1 = theDate2 Then '若发起日期与结束日期为同一天,则
  38.         If MyWorkDay(theDate1) Then '若为工作日,则
  39.             If theTime1 < TimeValue("12:00:01") Then
  40.                 If theTime2 < TimeValue("14:00:01") Then
  41.                     MyTime = theTime2 - theTime1 '两个时间均处于上午,则直接相减
  42.                 Else
  43.                     MyTime = TimeValue("12:00:00") - theTime1 '先计算出上午时长
  44.                     MyTime = MyTime + theTime2 - TimeValue("14:00:00") '再加上下午时长
  45.                 End If
  46.             Else '否则,两个时间均处于下午
  47.                  MyTime = theTime2 - theTime1 '仅下午时长
  48.             End If
  49.         End If
  50.     Else '否则,发起日期与结束日期不为同一天
  51.         If MyWorkDay(theDate1) Then '先计算发起日的时长
  52.             If theTime1 < TimeValue("12:00:01") Then
  53.                 MyTime = TimeValue("12:00:00") - theTime1 '先计算出上午时长
  54.                 MyTime = MyTime + TimeValue("4:00:00") '再加上下午时长
  55.             Else '否则,计算发起日的下午时长
  56.                 MyTime = TimeValue("18:00:00") - theTime1 '仅存在下午时长
  57.             End If
  58.         End If
  59.         If MyWorkDay(theDate2) Then '再计算结束日的时长
  60.             If theTime2 < TimeValue("12:00:01") Then '计算结束日的上午时长
  61.                 MyTime = MyTime + theTime2 - TimeValue("9:00:00") '仅存在上午时长
  62.             Else '否则计算结束日的时长
  63.                 MyTime = MyTime + TimeValue("3:00:00") + theTime2 - TimeValue("14:00:00") '上午3小时和下午时长
  64.             End If
  65.         End If
  66.     End If
  67.     For i = theDate1 + 1 To theDate2 - 1 '介于发起日和结束日之间的其他天数必定为7小时
  68.         If MyWorkDay(CDate(i)) Then
  69.             MyTime = MyTime + TimeValue("7:00:00")
  70.         End If
  71.     Next i
  72. End Function
  73. Private Function MyWorkDay(theDate As Date) As Boolean
  74.     '本函数当前内置数据仅适用于公元2013年
  75.     Dim arr As Variant '指按《全国年节及纪念日放假办法》规定安排的全年公休假放假安排
  76.     Dim brr As Variant '同上,用于调休日,即周六、周日因调休而成工作日
  77.     Dim theWorkDay As Boolean '是否调休日标记
  78.     Dim i&
  79.     arr = Array("2013-1-1", "2013-1-2", "2013-1-3", "2013-2-9", "2013-2-10", "2013-2-11", "2013-2-12", "2013-2-13", "2013-2-14", "2013-2-15", "2013-4-4", "2013-4-5", "2013-4-6", "2013-4-29", "2013-4-30", "2013-5-1", "2013-6-10", "2013-6-11", "2013-6-12", "2013-9-19", "2013-9-20", "2013-9-21", "2013-10-1", "2013-10-2", "2013-10-3", "2013-10-4", "2013-10-5", "2013-10-6", "2013-10-7") '法定节假日在此指定
  80.     brr = Array("2013-1-5", "2013-1-6", "2013-2-16", "2013-2-17", "2013-4-7", "2013-4-27", "2013-4-28", "2013-6-8", "2013-6-9", "2013-9-22", "2013-9-29", "2013-10-12") '调休日在此指定(指周六、周日因调休而成工作日)
  81.     If Weekday(theDate, vbMonday) < 6 Then '若为周一至周五,则进一步检查是否为节假日
  82.         theWorkDay = True '赋初值,即先假定为是正常的工作日
  83.         For i = LBound(arr) To UBound(arr)
  84.             If theDate = CDate(arr(i)) Then '若是节假日,则
  85.                 theWorkDay = False
  86.                 Exit For
  87.             End If
  88.         Next i
  89.     Else '否则,为周六或周日,则进一步检查是否调休日
  90.         For i = LBound(brr) To UBound(brr)
  91.             If theDate = CDate(brr(i)) Then '若是调休日,则
  92.                 theWorkDay = True
  93.                 Exit For
  94.             End If
  95.         Next i
  96.     End If
  97.     If theWorkDay Then MyWorkDay = True Else MyWorkDay = False
  98. End Function


复制代码

上个图(罗列的数据应该还算详细了吧。另注:黄色底纹系特意提醒注意该行所举数据的特殊性,无它):
未命名.jpg

TA的精华主题

TA的得分主题

 楼主| 发表于 2013-4-11 09:07 | 显示全部楼层
yygpdkkk 发表于 2013-4-11 02:09
为此题花了7、8个小时,晕死。
另:代码未经严格测试(短时间内考虑不到那么多细节数据)

太谢谢啦!高人了,看到你的回复真的是惊喜啊, 我正在测试中

TA的精华主题

TA的得分主题

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

  15楼代码重发。。。。。

TA的精华主题

TA的得分主题

发表于 2013-4-11 10:11 | 显示全部楼层
  1. Sub lqxs()
  2. Dim ks, js, kssj, jssj, rq, sw
  3. ks = [a1].Value
  4. js = [a2].Value
  5. kssj = Split(ks)
  6. jssj = Split(js)
  7. rq = DateDiff("d", ks, js)
  8. If rq > 0 Then
  9.     If CDate(kssj(1)) < #6:00:00 PM# Then
  10.         If CDate(kssj(1)) < #12:00:00 PM# Then
  11.             If CDate(kssj(1)) > #9:00:00 AM# Then
  12.                 sw = DateDiff("h", CDate(kssj(1)), #12:00:00 PM#) + 4
  13.             Else
  14.                 sw = 7
  15.             End If
  16.         ElseIf CDate(kssj(1)) > #2:00:00 PM# Then
  17.             sw = DateDiff("h", CDate(kssj(1)), #6:00:00 PM#)
  18.         Else
  19.             sw = 4
  20.         End If
  21.     End If
  22.     If CDate(jssj(1)) <= #12:00:00 PM# Then
  23.         If CDate(jssj(1)) > #9:00:00 AM# Then
  24.             sw = sw + DateDiff("h", #9:00:00 AM#, CDate(jssj(1)))
  25.         End If
  26.     Else
  27.         If CDate(jssj(1)) <= #6:00:00 PM# Then
  28.             If CDate(jssj(1)) > #2:00:00 PM# Then
  29.                 sw = sw + DateDiff("h", #2:00:00 PM#, CDate(jssj(1))) + 3
  30.             End If
  31.         Else
  32.             sw = sw + 7
  33.         End If
  34.     End If
  35.     sw = sw + 7 * (rq - 1)
  36. Else
  37.         If CDate(kssj(1)) < #11:59:00 AM# Then
  38.             If CDate(kssj(1)) > #9:00:00 AM# Then
  39.                 sw = DateDiff("h", CDate(kssj(1)), #12:00:00 PM#)
  40.                 If CDate(jssj(1)) <= #6:00:00 PM# Then
  41.                     If CDate(jssj(1)) > #2:00:00 PM# Then
  42.                         sw = sw + DateDiff("h", #2:00:00 PM#, CDate(jssj(1)))
  43.                     End If
  44.                 Else
  45.                     sw = sw + 4
  46.                 End If
  47.             End If
  48.         ElseIf CDate(kssj(1)) > #2:00:00 PM# Then
  49.             If CDate(kssj(1)) <= #6:00:00 PM# Then
  50.                 If CDate(jssj(1)) <= #6:00:00 PM# Then
  51.                     sw = sw + DateDiff("h", CDate(kssj(1)), CDate(jssj(1)))
  52.                 Else
  53.                     sw = DateDiff("h", CDate(kssj(1)), #6:00:00 PM#)
  54.                 End If
  55.             Else
  56.                 sw = 0
  57.             End If
  58.         Else
  59.                 If CDate(jssj(1)) <= #6:00:00 PM# Then
  60.                     sw = DateDiff("h", #2:00:00 PM#, CDate(jssj(1)))
  61.                 Else
  62.                     sw = 4
  63.                 End If
  64.         End If
  65. End If
  66. MsgBox sw
  67. End Sub
复制代码

TA的精华主题

TA的得分主题

发表于 2013-4-11 10:13 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
请见附件。

时间计算0410.rar

6.59 KB, 下载次数: 44

TA的精华主题

TA的得分主题

 楼主| 发表于 2013-4-11 22:21 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
蓝桥玄霜 发表于 2013-4-11 10:13
请见附件。

非常谢谢版主的关注,需求中 还需要判断周六日或者如在代码加上中国的法定节假日 ,这个还需要加什么的代码呢,因为这是需要批量处理,按钮如何切换成更快捷的方式,期待 版主的指点。

TA的精华主题

TA的得分主题

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

高手 能不能发给文档 给我看看学习 学习
因为 我才开始学VBA 你的代码复制到宏里 无法启动
  期待你的回复

TA的精华主题

TA的得分主题

 楼主| 发表于 2013-4-11 22:24 | 显示全部楼层
张三李四 发表于 2013-4-11 09:20

谢谢 高手的支持  因为才开始学习VBA  但代码复制进去 有问题
  你看 可不可以 发个文档呢! 再次谢谢
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

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

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

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

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

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

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