【问题标题】:Excel VBA Generating a random number in order and according to how manyExcel VBA按顺序生成随机数并根据多少
【发布时间】:2012-12-19 17:10:48
【问题描述】:

生日,

我有一个棘手的问题,即根据 VBA 代码或 VBA 中的公式需要多少来按排序顺序获取随机数。这种需求是在 1 到 10 之间随机生成的。

它启动时看起来像这样。

这是我想到的效果,它根据示例中失败的数量显示排序的数字。

这是我做的 VBA 的一次尝试,其中单元格 J7 包含我需要的随机数,但数字没有完全排序。我愿意在这里接受建议/反馈。非常感谢。

Public Const BeCoolMachineCounter As String = "J7"
Public Const BeCoolMachineRange As String = "Q03:Q12"
'Generate the random data according to how many needed.
Call CreateNumbers(Range(BeCoolMachineRange), Range(BeCoolMachineCounter).Value)
Private Sub CreateNumbers(Which As Range, HowMany As Integer)
' Declaration of variables
    Dim c As Range
    Dim iCheck As Long

    iCheck = 1

' Generate random failures based on the number of required for each supplier
    For Each c In Which
        If iCheck <= HowMany Then
            c.Value = Random1to2192
            iCheck = iCheck + 1
        End If
    Next c
End Sub

【问题讨论】:

  • 如果电子表格布局是静态的,我会尝试SMALL 工作表函数。
  • 您好 Juri,我认为这里不需要 SMALL 工作表函数,因为这意味着一个数字。感谢您的建议。
  • =SMALL($B$3:$B$12),ROW()-2 从 C3 复制到单元格 C3:C12 您的示例对所有输出数据进行排序。

标签: excel vba random formula sorted


【解决方案1】:

您可以在目标范围内使用数组公式,并使用返回数组的 UDF。

它会准确地为您提供所显示的结果。

所以,UDF:

Public Function GetRandomFailures(count As Long) As Variant
    Dim result As Variant, numbers As Variant
    ReDim result(100)
    ReDim numbers(count - 1)

    For i = 0 To count - 1
        numbers(i) = Application.WorksheetFunction.RandBetween(1, 10000)
    Next i

    Call QuickSort(numbers, LBound(numbers), UBound(numbers))

    For i = 0 To 99
        If i < count Then
            result(i) = numbers(i)
        Else
            result(i) = ""
        End If
    Next i

    GetRandomFailures = Application.WorksheetFunction.Transpose(result)
End Function

Public Sub QuickSort(vArray As Variant, inLow As Long, inHi As Long)

  Dim pivot   As Variant
  Dim tmpSwap As Variant
  Dim tmpLow  As Long
  Dim tmpHi   As Long

  tmpLow = inLow
  tmpHi = inHi

  pivot = vArray((inLow + inHi) \ 2)

  While (tmpLow <= tmpHi)

     While (vArray(tmpLow) < pivot And tmpLow < inHi)
        tmpLow = tmpLow + 1
     Wend

     While (pivot < vArray(tmpHi) And tmpHi > inLow)
        tmpHi = tmpHi - 1
     Wend

     If (tmpLow <= tmpHi) Then
        tmpSwap = vArray(tmpLow)
        vArray(tmpLow) = vArray(tmpHi)
        vArray(tmpHi) = tmpSwap
        tmpLow = tmpLow + 1
        tmpHi = tmpHi - 1
     End If

  Wend

  If (inLow < tmpHi) Then QuickSort vArray, inLow, tmpHi
  If (tmpLow < inHi) Then QuickSort vArray, tmpLow, inHi

End Sub

和一个示例公式:

{=GetRandomFailures(A1)}

(Excel添加的大括号)

您当然可以简单地从宏中调用此 UDF,但恕我直言,使用数组公式可以改善用户体验,因为一切都是透明的,并且每次更改计数时都会刷新列表。

注意:快速排序的实现来自这里:VBA array sort function?

【讨论】:

  • 感谢您的建议。我会检查代码并通知您。
  • 非常感谢,它可以按我的意愿工作。一旦我记得如何做 CSE 公式,这就解决了我的问题。
【解决方案2】:

我不确定我是否理解您所说的,但基于之前和之后我假设您已经在列中拥有 10 个数字,并且您希望获得大小为 HowMany 的随机样本 从他们那里,然后确保所取的数字按顺序排序。

Public Sub RandomSample(Data10 As Range, HowMany As Integer)

    ' Insert random numbers next to the data
    Data10.Cells(1, 2).FormulaR1C1 = "=RAND()"
    Data10.Cells(1, 2).AutoFill Destination:=Range(Data10.Cells(1, 2), Data10.Cells(10, 2))

    ' Sort the data by the random numbers
    Range(Data10.Cells(1, 1), Data10.Cells(10, 2)).Sort key1:=Data10.Cells(1, 2), header:=xlNo
    ' Remove the random numbers
    Range(Data10.Cells(1, 2), Data10.Cells(10, 2)).ClearContents

    ' Remove numbers surplus to HowMany
    If HowMany < 10 Then
        Range(Data10.Cells(HowMany + 1, 1), Data10.Cells(10, 1)).ClearContents
    End If

    ' Resort the remaining numbers
    Range(Data10.Cells(1, 1), Data10.Cells(HowMany, 1)).Sort key1:=Data10.Cells(1, 1), header:=xlNo

End Sub

你可以用 RandomSample Range("B3:B12"),6

来调用它

【讨论】:

  • 嗨 Morbo,是的,这是正确的,10 个数字并按排序顺序排列。我在提供的静态图片中使用了 10 个数字作为小样本,用于说明目的。我会看看这段代码做了什么,看看这是否符合我的想法。谢谢。
  • 我尝试了这段代码,我认为排序不起作用,因为它会在填充后清除数据。
  • 它在 Excel 2003 中对我有用,正如我在 cmets 中所描述的那样。如果你想要 3 个号码,它将删除剩余的 7 个号码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-20
  • 1970-01-01
  • 1970-01-01
  • 2017-09-27
  • 1970-01-01
  • 2020-01-19
相关资源
最近更新 更多