【问题标题】:Excel Macro VBA: Add minutes and hours together where total can exceed 24 hoursExcel 宏 VBA:将分钟和小时相加,总计可能超过 24 小时
【发布时间】:2017-11-29 00:12:29
【问题描述】:

希望这是一个简单的答案。

我真的没有选择我使用什么语言,这就是我在 Excel 中使用 VBA 执行此操作的原因。

我基本上是在计算一个月内的总停机时间。当然,我需要将少量分钟加在一起才能得出总时间超过 24 小时。

这是场景:

本月服务器 A 停机 3 小时 52 分钟。
本月服务器 B 宕机了 15 小时 25 分钟。

服务器 B 在关键期间有 7 小时 23 分钟的停机时间,因此将其乘以 3 等于非关键停机时间。

服务器 A 有:3 小时 52 分钟 x1
服务器 B 有:8 小时 2 分钟 x1
服务器 B 有:7 小时 21 分钟 x3

所有停机时间和恢复时间都以 Excel 可识别的时间格式手动列出在工作表中,例如:

活动 1 : 19/11/2017 5:00 : 19/11/2017 14:12
活动 2 : 13/11/2017 6:00 : 13/11/2017 6:40
活动 3 : 13/11/2017 7:57 : 13/11/2017 9:01
活动 4 : 17/11/2017 6:15 : 18/11/2017 8:10

周末不计算

只计算早上 6 点到下午 6 点之间的分钟数

在特定时间段内优先级增加的分钟数:

06:00-07:00, 07:00-09:00, 09:00-10:00, 10:00-14:00

将高优先级分钟数相乘以使高峰时间使用量与较低标准时间使用量相等

我正在努力寻找一种将时间相加来计算小时数的方法,excel 尝试给出相对于 01/01/1900 或某个“真实”日期的答案。

我走的是相反的路,我有真正的约会,我需要处理他们之间的时间。是否有以小时为单位的数据格式:分钟?

我认为这很明显,但我会明确说明以防万一,开始时间和结束时间不一定在同一天。它们可以是任何时间、任何关系,有时开始时间会在结束时间之后,这取决于如何报告故障。显然,在这种情况下,这算作 0 分钟。


我目前解决这个问题的方法是:

  1. 增加启动时间,直到变为有效充电时间
  2. 计算直到发生变化(例如结束时间或更高优先级的时间段,或开始时间 = 结束时间)的分钟数
  3. 将计算出的分钟数加到总数中
  4. 将开始时间增加计算的分钟数
  5. 从新的“开始时间”重新开始循环并循环,直到开始时间和结束时间之间没有剩余分钟数

    startof:
    
    'move to start of next chargeable day, if not on a chargeable day
    'eg weekends, public holidays, easy function to write
    Do While testForChargeable() = False
    
        opnDate = DateAdd("d", 1, opnDate)
        opnTime = "06:00"
    
    Loop
    
    'check if open time is past the end of chargeable time, 18:00
    If (opnTime >= endofdayTime) Then
        'move to start of next chargeable day
        opnDate = DateAdd("d", 1, opnDate)
        opnTime = "06:00"
    End If
    
    'check if open time is after close time and fault is excluded
    If (opnDate >= bisDate) And (opnTime >= bisTime) Then
        GoTo last
    End If
    
    'check if close time is on same day as start time
    If DateDiff("d", opnDate, bisDate) = 0 Then
        'if it is, add minutes between opntime and bistime
        chargeTime = chargeTime + calculateChargeTime(opnTime, bisTime)
        'calculation ends, loop naturally terminates
    Else
        'if not, add remaining mintes of day to chargeable time
        chargeTime = chargeTime + calculateChargeTime(opnTime, endofdayTime)
        'move to start of next day
        opnDate = DateAdd("d", 1, opnDate)
        opnTime = "06:00"
        GoTo startof
    End If
    
    last:
    

干杯

【问题讨论】:

  • 这里没有问题
  • 简单(或愚蠢?)的答案显然是“有时”(或者那是“有时”?)
  • 我在添加标签时按回车,在我写之前不小心提交了问题
  • NumberFormat 更改为 [hh]:mm,这会强制 Sum 以小时为最大单位。
  • Patrick 听起来不错,但我看不到如何在 VBA 中执行此操作,就像使用单元格属性一样

标签: vba date time


【解决方案1】:

编辑: 现在我们在同一页面上,我认为对你来说是一个可行的解决方案,我将替换我之前的答案 [re: Excel 日期如何与值相关(即 1 天 = 1)] 与这个。之前的答案(我的电脑在尝试发布时出现问题)可在编辑历史记录中查看。


因此,您需要一种方法来计算两个日期时间之间的分钟持续时间,并根据可能需要持续调整的标准包括或排除子时间范围,并且您希望在 VBA 函数中使用此功能以自动停机数据分析。

试试这个:

Option Explicit

Function MinsBetween(startDateTime As Date, stopDateTime As Date, count_StartTime As Date, count_StopTime As Date) As Long

    Dim startTime As Date, stopTime As Date 

    'ignore dates, use only the times
    startTime = startDateTime - Int(startDateTime)
    stopTime = stopDateTime - Int(stopDateTime)

    If startTime >= count_StopTime Or stopTime <= count_StartTime Then
        'entire period falls outside of times to count
        MinsBetween = 0
        Exit Function
    End If

    'make 'adj' times start/end at counted times if necessary
    startDateTime = IIf(startTime < count_StartTime, count_StartTime, startTime)
    stopDateTime = IIf(stopTime > count_StopTime, count_StopTime, stopTime)

    'calculate & return minutes between (never return negative number)
    MinsBetween = Abs(DateDiff("n", startDateTime, stopDateTime))

End Function

此函数仅计算 startDateTimestopDateTime 之间的分钟数,这些分钟数也在 count_StartTimecount_StopTime 之间。

预期: - count_StartTime & count_StopTime 是 Excel 时间(或 0 到 1 之间的数字) - startDateTime & stopDateTime 是 Excel 时间 DateTime。

返回一个长整数。可以在 VBA 中引用或作为工作表函数引用。

使用示例:

中断“事件”发生在 2017/11/19 的 05:00 至 07:03,但仅应计算上午 6 点至下午 6 点之间的时间:

Debug.Print MinsBetween("2017/11/19 05:00", "2017/11/19 07:03", "06:00", "18:00") 

中断“事件”发生在 2017/11/19 的 05:00 到 14:12。 [高峰期] 下午 1 点到 2 点之间发生的持续时间优先级较高,应计为“双倍时间”:

Debug.Print (2 * MinsBetween("2017/11/19 05:00", "2017/11/19 14:12", "13:00", "15:00") )

由于完全忽略了周末,因此可以通过如下简单检查排除这些报告:

Function isWeekend(wDateTime As Date) As Boolean
    isWeekend = Weekday(DateValue(wDateTime)) = vbSaturday Or Weekday(DateValue(wDateTime)) = vbSunday
End Function

...如果提供的日期(或日期时间)在周末,则返回 TRUE,否则返回 FALSE。


您可以结合使用这些函数来围绕您的自定义标准构建子函数或工作表函数,并根据需要进行调整。

例如:

Function DownTimeMinutes(startDateTime As Date, stopDateTime As Date) As Long
'you could process your custom criteria for each start/stop period here

    Dim dtMinutes As Long

    'for example:

    'IGNORE DOWNTIME ON WEEKENDS
    If isWeekend(startDateTime) Then
        'ignore weekeends
        DownTimeMinutes = 0
        Exit Function
    End If

    'COUNT MINUTES BETWEEN 6AM-6PM with "x1" multiplier
    dtMinutes = MinsBetween(startDateTime, stopDateTime, "06:00", "18:00")

    'DON'T COUNT LUNCH BREAK (or something like that)
    '(subtract these minutes from total)
    dtMinutes = dtMinutes - MinsBetween(startDateTime, stopDateTime, "12:00", "12:30")

    'COUNT MINUTES BETWEEN 14:00-15:00 as "x3"
    '(already counted as "x1" so add "2x these minutes"
    dtMinutes = dtMinutes + (2 * MinsBetween(startDateTime, stopDateTime, "14:00", "15:00"))

    'return adjusted minutes for this downtime event
    DownTimeMinutes = dtMinutes

End Function

旁注:当我认为您的问题的一部分是转换不同的 M/D/Y 、 MM/DD/YY 时遇到问题时,这是我得到的长示例的短篇故事, M-DD-YYYY 等,无论用户的区域日期设置如何,Excel 都会识别的 DateTimes 的手动输入。

据我了解,您现在不需要它,但我想我还是把它添加到我的答案中:

=DATE(MID(RIGHT(LEFT(A1,FIND(" ",A1)-1),LEN(LEFT(A1,FIND(" ",A1)-1))-FIND("/",LEFT(A1,FIND(" ",A1)))),FIND("/",RIGHT(LEFT(A1,FIND(" ",A1)-1),LEN(LEFT(A1,FIND(" ",A1)-1))-FIND("/",LEFT(A1,FIND(" ",A1)))))+1,4),LEFT(RIGHT(LEFT(A1,FIND(" ",A1)-1),LEN(LEFT(A1,FIND(" ",A1)-1))-FIND("/",LEFT(A1,FIND(" ",A1)))),FIND("/",RIGHT(LEFT(A1,FIND(" ",A1)-1),LEN(LEFT(A1,FIND(" ",A1)-1))-FIND("/",LEFT(A1,FIND(" ",A1)))))-1),FIND("/",RIGHT(LEFT(A1,FIND(" ",A1)-1),LEN(LEFT(A1,FIND(" ",A1)-1))-FIND("/",LEFT(A1,FIND(" ",A1))))))+TIMEVALUE(RIGHT(A1,LEN(A1)-FIND(" ",A1)))

一般来说,我不容忍使用巨大的公式(我更关心的是把它变成一个关于可读性的函数),还有其他方法来处理共享工作簿中的区域差异引起的日期问题(包括Windows API) 但在大多数情况下,我发现文本操作也可以完成这项工作。

【讨论】:

  • 谢谢,我明白了,但我不能使用那个方法。就我而言,我必须找出停机时间和恢复时间之间的分钟差,如果停机时间恰好发生在一天中的特定时间段内,则添加 downtime_minutes x 3。
  • 我假设,例如,event 4 : 17/11/2017 6:15 : 18/11/2017 8:10 第一个值是停机时间,第二个值是恢复时间,所以这个停机时间将近 26 小时,对吗?
  • 是的,这只是一个例子,我在一张表中有数百行这样的行,因此需要编写一个宏来避免手工计算,这是我们目前唯一的方法。还有其他细节,这是真实事物的简化版本,其中有很多因素会影响最终结果,但问题中描述了要领
  • 更重要的是,26 小时跨越了所有不同的时间段,在这些时间段内不计算(隔夜)分钟数,或者由于更高的优先级时间,它们被计算为两倍或三倍。
  • 绝对,我正在整理一个彻底的答案,以换取您的耐心(然后前往超级用户寻求有关我该死的笔记本电脑的帮助,因此部分帖子!)数据量是' t 与格式一样重要。所有日期/时间的格式都与您发布的相同吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-01
  • 1970-01-01
  • 2021-02-03
  • 1970-01-01
  • 1970-01-01
  • 2021-03-29
相关资源
最近更新 更多