リストボックスから二つだけ選ばせたい ① 投票ボタンを押させない

以前、こんな相談を受けたことがあった。

  1. 複数の人に投票してもらう案件がある。
  2. 複数ある候補から、2つ選んで投票する。
  3. 必ず2つ選んで投票して欲しい。

2つというのが、なかなか悩ましい。
一つの場合:ListBox1.MultiSelect = fmMultiSelectSingle
複数の場合:ListBox1.MultiSelect = fmMultiSelectMulti
のようにMultiSelectプロパティで制御できるが、2つ限定のプロパティは無い。

そこで、色々と模索してみた。
f:id:Infoment:20190105100549p:plain

今回はとりあえず、こんな投票フォームを準備してみた。

f:id:Infoment:20190105100639p:plain

2つ選んで投票するのだから、↓ の設定にしておく。

ListBox1.MultiSelect = fmMultiSelectMulti

最初に思いついた作戦は、ListBoxで選ばれた項目が二つの時にだけ、投票ボタンを有効にするというもの。
そこで先ず、ユーザーフォームの初期化時に投票ボタンを無効化した。

Dim myList As Variant

Private Sub UserForm_Initialize()
    myList = Array("カレーライス", "ラーメン", "うどん", _
                 "うどん", "そば", "パスタ", "カツ丼")
    ListBox1.List = myList
    
    ' 投票ボタンの状態を「無効」にする。
    VoteButton.Enabled = False
End Sub

f:id:Infoment:20190105102942p:plain

次いで、リストボックスで選択された項目が幾つかを判別するために、関数を一つ準備する。将来的に「3つ」「4つ」と要求が変わるかもしれないので、「幾つ」の部分は引数にしておく。

Private Function JudgeSpecifiedNumber(Optional n As Long = 2) As Boolean
    Dim Counter As Long
        Counter = 0
    Dim i As Long
        For i = 0 To ListBox1.ListCount - 1
            If ListBox1.Selected(i) Then
                Counter = Counter + 1
            End If
        Next
        
        If Counter = n Then
            JudgeSpecifiedNumber = True
        Else
            JudgeSpecifiedNumber = False
        End If
End Function

最後に、リストボックスをクリックしたボタンが上がった時点で選択されている項目の数で、投票ボタンの有効無効を切り替える。

Private Sub ListBox1_MouseUp(ByVal Button As Integer, _
                             ByVal Shift As Integer, _
                             ByVal X As Single, _
                             ByVal Y As Single)
    VoteButton.Enabled = JudgeSpecifiedNumber(2)
End Sub

JudgeSpecifiedNumberをBoolean型にしたため、ボタンの有効 ⇔ 無効の切り替えにそのまま使用できる。

結果、このようになった。
f:id:Infoment:20190105105445g:plain

一応、要求された条件は満たした。しかし、何だかちょっと、面倒くさい。
例えばリストの項目を全て選択してしまうと、投票可能になるまで幾つも
項目の選択解除が必要になってしまう。この辺り、どう工夫したものか。

ということで、次回に続きます。

参考まで。