非IT企業に勤める中年サラリーマンのIT日記

非IT企業でしかもITとは全く関係ない部署にいる中年エンジニア。唯一の趣味がプログラミングという”自称”プログラマー。

【ExcelVBA】重複しないランダム番号を生成する方法

   

Excel VBAでランダムな数値を生成する際、単にRnd関数を使うだけでは、同じ数値が複数回出現する「重複」の問題に直面することがあります。しかし、抽選番号の生成やユニークなIDの作成など、重複しないランダムな番号が必要な場面は少なくありません。

この記事では、VBAのScripting.Dictionaryオブジェクトを活用し、効率的かつ確実に重複しないランダム番号を生成する方法を解説します。現場で今すぐ使える実用的なコードを提供しますので、ぜひ参考にしてください。

Dictionaryを使った重複しないランダム番号の生成

重複しないランダム番号を生成する最も確実な方法は、すでに生成した番号を記録し、新しい番号が生成されるたびにその記録と照合することです。ここで威力を発揮するのが、キーとアイテムのペアでデータを管理するScripting.Dictionaryオブジェクトです。

  • 生成する番号の範囲: 例として1から100までの範囲
  • 必要なユニークな番号の数: 例として10個

このシナリオで、重複しないランダム番号を生成する関数を作成します。

サンプルコード

以下の関数GenerateUniqueRandomNumbersは、指定された範囲から、指定された数の重複しないランダム番号を配列として返します。

Function GenerateUniqueRandomNumbers(ByVal minVal As Long, ByVal maxVal As Long, ByVal count As Long) As Variant
    Dim dict As Object
    Dim result() As Long
    Dim i As Long
    Dim randomNumber As Long
    Dim rangeSize As Long
    
    ' 必要な数と範囲の整合性チェック
    rangeSize = maxVal - minVal + 1
    If count > rangeSize Or count <= 0 Then
        MsgBox "必要な番号の数が範囲を超えているか、無効です。", vbCritical
        GenerateUniqueRandomNumbers = Array()
        Exit Function
    End If
    
    ' Dictionaryオブジェクトを初期化
    Set dict = CreateObject("Scripting.Dictionary")
    
    ' 乱数ジェネレータを初期化
    Randomize
    
    ' 指定された数のユニークな乱数を生成
    Do While dict.Count < count
        ' minValからmaxValまでの乱数を生成
        randomNumber = Int((maxVal - minVal + 1) * Rnd + minVal)
        
        ' Dictionaryに存在しない場合のみ追加
        If Not dict.Exists(randomNumber) Then
            dict.Add randomNumber, True
        End If
    Loop
    
    ' Dictionaryのキーを配列として取得
    ReDim result(0 To dict.Count - 1)
    i = 0
    For Each Key In dict.Keys
        result(i) = Key
        i = i + 1
    Next Key
    
    GenerateUniqueRandomNumbers = result
    Set dict = Nothing
End Function
 
コードの解説
  • Set dict = CreateObject("Scripting.Dictionary"): Scripting.Dictionaryオブジェクトを生成します。これはキーの一意性を保証するのに非常に便利です。
  • Randomize: 乱数ジェネレータを初期化します。これを記述しないと、VBAを再起動しない限り常に同じ乱数列が生成されてしまいます。
  • Do While dict.Count < count: 必要な数のユニークな番号がDictionaryに格納されるまでループを続けます。
  • randomNumber = Int((maxVal - minVal + 1) * Rnd + minVal): 指定されたminValからmaxValまでの範囲で乱数を生成します。
  • If Not dict.Exists(randomNumber) Then dict.Add randomNumber, True: 生成されたrandomNumberがDictionaryにまだ存在しない場合にのみ、キーとして追加します。Trueはダミーの値です。このExistsメソッドが重複チェックの核となります。
  • ReDim result(0 To dict.Count - 1) ... For Each Key In dict.Keys: Dictionaryに格納されたユニークな番号(キー)を配列resultに格納し、関数の戻り値として返します。

使用例

上記で作成した関数を使って、実際に重複しないランダム番号をシートに出力してみましょう。

Sub Sample_Usage_UniqueRandomNumbers()
    Dim uniqueNumbers As Variant
    Dim i As Long
    
    ' 1から100の範囲で、10個の重複しないランダム番号を生成
    uniqueNumbers = GenerateUniqueRandomNumbers(1, 100, 10)
    
    ' 結果をイミディエイトウィンドウに出力
    Debug.Print "--- 生成された重複しないランダム番号 ---"
    If IsArray(uniqueNumbers) Then
        For i = LBound(uniqueNumbers) To UBound(uniqueNumbers)
            Debug.Print uniqueNumbers(i)
        Next i
    Else
        Debug.Print "番号の生成に失敗しました。"
    End If
    
    ' または、シートのA列に出力する場合
    ' If IsArray(uniqueNumbers) Then
    '     For i = LBound(uniqueNumbers) To UBound(uniqueNumbers)
    '         ThisWorkbook.Sheets("Sheet1").Cells(i + 1, 1).Value = uniqueNumbers(i)
    '     Next i
    ' End If
End Sub
 
使用例の解説
  • uniqueNumbers = GenerateUniqueRandomNumbers(1, 100, 10): GenerateUniqueRandomNumbers関数を呼び出し、1から100の範囲で10個のユニークな番号を生成しています。
  • Debug.Print uniqueNumbers(i): 生成された番号をイミディエイトウィンドウに表示します。必要に応じてコメントアウトされているシートへの出力コードを使用してください。

Scripting.Dictionaryオブジェクトを利用することで、Excel VBAで重複しないランダム番号を効率的かつ確実 に生成することができます。この方法は、抽選システム、テストデータの生成、ユニークなIDの割り当てなど、様々な場面で応用可能です。

 

スポンサーリンク

 - Excel, VBA