Excel从日期/时段列表中查找下一个可用日期

时间:2019-01-30 01:52:56

标签: excel excel-formula

在Excel中,说我有一个每周可以使用的可用日期和时间列表(2个单独的列):

DAY         TIME
Monday      5:00 PM
Tuesday     4:00 PM
Wednesday   11:00 AM
Thursday    4:00 PM
Friday      11:00 AM
Friday      12:00 PM

此列表是可变的,可以随时更改,因此解决方案必须是一个可以根据可用列表更改重新计算的公式。

然后我有一列可能的“开始”日期/时间:

START TIME
3/12/19 3:00 PM (Tuesday)
3/12/19 4:00 PM (Tuesday)
3/15/19 2:00 PM (Friday)

有没有一种方法可以在开始日期旁边的3个单独的列中计算出接下来的3个可用天/时间,以作为紧随初始开始日期之后的实际日期?如果可用日期与开始日期是一周的同一天,则需要检查时间是否早于可用时间。如果是的话,那么可能会在同一天的晚些时候……如果开始时间在可用时间之后,则必须在一周后。

计算的时间可以与上一行相同,因此公式无需考虑任何形式的重复预订。在2个单独的行中使用相同的日期/时间将导致下3个可用的日期/时间相同。

因此在上面的示例中,结果为:

START TIME          Next Available Date 1    Next Available Date 2    Next Available Date 3
3/12/19 3:00 PM     3/12/19 4:00 PM          3/13/19 11:00 AM         3/14/19 4:00 PM          
3/12/19 4:01 PM     3/13/19 11:00 AM         3/14/19 4:00 PM          3/15/19 11:00 AM 
3/15/19 2:00 PM     3/18/19 5:00 PM          3/19/19 4:00 PM          3/20/19 11:00 AM 

我一直在尝试使用数组公式,但是不能使其在所有情况下都能正常工作。该解决方案必须基于公式,并且不使用VBA或UDF。

1 个答案:

答案 0 :(得分:0)

这可能会像铅气球一样掉下来,并且可能设计过度,但是如果您正在寻找VBA解决方案,这应该对您有用。

将以下代码添加到VBA编辑器中的新模块中...

Public Function CalculateNextAvailableDay(ByVal rngAvailableDays As Range, ByVal dtDate As Date, ByVal lngAvailableDayIndex As Long) As Date
    Dim strThisDay As String, tmThisTime As Variant, i As Long, intAvailableDay As Integer, lngRow As Long, dtNextDate As Date, arrNextAvailableDates() As Variant
    Dim lngArrayIndex As Long, intNextDateDay As Integer, lngMaxSecondsDiff As Long, lngSecondsDiff As Long, intDateOffset As Integer
    Dim lngIndexToRemove As Long, x As Long, bBeenThrough As Boolean

    Application.Volatile

    ' First, build up the range of next available DATES, not DAYS.
    For lngRow = 1 To rngAvailableDays.Rows.Count
        strThisDay = UCase(Trim(rngAvailableDays.Cells(lngRow, 1)))

        tmThisTime = TimeValue(rngAvailableDays.Cells(lngRow, 2).Text)

        Select Case strThisDay
            Case "SUNDAY"
                intAvailableDay = 1
            Case "MONDAY"
                intAvailableDay = 2
            Case "TUESDAY"
                intAvailableDay = 3
            Case "WEDNESDAY"
                intAvailableDay = 4
            Case "THURSDAY"
                intAvailableDay = 5
            Case "FRIDAY"
                intAvailableDay = 6
            Case "SATURDAY"
                intAvailableDay = 7
        End Select

        dtNextDate = DateValue(Split(CStr(dtDate))(0)) + tmThisTime
        intDateOffset = 0

        Do While 1 = 1
            dtNextDate = DateAdd("d", intDateOffset, dtNextDate)
            intNextDateDay = Weekday(dtNextDate)

            intDateOffset = 1

            If intNextDateDay = intAvailableDay And dtNextDate >= dtDate Then
                ' This date counts, add it to the list of available next dates.
                ReDim Preserve arrNextAvailableDates(lngArrayIndex)
                arrNextAvailableDates(lngArrayIndex) = dtNextDate

                lngArrayIndex = lngArrayIndex + 1

                Exit Do
            End If
        Loop
    Next

    ' Now find the next available date.
    For x = 1 To lngAvailableDayIndex
        lngMaxSecondsDiff = 0
        bBeenThrough = False

        ' We have all of the next available dates.
        For i = 0 To UBound(arrNextAvailableDates)
            If arrNextAvailableDates(i) <> "" Then
                lngSecondsDiff = Abs(DateDiff("s", arrNextAvailableDates(i), dtDate))

                If lngSecondsDiff < lngMaxSecondsDiff Or Not bBeenThrough Then
                    lngMaxSecondsDiff = lngSecondsDiff
                    lngIndexToRemove = i
                    bBeenThrough = True
                End If
            End If
        Next

        dtNextDate = arrNextAvailableDates(lngIndexToRemove)
        arrNextAvailableDates(lngIndexToRemove) = ""
    Next

    CalculateNextAvailableDay = dtNextDate
End Function

...并在第一个表格的顶部(不包括标题)定义一个名为 rngAvailableDays 的命名范围。

使用您的矩阵,将“可用日期1”的标题更改为仅数字,例如...

  • “可用日期1”,更改为“ 1”
  • “可用日期2”,更改为“ 2”
  • “可用日期3”,更改为“ 3”

然后您可以自定义格式,将其设置为...“可用日期” 0 ...,以便它们像以前一样显示,但是它们只能是数字。

完成此操作后,将以下公式添加到“下一个可用日期”矩阵的第一个单元格中...

=CalculateNextAvailableDay(rngAvailableDays,$D2,E$1)

...将“ $ D2”替换为第一个开始日期,并将“ E $ 1”替换为“可用日期1”标题字段。

现在填满手指并交叉,它应该对您有用。

请务必将日期和时间格式化为日期!

我希望一切都清楚。

让我知道你的生活。