Excel VBA范围RandBetween函数返回错误

时间:2013-07-27 07:27:18

标签: excel excel-vba excel-2010 vba

我正在尝试在excel范围之间随机获得一个非重复的结果。

当我输入Msgbox Range("C2")时,我得到一个单元格值。

但是,当我使用MsgBox Range("F" & WorksheetFunction.RandBetween(1, UBound(ElementHeader)))时,它会告诉我'type-mismatch'

知道为什么吗?我如何将它实际存储在VBA中的String数组中?

我的代码如下所示:

Sub Testy()
    Dim ElementHeader
    ElementHeader = Range("F1:F" & Range("F" & Rows.Count).End(xlUp).Row)
    MsgBox Range("F" & WorksheetFunction.RandBetween(1, UBound(ElementHeader)))
End Sub

这只是代码的一部分,但我希望将它存储到一个数组中,以便我可以检查每个代码以查看是否有任何重复。

Sub GenerateDescription()
    Dim Element
    Dim AddOn
    Dim MainRange
    ' Declare Sentences
    ' Addon Range is in Column F
    AddOn = Range("G1:G" & Range("G" & Rows.Count).End(xlUp).Row)
    ' Main Range is in Column D
    Set MainRange = Range("E1:E" & Range("E" & Rows.Count).End(xlUp).Row)
        For Each Element In MainRange
            Element.Offset(, 4).Value = Element & " " & Range("G" & WorksheetFunction.RandBetween(1, UBound(AddOn))) & " " & Range("G" & WorksheetFunction.RandBetween(1, UBound(AddOn))) & " " & Range("G" & WorksheetFunction.RandBetween(1, UBound(AddOn))) & " " & Range("G" & WorksheetFunction.RandBetween(1, UBound(AddOn))) & " " & Range("G" & WorksheetFunction.RandBetween(1, UBound(AddOn)))
        Next Element
End Sub

正如您所看到的,这个重复的G范围是我试图解决的部分。

我希望每个For Each方法只能出现一次G列句子。意思是,我希望每个元素包含G列中的5个唯一句子。

假设我有10个句子,对于每个循环,我想得到5个唯一的句子,例如:G1,G4,G2,G9,G10。应该从不重复相同的单元格,这意味着如果函数生成G1,G2,G5,G3,G1,我想用G列中的另一个随机单元格数替换重复的G1。 / p>

1 个答案:

答案 0 :(得分:1)

使用Chip Pearson函数获取唯一的随机数,并将代码调整为:

For Each Element In MainRange
    vRandom = UniqueRandomLongs(1, UBound(AddOn), 5)
    Element.Offset(, 4).Value = Element & " " & _
    Range("G" & vRandom(1)) & " " & _
    Range("G" & vRandom(2)) & " " & _
    Range("G" & vRandom(3)) & " " & _
    Range("G" & vRandom(4)) & " " & _
    Range("G" & vRandom(5))
Next Element

http://www.cpearson.com/excel/RandomNumbers.aspx

Public Function UniqueRandomLongs(Minimum As Long, Maximum As Long, _
            Number As Long, Optional ArrayBase As Long = 1, _
            Optional Dummy As Variant) As Variant
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' UniqueRandomLongs
' This returns an array containing elements whose values are between the Minimum and
' Maximum parameters. The number of elements in the result array is specified by the
' Number parameter. For example, you can request an array of 20 Longs between 500 and
' 1000 (inclusive).
' There will be no duplicate values in the result array.
'
' The ArrayBase parameter is used to specify the LBound of the ResultArray. If this
' is omitted, ResultArray is 1-based.
'
' The Dummy argument is to be used only when the function is called from a worksheet.
' Its purpose is to allow you to use the NOW() function as the Dummy parameter to force
' Excel to calculate this function any time a calculation is performed. E.g.,
'       =UniqueRandomLongs(100,199,10,NOW())
' If you don't want to recalulate this function on every calculation, omit the Dummy
' parameter. The Dummy argument serves no other purpose and is not used anywhere
' in the code.
'
' The function returns an array of Longs if successful or NULL if an error occurred
' (invalid input parameter).
'
' Note: The procedure creates its own array of size (Maximum-Minium+1), so very large
' differences between Minimum and Maximum may cause performace issues.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Dim SourceArr() As Long
Dim ResultArr() As Long
Dim SourceNdx As Long
Dim ResultNdx As Long
Dim TopNdx As Long
Dim Temp As Long

''''''''''''''''''''''''''''''''''''''
' Test the input parameters to ensure
' they are valid.
''''''''''''''''''''''''''''''''''''''
If Minimum > Maximum Then
    UniqueRandomLongs = Null
    Exit Function
End If
If Number > (Maximum - Minimum + 1) Then
    UniqueRandomLongs = Null
    Exit Function
End If
If Number <= 0 Then
    UniqueRandomLongs = Null
    Exit Function
End If

Randomize
''''''''''''''''''''''''''''''''''''''''''''''
' Redim the arrays.
' SourceArr will be sized with an LBound of
' Minimum and a UBound of Maximum, and will
' contain the integers between Minimum and
' Maximum (inclusive). ResultArray gets
' a LBound of ArrayBase and a UBound of
' (ArrayBase+Number-1)
''''''''''''''''''''''''''''''''''''''''''''''
ReDim SourceArr(Minimum To Maximum)
ReDim ResultArr(ArrayBase To (ArrayBase + Number - 1))
''''''''''''''''''''''''''''''''''''''''''''
' Load SourceArr with the integers between
' Minimum and Maximum (inclusive).
''''''''''''''''''''''''''''''''''''''''''''
For SourceNdx = Minimum To Maximum
    SourceArr(SourceNdx) = SourceNdx
Next SourceNdx

''''''''''''''''''''''''''''''''''''''''''''''
' TopNdx is the upper limit of the SourceArr
' from which the Longs will be selected. It
' is initialized to UBound(SourceArr), and
' decremented in each iteration of the loop.
' Selections from SourceArr are always in the
' region including and to the left of TopNdx.
' The region above (to the right of) TopNdx
' is where the used numbers are stored and
' no selection is made from that region of
' the array.
''''''''''''''''''''''''''''''''''''''''''''''
TopNdx = UBound(SourceArr)
For ResultNdx = LBound(ResultArr) To UBound(ResultArr)
    ''''''''''''''''''''''''''''''''''''''''''''''''''
    ' Set SourceNdx to a random number between 1 and
    ' TopNdx. ResultArr(ResultNdx) will get its value from
    ' SourceArr(SourceNdx). Only elements of SourceArr
    ' in the region of the array below (to the left of)
    ' TopNdx (inclusive) will be selected for inclusion
    ' in ResultArr. This ensures that the elements in
    ' ResultArr are not duplicated.
    ''''''''''''''''''''''''''''''''''''''''''''''''''
    SourceNdx = Int((TopNdx - Minimum + 1) * Rnd + Minimum)
    ResultArr(ResultNdx) = SourceArr(SourceNdx)
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    ' Now, swap elements SourceNdx and TopNdx of SourceArr,
    ' moving the value in SourceArr(SourceNdx) to the region
    ' of SourceArr that is above TopNdx.  Since only elements
    ' of SourceArr in the region below TopNdx (inclusive) are
    ' possible candidates for inclusion in ResultArr, used
    ' values are placed at TopNdx to ensure no duplicates.
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    Temp = SourceArr(SourceNdx)
    SourceArr(SourceNdx) = SourceArr(TopNdx)
    SourceArr(TopNdx) = Temp
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    ' Decrment TopNdx. This moves the effective UBound of SourceArr
    ' downwards (to the left), thus removing used numbers from the
    ' possibility of inclusion in ResultArr. This ensures we have
    ' no duplicates in the ResultArr.
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    TopNdx = TopNdx - 1
Next ResultNdx

''''''''''''''''''''''''''''''
' Return the result array.
''''''''''''''''''''''''''''''
UniqueRandomLongs = ResultArr

End Function