VBA Randomize 基礎知識

Excel コード

[初歩]Excel VBAで数値をランダム化する方法と基礎知識

かつてはPCでデタラメな数を生成することは、厳密には難しいことだったのですが、最近ではかなり巧妙に、二度と再現できないようなデタラメを作ってくれます。
少々大きな数の、例えば、顧客数から一定人数抜き出すようなことは意外と簡単にできるものです。
Excel では Rnd 関数を利用して、Enter を押すたびにランダムな数を生成するようなシートをつくるのは簡単です。

今回は、VBA Rnd 関数を使用してExcelで数値をランダム化するいくつかのサンプルをチェックします。
どちらかというと、Excel入門者がVBAを始める際の超入門として良いサンプルです。

まずはじめに、エクセルのVBAコードはAlt+F11でコードを確認できますので、予備知識として持っておきましょう。

例1:Excel VBA Randomize でランダム化

1から20までの間で、任意の整数を吐き出す関数を作りたい。

VBA 関数 Randomize でカスタマイズした乱数を生成するのは簡単です。
次のようにします。

step
1
モジュールを作ります


Excelから先程の、Alt+F11でVBAウインドウを開きます。
VBAウィンドウで、「挿入」メニューから「モジュール」タブを選択します。

VBA モジュール作成

step
2
VBAコードを定義する


VBA Rz のサブカテゴリを作成するか、任意の名前でVBAコードを定義します。
下の例では VBA_Rzとしました。

 VBA
Sub VBA_Rz()
End Sub

step
3
変数を定義します

 VBA
Sub VBA_Rz()
Dim RN As Double
End Sub

ここでは、変数 RN を Double(データ型:倍精度浮動小数点)にしました。Double にしたのは、生成された乱数にちょっと変更が加わることを狙ってのことです。

step
4
変数に関数を割り当てます


そして、定義済みの変数 RN に、VBA の Rnd 関数を割り当てます。

 VBA
Sub VBA_Rz()
Dim RN As Double
RN = Rnd
End Sub

step
5
Debug.Printで中身をチェック


生成した乱数を確認したいので、値を画面に表示するために Debug.Print を使います。

 VBA
Sub VBA_Rz()
Dim RN As Double
RN = Rnd
Debug.Print RN
End Sub

Debug.Printは途中の変数に何が入っているかを確認するために、画面出力させるときによく使います。
うまく動くことが確認できれば、Debug.Printについては普通はリリース時(公開時)に消してしまう(動かさない)ようにします。
(消さなくても構いませんが、冗長な表示になるので鬱陶しいはずです)

step
6
変数を確認します


変数や数値を確認するために、[表示]メニューからイミディエイトウィンドウを開きます。

ショートカットキー Ctrl + G でウィンドウを表示することもできます。

step
7
コンパイルします

VBAモジュール実行
コードをコンパイルし、メニューバーの下にある[再生]ボタンをクリックして実行します。
イミディエイトウィンドウに最初の乱数が表示されます。
コンパイルそのものは自動で行われますので、[再生]ボタンをクリックするだけで大丈夫です。

手っ取り早くF5を押して実行しても大丈夫です。

また、コードを何度も何度も実行すると、さらにいくつかの乱数が表示されます。

step
8
Randomize を先に実行して完璧な乱数に

Excel の Rnd 関数はデタラメをつくる関数のように思いがちですが、乱数を作り出す際に、シード値をみて乱数表から値を拾ってきているだけです。そのため、シード値が同じなら毎回決まった順番で乱数が返ります。ようするに、Excel を起動したときのシード値は毎回同じになります。
そのため、本気の乱数が欲しい場合は、Rnd 関数実行前に、Randomize を実行して Rnd 関数が取得していたシード値そのものをランダムにする必要があります。くじ引きなどでExcelを利用する人は、このことを強く意識しておきましょう。

ネーテ
購入した新品のトランプをシャッフルせずにテーブルに配るようなものです。麻雀牌でも同じですね。
 VBA
Sub VBA_Rz()
Dim RN As Double
Randomize
RN = Rnd
Debug.Print RN
End Sub

step
9
生成された数字が乱数かを確認

F5で、コードを複数回実行して、生成された数字が乱数かどうかを確認します。

Randomize を Rnd 関数より先に実行することにより、Excel の毎回起動時に同じシード値が設定されることはありません。
逆に、乱数とはいえ、毎回同じ値を拾いたいこともあるはずですから、その場合は Randomize は省略しましょう。

VBA Randamize

同じコーディングでさらに実験してみます。次に、Rnd 関数と一緒にデータ型変換に使うCInt関数を使ってみます。
これで、生成された乱数(Double型)が整数(Integer型)に変換されます。

 VBA
Sub VBA_Rz1()
Dim RN As Double
RN = CInt(Rnd)
Debug.Print RN
End Sub

VBA Rnd 整数化

ここでもう一度コードを実行します。結果を見れば、乱数が整数として生成されていることがわかります。ただし、値は0から1の範囲です。

Double型でランダム値を使い続けても、値は0から1の間(というか0か1のどちらか)にしかなりません。
これは、Rnd 関数と一緒に Randomizeを使用したためです。 それでは、Rnd 関数に任意の数(ここでは20にします)を掛けてみましょう。

 vba
Sub VBA_Rz1()
Dim RN As Double
RN = CInt(Rnd * 20)
Debug.Print RN
End Sub

ここでもう一度コードを実行します。

VBA Rnd 整数化

これでやりたかったことができました。 生成されるランダム値は0より大きく、20未満になります。
上のコードの20の部分を好きな整数に書き換えれば、その好きな整数未満の数、0以上の整数が返ります。

例2:Excel VBA 乱数生成

別の例で、VBA の Randomize がどのように機能するかを確認してみます。
Randomizeと一緒にいくつかの数式を適用し、乱数生成法が乱数値の生成にどう働くかをみてみます。

ただし、本例では、メッセージボックスに出力するようにします。これを行うには、以下の手順に従います。

step
1
先程の例に加えて関数作成

モジュールで、以下に示すようにVBA Rzのサブカテゴリを記述します。

 VBA
Sub VBA_Rz2()
End Sub

step
2
整数型で定義する


例1とは違って、変数を、今度は整数型で定義します。

 VBA
Sub VBA_Rz2()
Dim RN As Integer
End Sub

step
3
Randomize 関数をまず使う


数式を入力する前に、Randomize 関数を使って、シード値をシャッフルします。

 VBA
Sub VBA_Rz2()
Dim RN As Integer
Randomize
End Sub

step
4
適当な数式を入れてみる


次に、下の例に倣って、必要に応じて、足し算、引き算などの数式をいれてみます。

 VBA
Sub VBA_Rz2()
Dim RN As Integer
Randomize
RN = Int((300 - 200 + 1)
End Sub

この段階では変数RNは整数値101でしかありません。

step
5
Rnd 関数も使ってみる


Rnd 関数をここで使って、乱数を発生させます。

 VBA
Sub VBA_Randomize2()
Dim RN As Integer
Randomize
RN = Int((300 - 200 + 1) * Rnd + 200)
End Sub

普通に使われる数式の大半がこの段階で(代りに)使えます。

step
6
Msgboxで値を確認する


Msgbox を利用して、生成された乱数の中身を確認します。

 VBA
Sub VBA_Rz2()
Dim RN As Integer
Randomize
RN = Int((300 - 200 + 1) * Rnd + 200)
MsgBox RN
End Sub

step
7
コードを実行します

F5でコードを実行します。

VBA MsgBox

乱数は300のような値が返ります。これは、数値に($300 - 200 + 1$)を掛けてから、200を足しているため、1以上300以下の整数が返ります。
というのは、生成される乱数そのものは小さい値に過ぎないのですが、数式で数を大きく割増しているので、300のような値を返すことになります。

VBA MsgBox

そして、コードを再度実行すると、メッセージは先ほどと違う値の 258になります。

VBA Rnd 関数 のキモ

Rnd()として普通に使うと、シード値が変わらないので、Excel を起動してから生成する乱数は毎回同じパターになる。

Randomizeして、Rnd()を使うと、シード値がシャッフルするので、Excel を起動するタイミングに関わらず再現性の低い乱数が生成できる。

また、Rnd()の引数には、正の値、ゼロ(0)、負の数値の3パターンある。引数は省略でき、省略した場合は正の値を入れたものとして扱われる(デフォルト)。

  • 正の引数値:(シード値から参照される)次の乱数の値を返し。引数を省略したときと同じ
  • ゼロ(0):直前の乱数の値を返す
  • 負の引数値:シード値を指定して乱数を返す

わかりやすく解釈すると、Rnd(0)とやると、乱数値は固定される。
好きな乱数が出たら、すかさずRnd(0)としてやると、ずっと同じ数(直前のRnd()で出した数)を使い続けることができる。
Rnd(-1)というように、負の数を入れると、シード値が固定されるので、毎回ワンパターンの乱数値が並ぶ。

Excel VBA Randomize を使うメリット

  • 任意の範囲で任意の乱数を生成できる
  • 範囲が制限されても、乱数の生成に制限はつかない
  • 0より大きい乱数生成の範囲を制限できる

覚えておくべきこと

  • Randomize は、さまざまな関数で使える。Rnd 関数と使うことで、パターン化された乱数もが、より乱数になる
  • Randomize は、Rnd 関数と一緒に使うことで、0から1までの乱数を出せる


関連記事
エクセル ランダム
[VBA]Excel でランダム抽出するマクロ

かつて予想外に速攻作成に悩んだのが、Excel VBA で一覧からの無作為(ランダム)抽選です。ランダムは追求すると難し ...

続きを見る

RECOMMEND

-Excel, コード
-, , , , , ,