 Random Numbers In Excel
Random Numbers In Excel
This page describes how to work with random numbers in Excel and VBA.
 
Both Excel and VBA have limited support for random numbers. In Excel, you can use the 
RAND worksheet 
function to return a random number, D, where 0  <= D < 1. In the Analysis Tool Pack add-in, the is a function named 
RANDBETWEEN that will return an random integer between two specified numbers.
VBA has its own random function, 
Rnd, which returns a 
random number, D, where 0  <= D < 1. Building upon the 
RAND and 
Rnd functions,
we can devise some useful formulas and functions.

The Excel worksheet function RAND returns a random value D where 0 <= D < 1.
To return a decimal number (including a fractional part after the decimal point) between to numbers, use the following 
formula:
=RAND()*(High-Low)+Low
where Low is the smallest value in the desired range and High is
the largest value in the desired range. The formula will return a value between Low and High.  
To return an integer (whole number with no fractional portion), use
=TRUNC(RAND()*(High-Low)+Low)
The RAND function is a supported array function so 
RAND alone or either of the formulas above can be used in array formulas. 
It should be noted that RAND is a volatile function, which means it will be recalculated any time
any calculation is made. This means that the value of the function will change with each calculation. If you want the random number to change
only under certain circumstances, you can use a formula with a circular reference to create a random number that is recalculated only under
certain circumstances.
=IF(ReCalc, RAND()*(High-Low)+Low,C3)
In this formula 
C3 is the cell containing the formula, and 
RecCalc is a value that
indicates whether to recalculate the random number. 
ReCalc can be a function or a cell reference. In either 
case, ReCalc should be 
TRUE or a non-zero numeric value to cause the formula to be recalculated, or 
FALSE or zero to prevent the formula from being recalculated. In order to allow circular references, go to the 
Tools menu, choose 
Options, then the 
Calculation tab. There, check the 
Iteration box and set 
Maximum Iterations to 1. This formula will recalculate the random number result only when the value of 
ReCalc is
TRUE. 

VBA provides a function named Rnd that returns a value D where where 0 <= D < 1. To get a random
number (a real number with a decimal portion) within a specified range of values, use code like the following. Change the value of 
Low and High to lower and upper limits of the range of allowable values.
Dim Low As Double
Dim High As Double
Low = 11 
High = 20 
R = (High - Low) * Rnd() + Low
The code above will put in the variable R an integer between 11 and 20. To get an integer (whole number)
between two numbers, use:
Dim Low As Double
Dim High As Double
Low = 11 
High = 20 
R = Int((High - Low + 1) * Rnd() + Low)
This will put in R a whole number between Low and 
High.

The function described in this section, 
RandomLongs, will return an array of random Long Integers.
The function has the following declaration.
Public Function RandomLongs(Minimum As Long, Maximum As Long, _
	   
Number As Long, Optional ArrayBase As Long = 1, _
	   
Optional Dummy As Variant) As Variant
This function will return an array of random Long Integers 
between the values of Minimum and Maximum. The Number parameter 
indicates how many values to return. The ArrayBase parameter indicates the LBound of the resulting array. If 
ArrayBase is 0, the function returns an array with bounds (0,Number - 1). 
If ArrayBase is 1, the funcion returns an array with bounds (1, Number).
The Dummy parameter is used only when this funciton is called from a worksheet cell (discussed later). If the
function is called from within VBA, the Dummy parameter is ignored. If there is an error in parameter values, 
such as Minimum > Maximum or Number less than 1, the function
will return Null. To test whether the result from the function is a valid array, use 
the IsArrayAllocated function on the Is Array Allocated page.
It is possible that there will be duplicated values in the result array. If you need unique, non-duplicated values, use the 
UniqueRandomLongs function described later on this page.
The code for RandomLongs is shown below:
Public Function RandomLongs(Minimum As Long, Maximum As Long, _
    Number As Long, Optional ArrayBase As Long = 1, _
    Optional Dummy As Variant) As Variant
Dim SourceArr() As Long
Dim ResultArr() As Long
Dim SourceNdx As Long
Dim ResultNdx As Long
If Minimum > Maximum Then
    RandomLongs = Null
    Exit Function
End If
If Number > (Maximum - Minimum + 1) Then
    RandomLongs = Null
    Exit Function
End If
If Number <= 0 Then
    RandomLongs = Null
    Exit Function
End If
ReDim SourceArr(Minimum To Maximum)
For SourceNdx = Minimum To Maximum
    SourceArr(SourceNdx) = SourceNdx
Next SourceNdx
ReDim ResultArr(ArrayBase To (ArrayBase + Number - 1))
Randomize
For ResultNdx = LBound(ResultArr) To UBound(ResultArr)
    
    SourceNdx = Int((Maximum - Minimum + 1) * Rnd + Minimum)
    
    ResultArr(ResultNdx) = SourceArr(SourceNdx)
Next ResultNdx
RandomLongs = ResultArr
End Function
This section describes the UniqueRandomLongs function.
Public Function UniqueRandomLongs(Minimum As Long, Maximum As Long, _
	   
    Number As Long, Optional ArrayBase As Long = 1, _
	   
    Optional Dummy As Variant) As Variant
This function returns an array of unique, non-duplicated, Long Integers. The Minimum and
Maximum parameters indicate the lower and upper bounds of the values of the numbers. The numbers in the returned
array will always be between Minimum and Maximum (inclusive). The Number parameter
indicates the number of values to return. The ArrayBase parameter indicates the LBound of the result
array. ArrayBase should be either 0 or 1; the default is 1. If ArrayBase is 0, the
result array has bounds of (0, Number -1). If ArrayBase is 1, the result array
has bounds of (1, Number). The Dummy parameter is used only when this function 
is called from a worksheet cell (discussed later). If the function is called from within VBA, the Dummy parameter
is ignored. If there is an error in the parameters, such as Minimum > Maximum or 
Number less than 1, the function returns Null. To test whether the result from 
the function is a valid array, use the IsArrayAllocated function on the Is Array Allocated page.
The code for UniqueRandomLongs is shown below.
Public Function UniqueRandomLongs(Minimum As Long, Maximum As Long, _
            Number As Long, Optional ArrayBase As Long = 1, _
            Optional Dummy As Variant) As Variant
Dim SourceArr() As Long
Dim ResultArr() As Long
Dim SourceNdx As Long
Dim ResultNdx As Long
Dim TopNdx As Long
Dim Temp As Long
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 SourceArr(Minimum To Maximum)
ReDim ResultArr(ArrayBase To (ArrayBase + Number - 1))
For SourceNdx = Minimum To Maximum
    SourceArr(SourceNdx) = SourceNdx
Next SourceNdx
TopNdx = UBound(SourceArr)
For ResultNdx = LBound(ResultArr) To UBound(ResultArr)
    
    SourceNdx = Int((TopNdx - Minimum + 1) * Rnd + Minimum)
    ResultArr(ResultNdx) = SourceArr(SourceNdx)
    
    Temp = SourceArr(SourceNdx)
    SourceArr(SourceNdx) = SourceArr(TopNdx)
    SourceArr(TopNdx) = Temp
    
    TopNdx = TopNdx - 1
Next ResultNdx
UniqueRandomLongs = ResultArr
End Function

The following code demonstrates using the UniqueRandomLongs function in VBA.
Sub DemoUniqueRandomLongs()
Dim Res As Variant
Dim Min As Long
Dim Max As Long
Dim N As Long
Min = 101
Max = 200
N = 20
Res = UniqueRandomLongs(Minimum:=Min, Maximum:=Max, Number:=N)
If IsArrayAllocated(Res) = False Then
    Debug.Print "Error from UniqueRandomLongs."
Else
    For N = LBound(Res) To UBound(Res)
        Debug.Print Res(N)
    Next N
End If
End Sub
Function IsArrayAllocated(V As Variant) As Boolean
    On Error Resume Next
    IsArrayAllocated = Not (IsError(LBound(V)) And _
        IsArray(V)) And (LBound(V) <= UBound(V))
End Function

Both the RandomLongs and the UniqueRandomLongs functions may be used as
Array Formulas on a worksheet. Since these functions return arrays of values, you must array-enter
the functions into a range of cells. The size of this range must be the same as the value of the Number parameter.
For example, select range A1:K10 and type the formula
=UniqueRandomLongs(100,199,10)
and then press CTRL SHIFT ENTER rather than just ENTER. 
This will return an array of 10 numbers between 100 and 199 into the range A1:K10. By default, the functions return a horizontal array; that is, 
an array that is in one row spanning several columns. If you want the result in a vertical range, a single column spanning several rows, you
must transpose the result array:
=TRANSPOSE(UniqueRandomLongs(100,199,10))
Since these are array formulas, you must select the result range, type the formula, and then press 
CTRL SHIFT ENTER rather than just ENTER. If you do this properly, Excel 
will display the formula enclosed in curly braces { }. 
If you enter the functions as show above, Excel will not recalculate and update the functions and their return values when it does a calculation.
You have two options to control when Excel will recalculate the functions. The first method, which will cause the functions to recalculate
when any calculation is made, is to include NOW() as the final argument to the function. This is the 
Dummy parameter described in the VBA section of this page.
=UniqueRandomLongs(100,199,10,NOW())
Because NOW() is a volatile function, it will cause a recalculation of the formula whenever
Excel makes any calculation. The actual value of the NOW() is not used. The sole purpose of 
NOW() is to force a calculation.
You can also use the last parameter, the Dummy parameter, to specify a cell that controls 
calculation. For example:
=UniqueRandomLongs(100,199,10,C1)
The reference to cell C1 will cause the formula to be updated whenver the value of cell
C1 is changed.

You can also create a function that returns a number of elements in random order and without duplicates from a range of worksheet
cells. The function below does just this. You can call as an array formula with a formula like
=RandsFromRange(A1:A10,5)
where A1:A10 is the list of elements from which to pull the values and 5 is
the number of values to return. Enter the formula in a range with as many cells as you specify to return, and press
CTRL SHIFT ENTER rather than just ENTER. The VBA code is shown below:
Function RandsFromRange(InputRange As Range, GetNum As Long) As Variant
    Dim ResultArr() As Variant
    Dim SourceArr() As Variant
    Dim TopNdx As Long
    Dim ResultNdx As Long
    Dim SourceNdx As Long
    Dim Temp As Variant
    
    If InputRange.Columns.Count > 1 And InputRange.Rows.Count > 1 Then
        RandsFromRange = CVErr(xlErrRef)
        Exit Function
    End If
    
    If GetNum > InputRange.Cells.Count Then
        RandsFromRange = CVErr(xlErrValue)
        Exit Function
    End If
    
    ReDim ResultArr(1 To InputRange.Cells.Count)
    SourceArr = InputRange.Value
    Randomize
    TopNdx = UBound(ResultArr)
    
    
    For ResultNdx = LBound(ResultArr) To UBound(ResultArr)
        SourceNdx = Int(TopNdx * Rnd + 1)
        ResultArr(ResultNdx) = SourceArr(SourceNdx, 1)
        Temp = SourceArr(SourceNdx, 1)
        SourceArr(SourceNdx, 1) = SourceArr(TopNdx, 1)
        SourceArr(TopNdx, 1) = Temp
        TopNdx = TopNdx - 1
    Next ResultNdx
    
    
    If IsObject(Application.Caller) = True Then
        If TypeOf Application.Caller Is Excel.Range Then
            If Application.Caller.Columns.Count = 1 Then
                RandsFromRange = Application.Transpose(ResultArr)
            Else
                RandsFromRange = ResultArr
            End If
        Else
            
        End If
    Else
        RandsFromRange = ResultArr
    End If
        
End Function

You can download 
a bas code module here. You can also download a 
complete workbook file with the code and examples.
This page last updated: 11-August-2007