Public Function RandLong(Optional iMin As Long = 1, _</SPAN>
Optional iMax As Long = -2147483647, _</SPAN>
Optional bVolatile As Boolean = False) As Variant</SPAN>
' UDF only!</SPAN>
' Returns numbers between iMin and iMax to the calling range</SPAN>
' UDF wrapper for aiRandLong</SPAN>
' shg 2008</SPAN>
Dim nRow As Long ' rows in calling range</SPAN>
Dim nCol As Long ' columns in calling range</SPAN>
Dim iRow As Long ' row index</SPAN>
Dim iCol As Long ' col index</SPAN>
Dim aiTmp() As Long ' 1D temp array</SPAN>
Dim aiOut() As Long ' output array</SPAN>
If bVolatile Then Application.Volatile True</SPAN>
With Application.Caller</SPAN>
nRow = .Rows.Count</SPAN>
nCol = .Columns.Count</SPAN>
End With</SPAN>
ReDim aiOut(1 To nRow, 1 To nCol)</SPAN>
If iMin = 1 And iMax = -2147483647 Then iMax = nRow * nCol</SPAN>
aiTmp = aiRandLong(iMin, iMax, nRow * nCol)</SPAN>
For iRow = 1 To nRow</SPAN>
For iCol = 1 To nCol</SPAN>
aiOut(iRow, iCol) = aiTmp((iCol - 1) * nRow + iRow)</SPAN>
Next iCol</SPAN>
Next iRow</SPAN>
RandLong = aiOut</SPAN>
End Function</SPAN>
Public Function aiRandLong(iMin As Long, _</SPAN>
iMax As Long, _</SPAN>
Optional ByVal n As Long = -1, _</SPAN>
Optional bVolatile As Boolean = False) As Long()</SPAN>
' shg 2008
' UDF or VBA</SPAN>
' Fisher-Yates shuffle</SPAN>
' Returns a 1-based array of n unique Longs between iMin and iMax inclusive</SPAN>
Dim aiSrc() As Long ' array of numbers iMin to iMax</SPAN>
Dim iSrc As Long ' index to aiSrc</SPAN>
Dim iTop As Long ' decreasing upper bound for next selection</SPAN>
Dim aiOut() As Long ' output array</SPAN>
Dim iOut As Long ' index to aiOut</SPAN>
If bVolatile Then Application.Volatile True</SPAN>
If n < 0 Then n = iMax - iMin + 1</SPAN>
If iMin > iMax Or n > (iMax - iMin + 1) Or n < 1 Then Exit Function</SPAN>
ReDim aiSrc(iMin To iMax)</SPAN>
ReDim aiOut(1 To n)</SPAN>
' init iSrc</SPAN>
For iSrc = iMin To iMax</SPAN>
aiSrc(iSrc) = iSrc</SPAN>
Next iSrc</SPAN>
iTop = iMax</SPAN>
For iOut = 1 To n</SPAN>
' Pick a number in aiSrc between 1 and iTop, copy to output,</SPAN>
' replace with the number at iTop, decrement iTop</SPAN>
iSrc = Int((iTop - iMin + 1) * Rnd) + iMin</SPAN>
aiOut(iOut) = aiSrc(iSrc)</SPAN>
aiSrc(iSrc) = aiSrc(iTop)</SPAN>
iTop = iTop - 1</SPAN>
Next iOut</SPAN>
aiRandLong = aiOut</SPAN>
End Function</SPAN>