Please Note: This article is written for users of the following Microsoft Excel versions: 97, 2000, 2002, and 2003. If you are using a later version (Excel 2007 or later), this tip may not work for you. For a version of this tip written specifically for later versions of Excel, click here: Playing with a Full Deck.

Playing with a Full Deck

by Allen Wyatt
(last updated January 9, 2016)

11

How's that for a tip title? The title refers to the fact that you may have a need to populate a range of cells with a series of numbers in random order. For instance, you might want to populate 52 cells with the numbers 1 through 52, in random order. (This would be similar to drawing cards from a shuffled deck, thus the tip title.)

There obviously is no built-in Excel function to provide this capability, so you are left to work with macros. Fortunately, such a macro is not terribly difficult to create. The following macro will do the trick nicely:

Sub FillRand()
    Dim nums() As Integer
    Dim maxval As Integer
    Dim nrows As Integer, ncols As Integer
    Dim j As Integer, k As Integer
    Dim Ptr As Integer
    Randomize

    Set s = Selection
    maxval = s.Cells.Count
    nrows = s.Rows.Count
    ncols = s.Columns.Count

    ReDim nums(maxval, 2)

    'Fill the initial array
    For j = 1 To maxval
        nums(j, 1) = j
        nums(j, 2) = Int((Rnd * maxval) + 1)
    Next j

    'Sort the array based on the random numbers
    For j = 1 To maxval - 1
        Ptr = j
        For k = j + 1 To maxval
            If nums(Ptr, 2) > nums(k, 2) Then Ptr = k
        Next k
        If Ptr <> j Then
            k = nums(Ptr, 1)
            nums(Ptr, 1) = nums(j, 1)
            nums(j, 1) = k
            k = nums(Ptr, 2)
            nums(Ptr, 2) = nums(j, 2)
            nums(j, 2) = k
        End If
    Next j

    'Fill in the cells
    Ptr = 0
    For j = 1 To nrows
        For k = 1 To ncols
            Ptr = Ptr + 1
            s.Cells(j, k) = nums(Ptr, 1)
        Next k
    Next j
End Sub

This macro uses a two-dimensional array (nums) to figure out which numbers to use and the order in which they should be used. Near the beginning of the macro the array is filled with a static number (1 through the number of cells) and a random number between 1 and the number of cells. This second number is then used to sort the array. Once the array is stored, it is a simple matter to place the original numbers in the cells.

By the way, the reason a two-dimensional array is used is because the Rnd function that VBA uses to generate random numbers can return duplicate values. Thus, even through the second dimension of the array can have duplicates in it, when the array is finally sorted, the first dimension will not have duplicates.

To use the macro, start by selecting the cells you want to have filled with sequential values in a random order. When you run the macro, that range is filled. For instance, if you select ten cells and then run the macro, then those cells are filled with the numbers 1 through 10, in random order.

ExcelTips is your source for cost-effective Microsoft Excel training. This tip (2280) applies to Microsoft Excel 97, 2000, 2002, and 2003. You can find a version of this tip for the ribbon interface of Excel (Excel 2007 and later) here: Playing with a Full Deck.

Author Bio

Allen Wyatt

With more than 50 non-fiction books and numerous magazine articles to his credit, Allen Wyatt is an internationally recognized author. He  is president of Sharon Parq Associates, a computer and publishing services company. ...

MORE FROM ALLEN

The Case of the Disappearing Icons

Troubleshooting your custom icons on the Toolbar.

Discover More

Switching Editing Location

Excel allows you to edit the contents of a cell in two places—the cell itself or in the Formula bar. If you want to ...

Discover More

Create a Template that Stops Styles from Being Added to a Document

Limiting which styles a user can use or add to a document can be a tricky task. Fortunately Word has advanced to the point ...

Discover More

Solve Real Business Problems Master business modeling and analysis techniques with Excel and transform data into bottom-line results. This hands-on, scenario-focused guide shows you how to use the latest Excel tools to integrate data from multiple tables. Check out Microsoft Excel 2013 Data Analysis and Business Modeling today!

More ExcelTips (menu)

Generating Double-Digit Random Numbers

Normally you use the RAND and RANDBETWEEN functions to generate random numbers. What if you want to generate random numbers ...

Discover More

Random Numbers in a Range

Excel provides several different functions that you can use to generate random numbers. One of the most useful is the ...

Discover More

AutoFill with Random Numbers

When entering data into a worksheet, you may have a need to fill a range of cells with a group of random numbers. This task ...

Discover More
Subscribe

FREE SERVICE: Get tips like this every week in ExcelTips, a free productivity newsletter. Enter your address and click "Subscribe."

View most recent newsletter.

Comments

If you would like to add an image to your comment (not an avatar, but an image to help in making the point of your comment), include the characters [{fig}] in your comment text. You’ll be prompted to upload your image when you submit the comment. Maximum image size is 6Mpixels. Images larger than 600px wide or 1000px tall will be reduced. Up to three images may be included in a comment. All images are subject to review. Commenting privileges may be curtailed if inappropriate images are posted.

What is seven less than 7?

2017-12-13 09:03:11

Willy Vanhaelen

@Rick
Interesting link. It gives a better insight in the working of the macro.


2017-12-10 11:21:47

Rick Rothstein

@Willy,

Ah yes, I had forgotten that. The original routine that I developed the code I posted from was an array randomizer where the values were assumed to already be loaded in the array. Those values could be anything (random or ordered numbers, text or a mixture of both) and not simply numbers in numerical order as this article assumed. My original routine is quite old now... I originally published it in an old newsgroup (the predecessors to modern forums) devoted to VB (the compiled version, not the DotNET version) questions. I know the year because my code was incorporated into a web article back then which has a posting date on it of October 18, 1999...

http://vbnet.mvps.org/code/helpers/randomarray.htm

Randy, the man who maintained the website, used my RandomizeArray subroutine as part of a generalized presentation code of his own.


2017-12-10 07:52:09

Willy Vanhaelen

@Rick
Allen's macro as well as yours and my variant don't scramble the cells, they simply fill the selection with a random list overwriting it's contents. So you you don't have to fill the list with numbers first, you can as well start with an empty selection.
With Nums=Selection and a two dimensional array you get something new: shuffeling the selection maintaining their contents, whatever it is. This can be very usefull too.


2017-12-09 11:11:51

Rick Rothstein

@Willy,

Why would you want to randomly scramble empty cells? The idea behind my original code (which your modification retains) is to randomly rearrange the values within a selected columnar range of cells filled with values. For example, put the numbers 1 through 52 in cells A1:A52, select the range and run the code. if you think of the range as a deck of 52 cards, run the code and it shuffles them, run the code again and it shuffles them again. Of course, the code can randomly reorder any type of values within a columnar range of any size.


2017-12-09 10:37:38

Willy Vanhaelen

@Rick
Nums=Selection doesn't work. The selection being empty, It produces also an empty array, Or am I missing something?


2017-12-09 02:57:16

Rick Rothstein

@Willy,

Good idea to use a two-dimensional array instead of my one-dimensional array in order to remove the limitation built into the TRANSPOSE function when called from the Evaluate function. One note on that though, instead of loading up the Num array this way...

Nums = Evaluate("ROW(1:" & Selection.Count & ")")

you can simply do this (since Num is declared as a Variant) and end up with the identical array...

Num = Selection

Not sure if that will make the macro faster or not, but it does simplify the creation of the array.


2017-12-08 11:17:12

Willy Vanhaelen

Rick Rothstein's solution is a gem as usual. He claims his macro will be much faster than Allen's but didn't test it. I did and it is about 50 times faster !!! But while testing, I discovered his macro has a minor limitation: it has a limit of 65537 cells :-)
Further investigation revealed that TRANSPOSE is responsible for that. So I tried to produce the Num array only with ROW and it worked though the array is now two dimensional. I further took UBound(Nums) out of the loop because it doesn't change during the execution of the macro anyway. This makes the code in the loop a little bit simpler. Here is the result:

Sub FillRand()
Dim X As Long, RandIndex As Long, Nums As Variant, Cell As Range
Randomize
Nums = Evaluate("ROW(1:" & Selection.Count & ")")
X = UBound(Nums)
For Each Cell In Selection
RandIndex = Int(X * Rnd + 1)
Cell.Value = Nums(RandIndex, 1)
Nums(RandIndex, 1) = Nums(X, 1)
X = X - 1
Next Cell
End Sub

I did a test in Excel 2007 for a whole column and it took only 16 seconds to process the more than a million cells.


2016-01-10 12:16:18

Greg

A simpler method without using macros is to populate one column with the number 1 thru 52 then in an adjacent column use the RND function to put a random number against each row.

Sort both the columns using the 'random' column as the key and you've randomised the order.

As in the example above you could end up with the same random number in the sort key but that does not matter.


2016-01-09 10:43:09

Rick Rothstein

I should have mentioned in both of my previous messages that the code I posted works in XL2003 (the earliest version I own) to XL2010 (the lastest version I own)... I see no reason why the code would not work in XL2013 or later, but I have no idea if it will work in versions prior to XL2003.


2016-01-09 10:35:06

Rick Rothstein

I constructed the code in my previous message just before going to sleep... when I awoke just now, it occurred to me that I could reduce the code to a single loop... excluding the Dim statement, my modified macro (below) is now down to eight active lines of code.

Sub FillRand()
Dim X As Long, RandIndex As Long, Nums As Variant, Cell As Range
Randomize
Nums = Evaluate("TRANSPOSE(ROW(1:" & Selection.Count & "))")
For Each Cell In Selection
RandIndex = Int((UBound(Nums) - X) * Rnd + 1)
Cell.Value = Nums(RandIndex)
Nums(RandIndex) = Nums(UBound(Nums) - X)
X = X + 1
Next
End Sub


2016-01-09 06:11:10

Rick Rothstein

Here is another (more concise) way to write the macro...

Sub FillRand()
Dim X As Long, RandIndex As Long
Dim Temp As Variant, Nums As Variant
Dim Cell As Range
Randomize
Nums = Evaluate("TRANSPOSE(ROW(1:" & Selection.Count & "))")
For X = UBound(Nums) To 1 Step -1
RandIndex = Int(X * Rnd + 1)
Temp = Nums(RandIndex)
Nums(RandIndex) = Nums(X)
Nums(X) = Temp
Next
For Each Cell In Selection
X = X + 1
Cell.Value = Nums(X)
Next
End Sub

Also note that the selection does not have to be contiguous so long as the parts that make it up do not overlap in any way.


This Site

Got a version of Excel that uses the menu interface (Excel 97, Excel 2000, Excel 2002, or Excel 2003)? This site is for you! If you use a later version of Excel, visit our ExcelTips site focusing on the ribbon interface.

Newest Tips
Subscribe

FREE SERVICE: Get tips like this every week in ExcelTips, a free productivity newsletter. Enter your address and click "Subscribe."

(Your e-mail address is not shared with anyone, ever.)

View the most recent newsletter.