ユーザーフォーム 第9回 リストボックス

ユーザーフォーム

リストボックス(基礎編)

 リストボックスは、リストを表示させておいて、その中から項目を選択するコントロールです。
 選択する項目は複数指定することもできます。
 解りやすくするためにこのページでは単一選択について解説し、複数選択については別のページで解説します。
 
 作り方としてはコンボボックスに似ており、表示するリストを設定すること、そして選択された項目の取得方法を押さえておけば大丈夫です。
 リストは複数列で表示する事もできますが、Excelシートのような高度な機能は持っていません。

リストボックスの使い方

 リストボックスの使い方を理解するには、リストの設定と値の取得に注目しましょう。
 リストの設定には、
 ・1つずつ追加していく(AddItem)
 ・リストで指定(List)
 ・セル範囲で指定(RowSource)

 という3種類の方法があります。

 値の取得は、TextプロパティValueプロパティで取得できます。
 変更後すぐに取得したい場合はChangeイベントで拾うと良いでしょう。
 
 具体的な例を見ていきます。

 サンプルコードの作り方は、コンボボックスのページを参照してください。

リストの設定方法

 リストボックスのリストの設定は、
 ・1つずつAddItemで追加する方法
 ・Listプロパティに配列を設定する方法
 ・RowSourceプロパティでセルの範囲を指定する方法
 があります。

 リストの設定は初期化(Initialize)のタイミングで行うのが一般的です。
 UserForm1にInitializeプロシージャを追加します。
 ユーザーフォームのコード画面から、上部のダウンリストから UserForm1 を選択し、右のダウンリストから Initialize を選択して追加します。

AddItemで設定

 リストを1つずつ設定するには、AddItemメソッドを使用します。
 複数列の設定には向いていません。

Private Sub UserForm_Initialize()
    Me.ListBox1.AddItem "りんご"
    Me.ListBox1.AddItem "いちご"
    Me.ListBox1.AddItem "みかん"
End Sub

 上記のように羅列しても構いませんが、Withステートメントで記述を省略する事もできます。

Private Sub UserForm_Initialize()
    With Me.ListBox1
    .AddItem "りんご"
    .AddItem "いちご"
    .AddItem "みかん"
    End With
End Sub

順番指定

 AddItemでは、第2引数にリストの順番を指定する事もできます。
 指定方法は、カンマにつづけて数値を書きますが、それまでのアイテム数より大きいとエラーとなります。
 数値は0が一番上になります。
 また、後から書いた方が優先されます

Private Sub UserForm_Initialize()
    With Me.ListBox1
    .AddItem "いちご", 0
    .AddItem "りんご", 0
    .AddItem "みかん", 1
    End With
End Sub

 上記の例では上から、りんご、みかん、いちごの順になります。
 あとから定義した方が優先され ”いちご” は最後に繰り下げられます。

Listプロパティで設定

 リストボックスのListプロパティを使えば、リストを直接指定できます。
 以下の例では2列のリストを設定しています。

Private Sub UserForm_Initialize()
    Dim arr(2, 1)
    arr(0, 0) = "りんご"
    arr(1, 0) = "いちご"
    arr(2, 0) = "みかん"
    arr(0, 1) = "100"
    arr(1, 1) = "200"
    arr(2, 1) = "300"
    
    With ListBox1
        .ColumnCount = 2
        .ColumnWidths = "60;50"
        .List = arr
    End With
End Sub

 Listプロパティで配列を指定します。
 複数列の指定では列数指定を ColumnCount で、各列の幅指定を ColumnWidthsで行います。

 
 セルの範囲を指定したい場合は、配列の範囲(Range)を一旦変数で受けて配列にしてから代入します。
 Sheet2 シートの A1:B3 に値がある場合です。

Private Sub UserForm_Initialize()
    Dim arr
    arr = Worksheets("Sheet2").Range("A1:B3")
    
    With ListBox1
        .ColumnCount = 2
        .ColumnWidths = "60;50"
        .List = arr
    End With
End Sub

RowSourceプロパティで設定

 リストボックスのプロパティであるRowSourceにセルの範囲を設定すれば、これをリストとして指定できます。

 Sheet2 シートの A1:A3 にある値をリストとしたい時は、ListBox1のプロパティウインドウの「RowSource」の項目に、「Sheet2!A1:A3」と入力します。
 尚、この場合、Initializeなどにリストボックスの設定コードを書くとエラーとなります。

 同じ事をプログラムコードで書くときは、以下のようにします。

Private Sub UserForm_Initialize()
    With ListBox1
        .ColumnCount = 2
        .ColumnWidths = "60;50"
        .RowSource = Worksheets("Sheet2").Range("A1:B3").Address(External:=True)
    End With
End Sub

 とします。 External:=True を指定しないと別のシートにリストがある場合上手くいきません。

選択された値を取得

 選択された値の取得は、何行目であるかをListIndexプロパティで得ます。
複数列ある場合は、TextプロパティValueプロパティでそれぞれ個別に取得する列を決める事が出来ます。また、Listプロパティを使えば、List( 行 , 列 )という形で値を取り出す事ができます。
 尚、複数行指定(fmMultiSelectMultiなど)にしていると、TextプロパティとValueプロパティは空白やNULLを返してきますので注意してください。

選択された項目が何番目か?

 値だけでなくリストの何番目を選択したかを得たい時は、ListIndexプロパティを使います。
 1番上なら0が返り、
 選択されていない場合は‐1が返ってきます。

MsgBox  Me.ListBox1.ListIndex

複数列の設定

 リストボックスのリストで複数列を指定する場合は、
 ・列の数
 ・Textとして取得する列の設定
 ・Valueとして取得する列の設定
 ・列幅の指定
 ・リストの指定

 
 などを指定する必要があります。

 以下のコードでは、Sheet2シートのA1:A3をリストに指定しています。
 Textは1列目、Valueは2列目を指定していますので、それぞれ別々に値を取得する事ができるようになります。

Private Sub UserForm_Initialize()
    Dim myList
    myList = Worksheets("Sheet2").Range("A1:B3")
    With ListBox1
        .ColumnCount = 2            '表示列数の設定
        .TextColumn = 1              'Textとして取得する列の設定
        .BoundColumn = 2            'Valueとして取得する列の設定
        .ColumnWidths = "60;50"  '列幅の指定
        .List = myList                  'リストの設定
    End With
End Sub

TextプロパティとValueプロパティの指定

 リストボックスでは、TextColumnプロパティTextプロパティの値を指定できます。
 ListBox1.TextColumn = 2 
 
 また、BoundColumnプロパティValueプロパティの値を指定できます。
 ListBox1.BoundColumn = 1
 
 これらは別々に指定できます。
 
 選択されていない時のTextプロパティとValueプロパティの返り値は異なりますので注意してください。 
 Textプロパティでは空白
 ValueプロパティではNULL

 が返ります。空白とNULLは異なるので、判断処理を誤るとエラーとなります。

 また、MultiSelectプロパティが、fmMultiSelectSingle」(単一選択のみ)以外の時は機能しません。(複数選択の解説は、別ページで行います。)

 ユーザーフォームにコマンドボタンを2つ追加し、オブジェクト名をそれぞれ、「TextButton」「ValueButton」とした時の例を示します。

Private Sub TextButton_Click()
    If Me.ListBox1.Text = "" Then
        MsgBox "値が空白です"
    Else
        MsgBox Me.ListBox1.Text
    End If
End Sub

Private Sub ValueButton_Click()
    'Debug.Print Me.ListBox1.Value
    If IsNull(Me.ListBox1.Value) Then
        MsgBox "値がありません"
    ElseIf Me.ListBox1.Value = "" Then
        MsgBox "値が空白です"
    Else
        MsgBox Me.ListBox1.Value
    End If
End Sub

【参考】
 選択が無い時、コンボボックスでは、Valueに空白が返されましたが、リストボックスでは、NULLが返るようです。

List プロパティで列を指定

 Listプロパティを使えば、List( 行 , 列 )という形で値を取り出す事ができます。
 選択された行はListIndexプロパティで取得できますので、行にはこの値を置きます。
 列は0から始まる値で指定できます。

MsgBox Me.ListBox1.List(Me.ListBox1.ListIndex, 1)

値取得のタイミング

 リストボックスの Changeイベントやダブルクリックイベントなどを使えば、選択後すぐに値を拾うことができます。
 準備としてユーザーフォームをモードレスにして動作を確認してみましょう。
 UserForm1 オブジェクトの ShowModal を 「False」 に設定します。

Changeイベント

 ユーザーフォームのコード画面で、上部のドロップボックスからListBox1Changeを選択すると、イベントプロシージャが表示されます。
 以下のプログラムでは、リストボックスの値を変更するたびに選択された値を表示します。

ダブルクリックイベント

 ユーザーフォームのコード画面で、上部のドロップボックスからListBox1DblClickを選択すると、イベントプロシージャが表示されます。
 以下のプログラムでは、リストボックスの値を変更するたびに選択された値を表示します。

ユーザーフォームを閉じる時

 「終了」ボタンなどを設けて、ユーザーフォームを閉じる際に全てのコントロールを値を反映させるような場合もあります。
 そのような場合は、Unload する前に値を取得すればOKです。

 尚、複数選択の場合は、リストボックスのイベントで取得する事はできませんので、コマンドボタンやフォームを閉じるタイミングで取得する事になります。

リストボックスの主なプロパティ

 リストボックスにも他のコントロールと同様にたくさんのプロパティがあります。
 ここでは、特徴的な2つのプロパティを紹介します。

ListStyle プロパティ

 リストの左側にオプションボタンやチェックボックスを表示させます。

定 数説 明
fmListStylePlain0標準のリストボックス表示
fmListStyleOption1各項目の先頭にオプションボタンまたはチェックボックスを表示

 MultiSelect プロパティが単一選択の場合はオプションボタン。

 複数選択の場合はチェックボックスとなります。

MultiSelectプロパティ

 単一選択と複数選択を指定できます。

定 数説 明
fmMultiSelectSingle0単一選択
fmMultiSelectMulti1クリックするたびに選択
fmMultiSelectExtended2windows基準の選択方法

 複数選択の場合は、選択する時の動作が異なりTextプロパティやValueプロパティは使いません。
 代わりにSelectedプロパティを使います。

 複数選択については、別ページで解説します。

まとめ

 このページでは、リストボックスの単一選択について解説しました。
 リストの設定では、AddItemで1つずつ追加していく方法や配列セルを参照させる方法がありました。
 
 選択された項目の取得では、複数列表示させる場合は、Textプロパティと Valueプロパティで別々の値を指定できます。
 何も選択されていない場合に、
 Textプロパティでは空白
 ValueプロパティではNULL

 が返ってくる点に注意が必要です。
また、Listプロパティを使えば、List( 行 , 列 )という形で値を取り出す事ができます。

一連のコードを示します。

'ユーザーフォームの初期化設定
Private Sub UserForm_Initialize()
    '// シートの値を使ってリストを作る
    Dim arr
    arr = Worksheets("Sheet1").Range("A1:C5")
    With ListBox1
        .ColumnCount = 3
        .TextColumn = 1              'Textとして取得する列の設定
        .BoundColumn = 2            'Valueとして取得する列の設定
        .ColumnWidths = "40;40;40"
        .List = arr
    End With
End Sub

'リストボックスに変更があった時のイベント
Private Sub ListBox1_Change()
    If Me.ListBox1.ListIndex > 0 Then
        Dim str As String
        str = Me.ListBox1.Text    '1列目
        str = str & vbCrLf & Me.ListBox1.Value      '2列目
        str = str & vbCrLf & Me.ListBox1.List(Me.ListBox1.ListIndex, 2)   '3列目
        
        MsgBox str
    End If
End Sub

 

 次回は、複数選択できるようなリストボックスのプログラムを解説します。
 複数選択では、選択された項目がリストで返ってくる点に注意が必要です。

タイトルとURLをコピーしました