どうでもいいプログラム研究所

とある編集者によるIT、Web、ソフトウェア、プログラミングに関する雑記と覚え書き

Excel VBAで重複しないランダムな数字を生成するマクロ

f:id:tdyu5021:20190505211955p:plain

趣味でエクセルVBAを使ってあるツールを作ってたとき、重複しないランダムな数(乱数)を生成する必要があり、他のWebサイトを見ながら調べました。それと同じものですが、備忘録がわりに以下にコードを載せます。

早速、コードは以下です。

Sub Randomizing()
   Dim MaxNum As Long
   Dim flg() As Boolean
   Dim num As Long
   Dim i As Long
   Dim Number() As Long

   MaxNum = 10 '←生成したい最大値をここに記入

   ReDim Number(1 To MaxNum) As Long
   ReDim flg(1 To MaxNum) As Boolean

   Randomize

   For i = 1 To MaxNum

      Do
         num = Int(Rnd * MaxNum) + 1
         If flg(num) = False Then
            flg(num) = True
            Number(i) = num
            Exit Do
         End If
      Loop

   Next i
 '//ここからは、生成した乱数(Number())をセルに書きだす処理'
   For j = 1 To MaxNum
      Cells(j, 1).Value = Number(j)
   Next

End Sub

このコードは数字の1から指定した任意の数まで、1回ずつランダムに数字が生成されます。生成したい数の最大値は、変数MaxNumで指定します(たとえば、1から10までの乱数を生成したいなら“MaxNum = 10”とする)

このコードを丸ごとコピペして、標準モジュールに張り付けて実行すればセルA1からA10までランダムに1から10までの数字が1回ずつ入力されます。

5つ乱数がほしい場合は、"For i = 1 To MaxNum"の部分の”1 To MaxNum”を”1 to 5”とすればOKです。

 簡単な解説

おそらくほかの方の記事で解説があるかと思いますし、解説するほどでもないのですが、念のため触れておきます。

配列の要素数を再定義するReDim

最初に以下の記述があると思います。

ReDim Number(1 To MaxNum) As Long
ReDim flg(1 To MaxNum) As Boolean

Number()という配列は、生成したランダムな数字を格納していく配列です。ReDimは最初の決めた配列の要素数を再定義するための宣言です。もちろんこの要素数を最初のDimの段階で定義してももちろん動作しますが、プログラムの途中で要素数を変更する必要もあるかもしれませんし、この記述をしたほうが他のプログラムなどへの移植性や柔軟性を考えた際に便利です。

乱数の生成

ランダムな数の生成を行っているのは“num = Int(Rnd * MaxNum) + 1”の部分です。MaxNumを10とすると、1から10までのランダムな数値が変数numに格納されます。

単にランダムな数字がほしいのであればこの1行でOKです。ただ、これだと重複が発生するかもしれません。そこで必要になるのが次の記述です。

重複を避けるための処理

If flg(num) = False Then
   flg(num) = True
   Number(i) = num
   Exit Do
End If

前の項でランダムな数字numが出現したら、配列変数のflg()の[num]番をフラグオンにしておき、「その[num]番はすでに使いましたよ」という目印を立てておくのです。

ランダムな数字はNumber()という配列変数にどんどん格納してきます。ただし、上記の5行のコードをみてわかるように、それは flg()がフラグオフ(=まだ一度もその数字が出現していない)でなければ実行されません。Do Loopをかけているので、無事にNumberに格納されない限り繰り返されます。

以上が簡単な解説です。ランダムな数字の生成は、業務で使用するツールにはまず出てくることはないでしょうけど、私のようにExcelでの簡単なゲームとかくだらないツール作るときには頻出なので備忘録としてここに記しました。