Excel найти следующую доступную дату из списка слотов дня / времени - PullRequest
0 голосов
/ 30 января 2019

В 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 голосов
/ 30 января 2019

Это может пойти вниз, как ведущий воздушный шарик, и это может быть слишком сложно, но если вы ищете решение 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 ... поэтому они отображаются так, как они были раньше, но они должны быть просто числами.

Как только вы это сделаете, добавьте следующую формулу в первую ячейку вашей" следующей доступной даты"matrix ...

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

... заменяя" $ D2 "первой датой начала и" E $ 1 "заголовком" Available Date 1 "er field.

Теперь заполните и поперек и скрестите пальцы, это должно работать для вас.

ОБЯЗАТЕЛЬНО ФОРМАТИРУЙТЕ ДАТЫ КАК ДАТЫ И ВРЕМЕНИ КАК РАЗ!

Надеюсь, все ясно.

Дайте мне знать, как у вас дела.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...