リストボックスから二つだけ選ばせたい ② 三つ以上選ばせない

昨日はリストボックスから二つだけ選ばせる方策として、選択数が二つ以外の時は投票ボタンを無効化してみた。
infoment.hatenablog.com
しかしこの方法だと、選択項目が100個ある場合、100個全て選べてしまう。98個分の選択解除を行うまで投票ボタンが押せないというのは、寂しい話だ。

そこで今日は、上記のような事態にならない工夫に挑戦する。
f:id:Infoment:20190106110820p:plain

今回立てた作戦は、こうだ。

3個目を選んだ際、1個目の選択を解除する。

これなら、選ばれている項目数は常に2個以下になる。

ユーザーフォーム

まず選択順が分かるように、リストボックスを2列にする。
f:id:Infoment:20190106111117p:plain

ついでに、昨日のリストに「うどん」が二つあったので、コッソリ削除。

何個選ばれているか?はたびたび登場するので、昨日作成したユーザー定義関数:JudgeSpecifiedNumberから独立させた。

Private Function JudgeSpecifiedNumber(Optional n As Long = 2) As Boolean
    If Counter = n Then
        JudgeSpecifiedNumber = True
    Else
        JudgeSpecifiedNumber = False
    End If
End Function
Private Property Get 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
End Property

次いで、ListBox1_MouseUpを少し改造する。
以下のように場合分けしてみた。

① 選択数が0のとき:
 ListBox1をリセットする。

② 選択数が1のとき:
 選択された項目について、選択順を1にする。
 それ以外の項目は、全て選択順を0にする。

③ 選択数が2のとき:
 選択された項目について、選択順が1の場合はそのままに。
 選択された項目について、選択順が0ならば2にする。
 それ以外の項目は、全て選択順を0にする。
 ※「3つの選択項目から1つ減らされた場合」は考慮不要。

④ 選択数が3のとき:
 選択された項目について、選択順が1の場合は0にして選択解除。
 選択された項目について、選択順が2の場合は1にする。
 選択された項目について、選択順が0の場合は2にする。
 それ以外の項目は、全て選択順を0にする。
 ※これにより、3つ以上の項目が選択された状態は存在しえない。

コード化してみる。

Private Sub ListBox1_MouseUp(ByVal Button As Integer, _
                             ByVal Shift As Integer, _
                             ByVal X As Single, _
                             ByVal Y As Single)
    Dim i As Long
    Select Case Counter
        Case 0
            ListBox1.Clear
            ListBox1.List = myList
        
        Case 1
            For i = 0 To ListBox1.ListCount - 1
                If ListBox1.Selected(i) Then
                    ListBox1.List(i, 1) = 1
                Else
                    ListBox1.List(i, 1) = 0
                End If
            Next
        
        Case 2
            For i = 0 To ListBox1.ListCount - 1
                If ListBox1.Selected(i) Then
                    ListBox1.List(i, 1) = 2 - ListBox1.List(i, 1)
                Else
                    ListBox1.List(i, 1) = 0
                End If
            Next
        
        Case 3
            For i = 0 To ListBox1.ListCount - 1
                If ListBox1.Selected(i) Then
                    Select Case ListBox1.List(i, 1)
                        Case 1
                            ListBox1.List(i, 1) = 0
                            ListBox1.Selected(i) = False
                        Case 2
                            ListBox1.List(i, 1) = 1
                        Case 0
                            ListBox1.List(i, 1) = 2
                    End Select
                Else
                    ListBox1.List(i, 1) = 0
                End If
            Next
    End Select
                             
    VoteButton.Enabled = JudgeSpecifiedNumber(2)
End Sub

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

3つ目を選んだとき、解除したくない方が解除されるという場合については・・・選び直しでお願いします。

参考まで。