在随机生成的非重复日期中排除周末

时间:2018-03-27 03:29:08

标签: excel vba excel-vba

我使用两个公式来生成指定范围内的随机非重复值。

1st是=IFERROR(RANDBETWEEN($A$1,$A$2),"")

第二名是=IFERROR(LARGE(ROW(INDIRECT(CONCATENATE("$",$A$1,":$",$A$2)))*NOT(COUNTIF($B$1:B1,ROW(INDIRECT(CONCATENATE("$",$A$1,":$",$A$2))))),RANDBETWEEN(1,($A$2+2-$A$1)-ROW(B1))),"")

这两个公式生成一组50个值(取决于我向下拖动第二个公式的位置),彼此是唯一的。

这也适用于日期。但是,我想要包含一个排除周末的选项。我已经创建了一个VBA用户表单,其中用户可以输入开始和结束日期。但是我也希望包含一个复选框,以确定是否从该范围中排除周末。如果可行,我希望扩展这一点,以便用户可以选择排除他/她希望排除的日期。

我在谷歌上搜索时发现了以下公式:

=DATE(2014, 1, 1)+(LARGE(IF(WEEKDAY((DATE(2014, 1, 1)+ROW($1:$365)-1)*((COUNTIF($A$1:A1, DATE(2014, 1, 1)+ROW($1:$365)-1))=0), 2)<6, ROW($1:$365)-1, ""), RANDBETWEEN(1, SUM(--(WEEKDAY((DATE(2014, 1, 1)+ROW($1:$365)-1)*((COUNTIF($A$1:A1, DATE(2014, 1, 1)+ROW($1:$365)-1))=0), 2)<6)))))

然而,经过一些调整和尝试后,我无法让它为我工作。此外,它在2014年1月1日的开始日期加上365天开始(这是相对简单的纠正)。我唯一的问题是试图从50个随机生成的非重复日期中排除周末。将此结合到用户表单是我已经可以做到的事情。

有了这个,请问你的帮助。谢谢!

3 个答案:

答案 0 :(得分:2)

您正在寻找WorksheetFunction.WorkDay(Arg1, Arg2, Arg3)或者您可以在VBA中将其用作WorksheetFunction.WorkDay

  

WORKDAY方法返回表示a的数字   日期是指之前或之后的指定工作日数   日期(开始日期)。工作日不包括周末和任何日期   确定为假期。使用boolean排除周末或假日   当您计算发票到期日,预计交货时间或   工作天数。

     

Arg1必需变体 Start_date - 表示开头的日期   日期。

     

Arg2必需变体天数 - 非周末数和   start_date之前或之后的非节假日。天数的正值   产生未来的日期;负值会产生过去的日期。

     

Arg3可选变体假期 - 一个或多个日期的可选列表   从工作日历中排除,例如州和联邦   假期和浮动假期。该列表可以是一系列的   包含日期或序列的数组常量的单元格   表示日期的数字

直接来自MS Doc $expr

如何使用此方法的一个很好的示例 MS Excel:如何使用WORKDAY函数(WS) https://msdn.microsoft.com/en-us/vba/excel-vba/articles/worksheetfunction-workday-method-excel

另外,我建议您阅读文章使用工作日 https://www.techonthenet.com/excel/formulas/workday.php

答案 1 :(得分:1)

这样可以合理地生成2014年周一至周五的随机日期。

=WORKDAY.INTL(41640, RANDBETWEEN(0, NETWORKDAYS.INTL(41640, 42004, 1)), 1)

请注意,日期并非完全唯一且不重复。

我使用了2014年1月1日的序列日期41,640和2014年12月31日的42,004,但这些可以用任何形式的真实日期替换;例如日期(2014年,1,1)。 WORKDAY.INTL和NETWORKDAYS.INTL都支持可选的假日列表参数。

enter image description here

对于真正独特且不重复的日期,我会使用vba字典。

答案 2 :(得分:0)

另一种方法是管理列表而不是试图操纵随机数。

Function MyRandomNumbers() As Collection ' could be anything
    Dim tSourceList As New Collection ' could be a list of anything
    Dim iterator As Long
    ' populate the list - for this example it will only be simple numbers
    For iterator = 1 To 500
        tSourceList.Add iterator ' New list item is the iterator. Could be anything
    Next iterator

    Dim tResultList As New Collection ' the same thing as put in the source list
    Dim index As Long
    For iterator = 1 To 50 ' How ever many numbers you want to pull out of the list
        index = CInt(tSourceList.Count * Rnd()) '<randomly generated number between 0 and length of tSourceList>
        tResultList.Add tSourceList(index)
        tSourceList.Remove (index)
    Next iterator
    Set MyRandomNumbers = tResultList
End Function

Sub testMRN()
Dim v As Collection
Dim r As Variant
    Set v = MyRandomNumbers
    Debug.Print v.Count,
    For Each r In v
        Debug.Print r & " ";
    Next r

End Sub

您可以使用更好的播种随机数修改index =部分。