取るべきアプローチはたくさんありますが、@CMArg は、配列またはディクショナリが重複を避けるための良い方法であると言っています。
回避したいのは、各セルの入力に時間がかかるシナリオです。非常に小さな正方形 (例: 10x10) では問題ありませんが、非常に大きな正方形は見苦しくなります。(範囲が 1 ~ 100 で、31 を除くすべての数字が既にテーブルにある場合、未使用の数字を 1 つ取得するには、平均で 100 回の推測が必要になります。範囲が 1 の場合-40000 (200x200)、最後のセルを埋めるのに 40000 回の推測が必要です。)
したがって、すでに使用されている数字のリストを保持する代わりに、どのように効果的に調べて、既に使用されている数字を「クロスオフ」し、新しいセルごとに正確に 1 つの「推測」でデータを入力できるかを考えてください。
これを実装する方法の 1 つを次に示します。
クラス: SingleRandoms
Option Explicit
Private mUnusedValues As Scripting.Dictionary
Private mUsedValues As Scripting.Dictionary
Private Sub Class_Initialize()
Set mUnusedValues = New Scripting.Dictionary
Set mUsedValues = New Scripting.Dictionary
End Sub
Public Sub GenerateRange(minimumNumber As Long, maximumNumber As Long)
Dim i As Long
With mUnusedValues
.RemoveAll
For i = minimumNumber To maximumNumber
.Add i, i
Next
End With
End Sub
Public Function GetRandom() As Long
Dim i As Long, keyID As Long
Randomize timer
With mUnusedValues
i = .Count
keyID = Int(Rnd * i)
GetRandom = .Keys(keyID)
.Remove GetRandom
End With
mUsedValues.Add GetRandom, GetRandom
End Function
Public Property Get AvailableValues() As Scripting.Dictionary
Set AvailableValues = mUnusedValues
End Property
Public Property Get UsedValues() As Scripting.Dictionary
Set UsedValues = mUsedValues
End Property
実際のクラスの例:
Public Sub getRandoms()
Dim r As SingleRandoms
Set r = New SingleRandoms
With r
.GenerateRange 1, 100
Do Until .AvailableValues.Count = 0
Debug.Print .GetRandom()
Loop
End With
End Sub
コレクションを使用すると、実際にはディクショナリを使用するよりもメモリ効率が高く高速になりますが、ディクショナリを使用すると、本来の動作を行っていることを簡単に検証できます.Exists
( などを使用できるため)。