Как я могу создать список дат на основе ввода пользователя? - PullRequest
0 голосов
/ 15 марта 2019

Скажите, что у меня есть электронная таблица, которая позволяет пользователям вставлять некоторые метаданные, например:

Date range start: mm/dd/yyyy
Date range end: mm/dd/yyyy
Mondays: (y/n)
Tuesdays: (y/n)
Wednesdays: (y/n)
Thursdays: (y/n)
Fridays: (y/n)

Исходя из этого, я хочу создать список дат в формате mm/dd/yyyy, которыйначинается 4/1/2019, заканчивается 4/30/2019 и включает только даты того дня, который был отмечен y.

Таким образом, если пользователь введет start date = 04/01/2019, end date = 04/30/2019, y только по понедельникам и средам, список будет выглядеть так:

04/01/2019
04/03/2019
04/08/2019
04/10/2019
04/15/2019
04/17/2019
04/22/2019
04/24/2019
04/29/2019

Не удалось найти ExcelФункция для начала.Я не знаю VBA, но думаю, что это было бы возможно сделать с этим.

Если бы я хотел написать это на Python с помощью надстройки, подобной Pyxll, потребовался бы каждый, у кого есть копия файла Excel, для установки Pyxll?

Ответы [ 2 ]

1 голос
/ 15 марта 2019

@ simplycoding: VBA не имеет функции или функции, готовых сделать то, что вы ищете, прямо из коробки. Тем не менее, вы можете создавать свои собственные на основе того, что VBA предлагает, что очень много.

Это мой сценарий запуска:

enter image description here

За 20 минут я написал, протестировал и прокомментировал следующий SUB. Поверьте мне, когда я говорю, что я не первый рядовый VBA-кодер.

Sub DateList()
'(C) Antonio Rodulfo, 2019
Dim dEnd, dStart, dCounter As Date
Dim iaDays(1 To 5) As Integer
Dim iCounter, iRow As Integer
'   Indent your sentences properly
    '   Reading parameters
    dStart = Cells(2, 1).Value
    dEnd = Cells(2, 2)
    For iCounter = 1 To 5
        If Cells(2, 2 + iCounter) = "y" Then
            iaDays(iCounter) = 1
        Else
            iaDays(iCounter) = 0
        End If
    Next iCounter
    '   Here's where the list of dates will start
    iRow = 4
    '   I process the dates: Excel stores dates in its own
    '       coding, which we can use to run a for..next loop
    For dCounter = dStart To dEnd
        '   Weekday(datecode,type) returns the day of week
        '   type 2 means the week starts with  monday being day 1
        iCounter = Weekday(dCounter, 2)
        '   The sub only sets dates for working days
        '   monday to friday
        If iCounter <= 5 Then
            '   date must be set if found "y" in the matching day
            If iaDays(iCounter) = 1 Then
                '   I like setting the proper numberformat so
                '   that no surprises are found when reading it
                Cells(iRow, 1).NumberFormat = "dd/mmm/yyyy"
                Cells(iRow, 1) = dCounter
                '   Increasing iRow sets the focus on next row
                iRow = iRow + 1
            End If
        End If
    '   Adding the index name to the next sentence helps
    '   tracking the structures
    Next dCounter
End Sub

Я всегда рекомендую использовать Option Explicit при кодировании. Поначалу это может показаться раздражающим, но это очень поможет при тестировании и отладке кода.

Удачи!

0 голосов
/ 16 марта 2019

Меня попросили попросить вообще не использовать VBA, поэтому я поиграл с некоторыми функциями Excel, и вот что я хотел бы, чтобы вы попробовали.

Я использовал ваши метаданные в следующих ячейках:

metadata

ВАРИАНТ 1 - легко

Введите следующую функцию Array в ячейку D1 (Ctrl + Shift + Enter) и перетащите ее полностью вправо (например, до ячейки AW1):

=IF(AND(ISNUMBER(MATCH(WEEKDAY($B$1+COLUMN()-4,2),--($B$3:$B$7="y")*(ROW($B$3:$B$7)-2),0)),($B$1+COLUMN()-4)<=$B$2),$B$1+COLUMN()-4,"")

Отображаются все даты, которые находятся между датами начала и окончания и для требуемых дней недели. Однако этот параметр не устраняет пробелы, поэтому между ними будет много пустых столбцов.

ВАРИАНТ 2 - завершено

Введите следующую функцию Array в ячейку D2 (Ctrl + Shift + Enter) и перетащите ее вправо:

=IFERROR(SUMPRODUCT(SMALL(($B$1+ROW($B$1:$B$30)-1)*(IF(ISNUMBER(MATCH(WEEKDAY($B$1+ROW($B$1:$B$30)-1,2),(--($B$3:$B$7="y")*(ROW($B$3:$B$7)-2)),0)),1,0)),30-COUNT(MATCH(WEEKDAY($B$1+ROW($B$1:$B$30)-1,2),(--($B$3:$B$7="y")*(ROW($B$3:$B$7)-2)),0))+COLUMN()-3)),"")

Как видите, эта опция отображает все "правильные" даты рядом друг с другом, без пробелов.

Надеюсь, вы найдете это полезным - мне было очень весело поиграть со вторым вариантом, и я уверен, что его еще можно улучшить.

Береги себя, Юстина

...