インストールレスプログラミング( ´ー`)

VBA , JavaScript , HTAなど 365アプリはインストール必要ですが、仕事に無いケースはほぼないから(・_・;)

Powerpoint VBA 重複しないランダムな整数値を作る

クイズの選択肢をランダムに並び替える。

この方法はいくらでもあると思うんですが,他でも応用が効くように,ランダムな整数値を作り,その順に並べなおすという方法を取ってみる。

その前段階として,例えば 5 という数値を与えたら 1~5の値をランダムに並べたものを配列で返す,という関数を作ってみることにしました。

Excelでなら,WorksheetfunctionにRankやCountifがあるから比較的楽に作れますが,

Powerpoint等になると,少し手間がかかりました。

手間がかかる方法を取っただけかもしれませんけど。。

最初に整数値を並べてそれをシャッフルする方法などもよく書いてありますが,今回はそれではないです。。

コードはこちら

Function RandArray(argMax As Long) As Variant
    Dim col As Collection: Set col = New Collection
    Dim Arr(): ReDim Arr(1 To argMax)
    Randomize
    
    Dim i As Long
    For i = 1 To argMax
        col.Add Rnd
    Next
    
    Dim tmp As Long, c
    For i = 1 To argMax
        tmp = 0
        For Each c In col
            If c < col(i) Then tmp = tmp + 1
        Next
        Arr(i) = tmp + 1
    Next
    
    RandArray = Arr
End Function

要素数が決まっているので,コレクションは使わなくてもいけます。ただ使いたかっただけ。。使い続けないと忘れる。。

方針としては,次のように考えました。
① RandomizeとRnd関数のコンビで 重複しない乱数を発生させます。
② まずその乱数をargMaxで指定された数だけコレクションに収める。
③ 重複していない(はず)なので,順位を取ればランダムに並んだ整数値を取れるはずです。
  ExcelならWorksheetfunctionのrankでさくっとこれが実現できますが,Powerpointではそれはできません。
  rank関数はCountifで代用できます。でも,これもExcelならWorksheetfunctionでいけますが,PowerpointにはCountifもありませんでした・・(;´▽`A``
  はい。For EachループでごりごりCountifの代わりをすることにしています。。

    Dim tmp As Long, c
    For i = 1 To argMax
        tmp = 0
        For Each c In col
            If c < col(i) Then tmp = tmp + 1
        Next
        Arr(i) = tmp + 1
    Next

For eachで ぐるぐる回す変数はバリアント型またはオブジェクト型である必要があります。
なので,cは型を与えずバリアント型で宣言しています。

Rankの代わりがCountifでできる,または,単純にループでできる,というのは盲点でした。当たり前といえば当たり前ですが,考えたり調べたりするものですね。。

目から鱗です。パズルのようで面白い。考えてみると楽しかったです。

PowerpointでRank使えないけどどうしたらいいの!?という場合の解決法になるかも,という意味でも今回の試みは面白かったです。


えっと,RandArray関数はVariant型配列なので,

RandArray(5) としたら1~5をランダムにならべたものを収納していますので,
まず何か違う変数に一回その配列ごといれてください。
実行するたびRandomizeで値が変わるので,直接 RandArray(5)(1)みたいな取得をして使うことは,正しい使用法とはならないことになります。

    Dim arr
    arr = RandArray(5)

こんな感じでバリアント型に一気につっこむ。一気にやらないといけないというのは大事な注意点です。。

次回は具体的に選択肢を入れ替えるあたりを書きます。