I have a requirement to randomize or shuffle a cet of cells in column A subject to the constraint that no cell remains unchanged.
I am placing the candidate randomization in column C with this code:
Sub ShuffleCutandDeal()
Dim A As Range, C As Range
Dim B As Range, cell As Range
Set A = Range("A1:A24")
Set B = Range("B1:B24")
Set C = Range("C1")
A.Copy C
Randomize
For Each cell In B
cell.Value = Rnd()
Next cell
With ActiveSheet.Sort
.SortFields.Clear
.SortFields.Add Key:=Range("B1:B24") _
, SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
.SetRange Range("B1:C24")
.Header = xlNo
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End Sub
The randomization works, but sometimes I get something like:
When I see that a data item has not moved, I re-run the code until all items have been moved.
It seems to me that this "If at first you don't succeed........." approach is really dumb.
Is there a better way to randomize and insure that all the items have moved in one pass ???
EDIT#1:
Based on iliketocode's comment, I attempted to adapt Tony's approach in this post to VBA:
Sub Tony()
Dim A As Range, C As Range
Dim m As Long, t As Variant, i As Long
Dim wf As WorksheetFunction
Set wf = Application.WorksheetFunction
Set A = Range("A1:A24")
Set C = Range("C1:C24")
A.Copy C
For m = 1 To 22
i = wf.RandBetween(m + 1, 24)
t = C(i)
C(i) = C(m)
C(m) = t
Next m
t = C(23)
C(23) = C(24)
C(24) = t
End Sub
I guess the idea is to:
Swap C1 with a random pick between C2 and C24 then
Swap C2 with a random pick between C3 and C24 then
Swap C3 with a random pick between C4 and C24 then
................
Swap C22 with a random pick between C23 and C24 and finally
Swap C23 and C24.
I ran this 1000 times with no unwanted matches appearing.