除了成员 David Zemens 给出的出色回答之外,以下是用“纯”Excel VBA 编写的通用函数,它不包含任何 Excel 工作表函数,也不包含字典对象(回复:CreateObject("Scripting.Dictionary")。
Option Explicit
'get N random integer numbers in the range from LB to UB, NO repetition
'general formula: Int ((UpperBound - LowerBound + 1) * Rnd + LowerBound)
Function RandomNumbers(LB As Integer, UB As Integer, N As Integer) As Variant
Dim I As Integer
Dim arrRandom() As Integer
Dim colRandom As New Collection
Dim colItem As Variant
Dim tempInt As Integer
Dim tempExists As Boolean
'check that ArraySize is less that the range of the integers
If (UB - LB + 1 >= N) Then
While colRandom.Count < N
Randomize
' get random number in interval
tempInt = Int((UB - LB + 1) * Rnd + LB)
'check if number exists in collection
tempExists = False
For Each colItem In colRandom
If (tempInt = colItem) Then
tempExists = True
Exit For
End If
Next colItem
' add to collection if not exists
If Not tempExists Then
colRandom.Add tempInt
End If
Wend
'convert collection to array
ReDim arrRandom(N - 1)
For I = 0 To N - 1
arrRandom(I) = colRandom(I + 1)
Next I
'return array of random numbers
RandomNumbers = arrRandom
Else
RandomNumbers = Nothing
End If
End Function
'get 5 Random numbers in the ranger 1...10 and populate Worksheet
Sub GetRandomArray()
Dim arr() As Integer
'get array of 5 Random numbers in the ranger 1...10
arr = RandomNumbers(1, 10, 5)
'populate Worksheet Range with 5 random numbers from array
If (IsArray(arr)) Then
Range("A1:A5").Value = Application.Transpose(arr)
End If
End Sub
功能
Function RandomNumbers(LB As Integer, UB As Integer, N As Integer)
返回 LB...UB 范围内的 N 个随机数组成的数组,不重复。
示例Sub GetRandomArray() 演示了如何在 1...10 范围内获取 5 个随机数并填充工作表范围:它可以针对任何特定要求进行定制(例如 PO 要求中的 1...40 中的 8 个)。
附录 A(由 David Ziemens 提供)
或者,您可以完全不依赖 Collection 对象来做类似的事情。构建一个分隔字符串,然后使用Split 函数将字符串转换为一个数组,并将其返回给调用过程。
这实际上将数字返回为String,但这对于这个特定的用例来说无关紧要,如果确实如此,则可以轻松修改。
Option Explicit
Sub foo()
Dim arr As Variant
arr = RandomNumbersNoCollection(1, 40, 6)
End Sub
'get N random integer numbers in the range from LB to UB, NO repetition
'general formula: Int ((UpperBound - LowerBound + 1) * Rnd + LowerBound)
Function RandomNumbersNoCollection(LB As Integer, UB As Integer, N As Integer)
Dim I As Integer
Dim numbers As String ' delimited string
Dim tempInt As Integer
Const dlmt As String = "|"
'check that ArraySize is less that the range of the integers
If (UB - LB + 1 >= N) Then
' get random number in interval
Do
Randomize
tempInt = Int((UB - LB + 1) * Rnd + LB)
If Len(numbers) = 0 Then
numbers = tempInt & dlmt
ElseIf InStr(1, numbers, tempInt & dlmt) = 0 Then
numbers = numbers & tempInt & dlmt
End If
Loop Until UBound(Split(numbers, dlmt)) = 6
numbers = Left(numbers, Len(numbers) - 1)
End If
RandomNumbersNoCollection = Split(numbers, dlmt)
End Function