【簡単エクセル/Excel VBA マクロ】リストから要素をランダムに選択する方法|フィッシャー・イェーツのシャッフル|ワンポイントテクニック #007


いつもありがとうございます!
皆さん、こんにちは。ご覧いただきありがとうございます。
“日々の業務にちょうどいい自動化を”──
業務改善アプリケーションの作成を行っている「ソフトデザイン工房」 です。
データ処理において「ランダム性」が求められる場面は意外と多いものです。例えば、アンケート回答のランダム抽出や、商品リストのランダム表示、さらにはチームメンバーのランダムな組み分けなどです。
では、「ランダム選択」を行うにはどうすれば良いのでしょうか?
そこで登場するのが「フィッシャー・イェーツのシャッフル」です。この手法をVBAで実装することで、要素の順序をランダムに並べ替えることが可能です。
この記事が、あなたのVBAマクロの価値をさらに高める一助となれば幸いです。
VBAを活用して、自分自身や身近なコミュニティに合ったアプリケーションを作成し、仕事量は半分に、成果は2倍に──そんな未来を目指すあなたを応援しています。
リストから要素をランダムに選択する方法|フィッシャー・イェーツのシャッフル

シナリオ
1週間の曜日(日、月、火、水、木、金、土)7つの中から、ランダムに3つを選びます。
具体例と解説
百聞は一見に如かず。まずは、上述のシナリオを実現するコードと、その実行結果を示します。
コードは以下の通りです。
Option Explicit ' 変数宣言の強制(タイプミスや意図しないデータ型の使用を防止)
Sub SelectRandomly()
' 変数の宣言
Dim days_array() As Variant ' 1週間の曜日を格納する配列
Dim current_index As Long ' 現在の配列インデックス
Dim random_index As Long ' ランダムに選ばれたインデックス
Dim swapping_day As String ' 入れ替え用に記録する一時的な曜日
' 配列に1週間分の曜日を設定
days_array = Array("日", "月", "火", "水", "木", "金", "土")
' シード値を初期化
Randomize
' フィッシャー・イェーツ法でシャッフル:
' 配列の最後の要素から順に、ランダムに選んだ別の要素と入れ替えて固定する
' UBound=6、LBound=0
For current_index = UBound(days_array) To LBound(days_array) Step -1
' LBound~current_indexの範囲(未処理の範囲)でRnd関数を使用して
' ランダムなインデックスを生成:
' Int関数:小数点以下を切り捨て整数部分を返す 例)Int(5.9)→5、Int(0.999)→0
' Rnd関数:0.0 以上 1.0 未満の乱数を返す 例)0.123, 0.999, 0.456 など
random_index = Int( _
(current_index - LBound(days_array) + 1) * Rnd _
) + LBound(days_array)
' 現在の要素(current_index)とランダムに選んだ要素(random_index)を交換:
' 現在の要素を一時的な変数に保存(上書きを防ぐため)
swapping_day = days_array(current_index)
' 現在の位置(インデックス)にランダムに選んだ要素を代入
days_array(current_index) = days_array(random_index)
' 一時的に保存していた現在の要素をランダムな位置に代入して交換
' ※これをしないと要素が重複する
days_array(random_index) = swapping_day
Next current_index
' シャッフル後の最初の3要素を出力
Debug.Print "ランダムに選ばれた3要素:"
For current_index = LBound(days_array) To LBound(days_array) + 2
Debug.Print days_array(current_index)
Next current_index
End Subこのコードを実行するとイミディエイトウィンドウに以下のような結果が出力されます。毎回結果は異なります。
実行1回目:
ランダムに選ばれた3要素:
日
月
金実行2回目:
ランダムに選ばれた3要素:
水
火
土実行3回目:
ランダムに選ばれた3要素:
水
金
日
解説していきます!
Option Explicit ' 変数宣言の強制(タイプミスや意図しないデータ型の使用を防止)ここでは、Option Explicit を有効にしています。この設定を使うと、変数を使用する前に必ず宣言が必要になります。これにより、変数のタイプミスや未定義変数によるエラーを防ぎ、コードの安全性と信頼性を高めることができます。
' 変数の宣言
Dim days_array() As Variant ' 1週間の曜日を格納する配列
Dim current_index As Long ' 現在の配列インデックス
Dim random_index As Long ' ランダムに選ばれたインデックス
Dim swapping_day As String ' 入れ替え用に記録する一時的な曜日ここでは、コード内で使用する変数が宣言されています。変数は Dim 変数名 As データ型 の構文で宣言します。これにより、各変数は As 以降で指定したデータ型のデータを格納できるようになります。
なお、各データ型の意味は下表の通りです。
| データ型 | 種類 | 意味 |
|---|---|---|
Long |
数値型 | -2,147,483,648 から 2,147,483,647 までの範囲の整数を格納できる数値型のデータ型です。 |
Variant |
汎用型 | 任意のデータ型を格納できる柔軟なデータ型です。ここでは配列などに使用されています。 |
String |
文字列型 | テキスト情報を格納する文字列型のデータ型です。 |
' 配列に1週間分の曜日を設定
days_array = Array("日", "月", "火", "水", "木", "金", "土")ここでは、1週間の曜日を配列に設定しています。この配列を後のシャッフル処理でランダムに並び替えます。なお、Array関数を使用しており、要素数が明確であるため、配列のサイズ調整をする必要(Redimをする必要)はありません。
' シード値を初期化
Randomizeここでは、Randomizeを使用して乱数生成器のシード値を現在の時刻に基づいて設定しています。この設定により、Rnd関数が毎回異なる乱数列を生成し、ランダム性が高い動作を実現します。シード値を設定しない場合、乱数列が固定され、ファイルを開くたびに同じ結果が繰り返されます。
' フィッシャー・イェーツ法でシャッフル:
' 配列の最後の要素から順に、ランダムに選んだ別の要素と入れ替えて固定する
' UBound=6、LBound=0
For current_index = UBound(days_array) To LBound(days_array) Step -1
' LBound~current_indexの範囲(未処理の範囲)でRnd関数を使用して
' ランダムなインデックスを生成:
' Int関数:小数点以下を切り捨て整数部分を返す 例)Int(5.9)→5、Int(0.999)→0
' Rnd関数:0.0 以上 1.0 未満の乱数を返す 例)0.123, 0.999, 0.456 など
random_index = Int( _
(current_index - LBound(days_array) + 1) * Rnd _
) + LBound(days_array)
' 現在の要素(current_index)とランダムに選んだ要素(random_index)を交換:
' 現在の要素を一時的な変数に保存(上書きを防ぐため)
swapping_day = days_array(current_index)
' 現在の位置(インデックス)にランダムに選んだ要素を代入
days_array(current_index) = days_array(random_index)
' 一時的に保存していた現在の要素をランダムな位置に代入して交換
' ※これをしないと要素が重複する
days_array(random_index) = swapping_day
Next current_indexここでは、配列をランダムに並べ替えるためにフィッシャー・イェーツシャッフルを実装しています。
ランダムに選ばれたインデックス同士で要素を入れ替えていくことで、重複することなくシャッフルが実現されています。ループが進むにつれて、未処理の部分(未シャッフルの部分)が少しずつ減っていくため、シャッフルが終了した時点で配列の要素は完全にランダムな順番に並び替えられます。
この方法を使うことで、配列の要素を効率よく、かつ公平にシャッフルすることができます。
' シャッフル後の最初の3要素を出力
Debug.Print "ランダムに選ばれた3要素:"
For current_index = LBound(days_array) To LBound(days_array) + 2
Debug.Print days_array(current_index)
Next current_indexここでは、シャッフル後の配列から最初の3要素を出力しています。

以上で解説は終了です。ありがとうございました!
VBAスキルアップの参考情報
近年は、ChatGPTをはじめとするAIの登場によって、学習のスタイルが大きく変わりました。
分からないことがあれば、AIに尋ねれば答えがすぐに見つかる時代です。
とはいえ、AIを使いこなすには、自分自身の基本的な知識や理解力が欠かせません。
全体像をつかむためには、やはり書籍などで体系的に学んでおくことが今でも有効です。
そのうえでAIを活用すれば、自分の理解度に合わせた的確な解説や、応用のヒントを得ることができます。
「学んで基礎を築く → AIで補い発展させる」──このサイクルを重ねることで、VBAスキルは着実に高まっていくでしょう。
VBAのスキルアップ
VBAを学び始めるなら
入門書は、どれを選んでも大きな差はないように感じます。
どれを選ぶかに悩むことに時間をかけるよりも、まずは手頃な一冊を手に取って進めてみるのがおすすめです。
もし迷ったときには、私はインプレス社の「いちばんやさしい」シリーズを選ぶことが多いです。
基礎を超えて力をつけたいなら
私は上級者を目指していましたので、入門書にとどまらず、このような内容の濃い一冊を選んで学んでいました。
今は誰でもAIを活用できる時代になりましたが、上級者を目指す方にとっては、AIをより上手に活用するという意味でも、こうした本は今なお価値があります。
このレベルの本を一冊持っておくことに、損はないでしょう。
資格で能力を証明したいなら
VBAのプログラミング能力を客観的に示したい場合には「VBAエキスパート試験」があります。
特に「スタンダード」の方は上級者向けです。
あなたが社内業務の改善を行う立場であっても、VBAで作成したシステムをお客様に納める立場であっても、この資格は信頼や安心につながるでしょう。
以下の公式テキストが販売されています。
プログラミングの一般教養
「独学プログラマー」というプログラミングの魅力を解説した書籍があります。
これはVBAではなくPythonを題材としていますが、プログラミングの基本的な知識や思考法、仕事の進め方まで幅広く学べます。
今はAIにコードを尋ねれば、答えが返ってくる時代です。
しかし、この本からは「コード」以上に、プログラミングに向き合う姿勢や考え方を学ぶことができるでしょう。
こちらの記事でも紹介しています。もしよろしければご覧ください。
【初心者歓迎】無料相談受付中

いつもありがとうございます!
限られた時間をより良く使い、日本の生産性を高めたい──
みんなの実用学を運営するソフトデザイン工房では、業務整理や業務改善アプリケーション作成のご相談を承っております。
お気軽にご相談ください。
こちらの記事でも紹介しております。
おわりに


ご覧いただきありがとうございました!
今回の記事では、「リストから要素をランダムに選択する方法」を解説しました。
お問い合わせやご要望がございましたら、「お問い合わせ/ご要望」フォームまたはコメント欄よりお知らせください。
この記事が皆様のお役に立てれば幸いです。
なお、当サイトでは様々な情報を発信しております。よろしければトップページもあわせてご覧ください。




