Есть ли способ заставить worksheetfunction.randbetween работать в течение определенного временного диапазона?

#excel #vba

#excel #vba

Вопрос:

Я очень новичок в программировании и просто хочу поблагодарить всех на этом сайте, кто уже так мне помог.

Я пытаюсь создать генератор случайного времени, который будет генерировать случайное время в пределах диапазона, указанного пользователем. В настоящее время я использую WorksheetFunction.Команда Randbetween, которая эффективно генерирует случайное время, однако оно не находится в пределах указанного диапазона. Этот код является частью более крупной пользовательской формы, которая выполняет аналогичные функции. Остальная часть кода работает нормально (ish).

Мой вопрос: что мне нужно добавить в мою строку кода, чтобы заставить ее эффективно генерировать время в указанном диапазоне? Мне также нужно убедиться, что он работает в 24-часовом формате «ЧЧ: ММ: СС» или «ЧЧ: ММ».

Я пробовал использовать Round и WorksheetFunction.Randbetween

 Private Sub Generate_Data_Button_Click()

Dim emptyRow As Long

Randomize 

'Make Data Active
Sheet1.Activate

'Determine emptyRow
emptyRow = WorksheetFunction.CountA(Range("A:A")) 1

'Transfer information to template
Cells(emptyRow, 4).Value = WorksheetFunction.Randbetween (start_time_textbox.value, end_time_textbox.value)   Rnd()

'Format cell on template
Cells(emptyRow, 4).NumberFormat = "hh:mm:ss"

End Sub 

 

Комментарии:

1. RANDBETWEEN возвращает целое число. 24 часа эквивалентны 1, поэтому по определению между вашим временем начала и временем окончания нет случайного целого числа — оба находятся между 0 и 1. Вы можете умножить каждое из них на 86400, чтобы получить соответствующее время в секундах, использовать секунды RANDBETWEEN , а затем разделить результат на 86400, чтобы получить время.

2. Потрясающе! Большое спасибо за ответ. Это имеет смысл. Я все еще зацикливаюсь на том, как он генерирует случайное время, но не внутри предоставленного мной диапазона. Например, если я введу 08:00 в качестве времени начала и 10:00 в качестве времени окончания, он будет выводить все с 02:30 до 23:59.

Ответ №1:

Метод Randomize / Rnd

После Randomize Rnd этого генерирует псевдослучайное десятичное число от нуля до единицы при каждом его вызове. Если ваши времена являются значениями полного времени (например, 23:59:45), преобразуйте строки, возвращаемые полями ввода, используя преобразование строки TimeValue в double, и используйте некоторую математику, чтобы принудительно ввести значения Rnd внутри времени начала и остановки.

 Private Sub Generate_Data_Button_Click()

    Dim emptyRow As Long, tstart As Double, tend As Double

    'convert string times from input to true time as double
    tstart = TimeValue(start_time_textbox.Value)
    tend = TimeValue(end_time_textbox.Value)

    Randomize

    'Make Data Active
    With Worksheets("Data")

        'Determine emptyRow in COLUMN D
        emptyRow = .Cells(.Rows.Count, "D").End(xlUp).Row   1

        'Transfer information to template
        .Cells(emptyRow, "D").Value = (tend - tstart) * Rnd()   tstart

        'Format cell on template
        .Cells(emptyRow, "D").NumberFormat = "hh:mm:ss"

    End With

End Sub
 

Метод случайного переключения

Чтобы использовать функцию Randbetween рабочего листа, вам нужно преобразовать время начала и окончания в длинные целые числа, представляющие количество секунд, прошедших с полуночи, а затем рандомизировать между ними. Возьмите результат и преобразуйте его обратно в значение времени, уменьшив его на количество секунд в день.

 Private Sub Generate_Data_Button_Click2()

    Dim emptyRow As Long, tstart As Long, tend As Long, siad As Long

    siad = 86400 'seconds in a day

    'convert string times from input to seconds in a day as Long Integer
    tstart = TimeValue(start_time_textbox.Value)  * siad
    tend = TimeValue(end_time_textbox.Value)  * siad


    'Make Data Active
    With Worksheets("Data")

        'Determine emptyRow in COLUMN D
        emptyRow = .Cells(.Rows.Count, "D").End(xlUp).Row   1

        'Transfer information to template
        .Cells(emptyRow, "D").Value = Application.RandBetween(tstart, tend) / siad

        'Format cell on template
        .Cells(emptyRow, "D").NumberFormat = "hh:mm:ss"

    End With


End Sub
 

Комментарии:

1. Еще раз спасибо всем, кто помог мне решить эту проблему. Я занимаюсь этим меньше недели, так что это определенно было огромной помощью! Ваше здоровье!

Ответ №2:

Вы можете сделать это как UDF. Идея состоит в том, чтобы сгенерировать случайную минуту для смещения от Time1.

Сначала преобразуйте часы и минуты обоих периодов в минуты как единицу измерения.
Затем, основываясь на разнице в минутах, сгенерируйте случайные минуты, используя RandBetween , вычтите базовое время, затем добавьте эти случайные минуты к базовому времени (в минутах).

 Function RandomTimeBetween(FromTime As Range, ToTime As Range) As Date
    Dim Time1 As Date, Time2 As Date, Minutes As Integer
    Time1 = CDate(FromTime.Value)
    Time2 = CDate(ToTime.Value)
    Minutes = Hour(Time1) * 60   Minute(Time1) ' Base time in minutes
    ' Find the random offset time between them, deduct the base time
    Minutes = WorksheetFunction.RandBetween(Minutes, Hour(Time2) * 60   Minute(Time2)) - Minutes
    RandomTimeBetween = Time1   TimeSerial(0, Minutes, 0)
End Function
 

Если вы хотите выполнить рандомизацию с точностью до секунд, вам необходимо изменить значение ниже, поскольку переполнение может произойти в TimeSerial:

 Function RandomTimeBetween(FromTime As Range, ToTime As Range) As Date
    Dim Time1 As Date, Time2 As Date, Seconds As Long
    Time1 = CDate(FromTime.Value)
    Time2 = CDate(ToTime.Value)
    Seconds = Hour(Time1) * 3600   Minute(Time1) * 60   Second(Time1) ' Base time in seconds
    ' Find the random offset time between them, deduct the base time
    Seconds = WorksheetFunction.RandBetween(Seconds, Hour(Time2) * 3600   Minute(Time2) * 60   Second(Time2)) - Seconds
    RandomTimeBetween = Time1   TimeSerial(Seconds  3600, Seconds  60, Seconds Mod 60)
End Function