VBAにおいて、フォームにコントロール(ボタンなど)を動的に配置する方法がわかりにくかったので、恥ずかしながらQAサイトなどからコードのかけらを集めてサンプルプログラムを書いてみました(3時間前に発見していたら嬉しかっただろうというものです)。
Dictionaryに格納した複数の文字列をボタンとして配置したフォームをポップアップさせます。
ボタンを押下すると、そのボタンに設定したnameプロパティをmsgboxで出力します。
(ここで押した場合の値を後で使用するにはグローバル変数に格納するのがよさそう?
SelectSortBookForm
'' ユーザフォームに空フォームを定義しておく。キャプションなど必要であればプロパティから変更しておく。
Private Sub SelectForm()
End Sub
MyButton
'' コマンドボタンの実態をクラスモジュールに作成しておく
Public WithEvents button As CommandButton
'' クリックイベント発生時の動作
Private Sub button_Click() 
    pub_clickedButtonName = button.name
    Unload SelectForm'フォームをメモリから解放する
End Sub
module1
'' Dictionary型を引数にとって全要素をボタンにしたFormを作成する
Sub make_form(dictionary As Object)
    Dim i As Integer
    Dim btn As Control
    Dim NewBtn() As New MyButton ''ボタンオブジェクトを動的配列
    ReDim NewBtn(1 To dictionary.Count) '' 配列の長さを動的に決定
    With SelectForm
        i = 1
        For Each Key In dictionary
            Set btn = .Controls.Add("Forms.CommandButton.1", dictionary(Key)) 
            '' 第一引数はコマンドボタンを表し、第二引数がnameプロパティになる
            With btn
                .Top = 5 + (i - 1) * 20
                .Left = 5
                .Height = 20
                .Width = 60
                .Caption = "No." & i & ":" & dictionary(Key)
            End With
            Set NewBtn(i) = New MyButton
            Set NewBtn(i).button = btn
            i = i + 1
        Next Key
        .Height = i * 20 + 10
        .Width = 70
        .Show ' フォームを起動する
    End With
End Sub
'' テストメソッド
' フォームで押されたボタンの名前を呼び出し元で利用するためにはpublicで変数を作成しておく必要がある。
Public pub_clickedButtonName As String
Sub test_make_form()
    Dim targetDictionary As Object
    Set targetDictionary = CreateObject("Scripting.Dictionary")
    
    targetDictionary(0) = "ビアンカ"
    targetDictionary(1) = "フローラ"
    targetDictionary(2) = "ルドマン"
    
    Call make_form(targetDictionary)
    msgbox pub_clickedButtonName
End Sub
雑感
- VBA系の公式ドキュメント、えらいわかりにくいorさがしにくい
 - コントロールなどGUI系の用語よくわかっていない