RandArray関数っぽいユーザー定義関数で、重複不可の引数を追加

昨日は、RandArray関数っぽく振舞う、ユーザー定義関数を作ってみた。
infoment.hatenablog.com

これの使い処を考えるうち、思いついた。少し手を加えれば、ランダムな並び替えに使用できるのでは?ということで、やってみた。
f:id:Infoment:20200113232131p:plain

ランダム並び替えといっても、実はたいしたことをしていない。
単に、ランダムな整数の重複を禁止しただけ。結果が、ランダムに並べ替えたように見えるだけだったりする。

Function DemiRandArray(r_max As Long, _
                       c_max As Long, _
                       dra_min As Long, _
                       dra_max As Long, _
                       integer_flag As Boolean, _
              Optional duplicate_flag As Boolean = False) As Variant

    ' duplicate_flagがTrueの場合、整数に限り値の重複を不可とする。
    
    ' ランダムに作成した値を格納するための配列。
    Dim arr() As Variant
    ReDim arr(1 To r_max, 1 To c_max)
    
    ' ループ変数:行。
    Dim r As Long
    ' ループ変数:列。
    Dim c As Long
    ' 重複不可の場合に使用する辞書。
    Dim Dict As Object
    Set Dict = CreateObject("Scripting.Dictionary")
    
    ' ランダムに作成した値を一旦格納するための変数。
    Dim temp As Double
        For r = 1 To r_max
            For c = 1 To c_max
                ' Trueの場合、整数のみとする。
                Select Case integer_flag
                    Case True
                        ' Trueの場合、重複不可とする。
                        Select Case duplicate_flag
                            Case True
                                Do
                                    temp = WorksheetFunction.RandBetween(dra_min, dra_max)
                                    If Dict.Exists(temp) = False Then
                                        arr(r, c) = temp
                                        ' キー情報の重複を確認したいだけなので、アイテム不問。
                                        ' なんでもよいので、今回は「1」とした。
                                        Dict(temp) = 1
                                        Exit Do
                                    End If
                                Loop
                            Case False
                                arr(r, c) = WorksheetFunction.RandBetween(dra_min, dra_max)
                        End Select
                    Case False
                        Dim myFlag As Boolean
                            myFlag = False
                        Do While myFlag = False
                            temp = Rnd * (dra_max + 1)
                            If dra_min <= temp And temp <= dra_max Then
                                arr(r, c) = temp
                                myFlag = True
                            End If
                        Loop
                End Select
            Next
        Next
                
        DemiRandArray = arr
End Function

それでは、1~75までの数字を縦に並べてみよう。
まずは、重複可の場合。

Sub Test()
    Dim arr As Variant
        arr = DemiRandArray(75, 1, 1, 75, True)
        Range("A2").Resize(75) = arr
End Sub

ピボットテーブルで集計してみると、欠番が生じていることが分かる。
f:id:Infoment:20200113232548p:plain

次いで、重複不可の場合。

Sub Test()
    Dim arr As Variant
        arr = DemiRandArray(75, 1, 1, 75, True, True)
        Range("A2").Resize(75) = arr
End Sub

1~75までの数が、全て一つずつ生成されている。
f:id:Infoment:20200113232745p:plain

どうやら、上手くいったようだ。

では、これで何をするかというと・・・ビンゴゲームかな。

参考まで。