ListBoxを操作するクラスモジュール ① 配列でリスト作成

ことりちゅんさんに倣い、ListBoxを操作するクラスモジュールを、
私なりに作ってみることにした。
f:id:Infoment:20200929223930p:plain

例えば、こんなリストボックスがあったとする。
f:id:Infoment:20200929224547p:plain

それで、選択された行(今回も書き易さの都合上、「行」「列」で表現する)
に対して何某かの処理をするため、今まで何度となくこのようなコードを
書いてきた。

    Dim i As Long
        For i = 0 To ListBox1.ListCount - 1
            If ListBox1.Selected(i) Then
                何某かの処理
            End If
        Next

一行ずつ「選ばれているかどうか」を確認し、「選ばれているなら」で
何某かの処理を行っている。これが、何とも面倒臭い。

そこで少しでも簡便にするため、クラスモジュールを作成することにした。

今回は、配列でリストを作成するところまで作ってみた。

クラスモジュール(ListBoxControl)

何かと値を遣り取りするために、リスト作成に使用した配列は、そのまま
保持しておくことにした。リストボックスは行数・列数ともに0番目から
始まるため、配列のインデックスもそれに合わせて変換している。

' 対象となるリストボックス。
Public TargetListBox As MSForms.ListBox

' リストとして与えられた配列(二次元配列)。
' 一次元配列は、複数行1列の二次元配列に変換後のもの。
' またインデックスは、行と列ともに0始まりへ矯正後のもの。
Private ListArray() As Variant

' ループ用整数。
Private i As Long
Private j As Long

' リスト用に与えられた配列の次元数。
Private DimensionNumber As Long

Private Sub Class_Initialize()

    ' リストボックスに渡した配列の次元数。
    ' 初期値は一次元配列とする。
    DimensionNumber = 1

End Sub

' リストボックスにリストをセット。
Public Sub SetList(ByVal list_array As Variant)

    ' 仮の配列。
    Dim Temp As Variant
        ' list_arrayが配列なら、そのままTempにセット。
        ' 配列でないならば、一旦配列化したのちセット。
        If IsArray(list_array) Then
            Temp = list_array
        Else
            Temp = Array(list_array)
        End If
        TargetListBox.List = Temp
    
        ' 配列のインデックスについて、最小値を一旦
        ' 「1」としたい。
        ' 配列が一次元の場合、Transpose関数で一旦行列を反転させると、
        ' インデックスの最小値が1の、複数行1列の二次元配列になる。
        Temp = WorksheetFunction.Transpose(Temp)
        
        ' 二次元目のインデックス最大値が1で無い場合、配列は元から
        ' 二次元配列ということになる。したがって、行列を反転して元に戻す。
        ' またこの時点で、元の配列のインデックス最小値が何であっても、
        ' 行と列ともに1から始まる配列となる。
        If UBound(Temp, 2) <> 1 Then
            Temp = WorksheetFunction.Transpose(Temp)
            DimensionNumber = 2
        End If
        
        ' リストボックスのリストと同じ構成の二次元配列を作成する。
        ' リストボックスは行列共に0始まりであるため、下記でその
        ' ギャップを解消している。
    ReDim ListArray(UBound(Temp) - 1, UBound(Temp, 2) - 1)
        For i = 0 To UBound(ListArray)
            For j = 0 To UBound(ListArray, 2)
                ListArray(i, j) = Temp(i + 1, j + 1)
            Next
        Next

End Sub
ユーザーフォーム

今回、こちらの範囲をリストボックスに表示する。
f:id:Infoment:20200929225543p:plain

ラベル行が含まれているが、今回は不問とする。
また、ListBox1のColumnCountは予め「4」としている。

Dim Lbc As VBAProject.ListBoxControl

Private Sub UserForm_Initialize()
    ' リストを作成するための配列。
    Dim arr As Variant
        arr = Range("A1").CurrentRegion
    
    ' クラスモジュール初期化。
    Set Lbc = New VBAProject.ListBoxControl
    ' ListBox1を対象としてセット。
    Set Lbc.TargetListBox = ListBox1
    ' 配列からリスト作成。
        Lbc.SetList arr
End Sub

今回の結果がこちら。
f:id:Infoment:20200929225948p:plain


またしても見切り発車で始まった、今回のシリーズ。
果たして無事に、ゴールできますことやら。

次回に続きます。

参考まで。