【エクセルはとにかく機能が豊富です。その象徴がユーザーフォームです】
エクセルVBAの初級者か、そうでないかの境目の一つは「ユーザーフォームが使えるか?」だと思っています
ユーザーフォームを使うことで、エクセルファイル内の利便性は格段に向上します
ユーザーフォームを使えると、入力と表示を明確に切り分けることができるのでデータを有効活用できるからです
例えば、下の画像を見てください

これはG2セルとG7セルに移動して、会社名をそれぞれ入力しています
つまり、宛先を表示するために、宛先の表示場所に移動して入力作業をしています
これが、ユーザーフォームを使うとどうなるでしょう?

ユーザーフォーム内に表示されている内容から「選択」を行い、「登録」ボタンを押すだけです
これは、繰り返しになりますが、入力と表示が分かれているから行えます
便利なユーザーフォームですが、実際に活用するとなると最初はかなりとっつきにくいと思います
通常のエクセルと考え方が違うからです
後、とにかく機能が多いです
今回の記事ではユーザーフォームを使う中で、躓きやすい「不思議な箇所」、並びにこれは便利だと思った機能を解説したいと思います
VBAを使った事が無い方、VBAを使ったことがあるけどユーザーフォームを使ったことが無い方も、これを機会にユーザーフォームの魅力、エクセルの奥深さを感じて頂けたら幸いです
ちなみに上記のユーザーフォームのコードは以下の通りとなります
初期表示
***
With ListBox1 ’リストボックスのオブジェクト名
.Font.Size = 9
.ColumnCount = 3
.ColumnWidths = “20;50;100”
.TextAlign = fmTextAlignCenter
‘リストボックスに情報を追加
Dim i As Long
Dim myLast As Long
myLast = Worksheets(“①”).Cells(Rows.Count, 2).End(xlUp).Row
For i = 3 To myLast
.AddItem
.List(.ListCount – 1, 0) = Worksheets(“①”).Cells(i, 2).Value
.List(.ListCount – 1, 1) = Worksheets(“①”).Cells(i, 3).Value
.List(.ListCount – 1, 2) = Worksheets(“①”).Cells(i, 4).Value
Next
End With
***
登録ボタン
***
With ListBox1
Dim myValue As String
myValue = .List(.ListIndex, 1)
Worksheets("①").Range("G2").Value = .List(.ListIndex, 2)
Worksheets("①").Range("G7").Value = .List(.ListIndex, 2)
End With
***
目次
リストボックスの10列超を表示できない
例えば、こんな横長な表があったとします

こちらの表をリストボックスで表示してみます

すると上の画像のような不思議なエラーになります
使用しているコードは「AddItem」になります

実はこの「AddItem」を使用する時は10列までしかリストボックスに表示できません
この場合は「RowSource」か「List」を使用し、直接エクセルの範囲を指定します
RowSource
RowSourceの場合は、関数で別シートを参照する時のような書き方で範囲を指定します

これで、B3セルからM列の最終行までをリストボックスで表示できます

しかも、ColumnHeadsを使用して指定範囲の1つ上の行を見出しとして表示できるのが便利です
List
Listで範囲指定する場合には、下のように通常のVBAの書き方をして、最後にValueを付け加えます
.List = Worksheets(“②”).Range(“B2:M” & myLast).Value
但し、RowSourceと違い、見出し設定はできませんのでご注意ください
リストボックスから行削除が行えない
これまた不思議なのですが、.RemoveItemを使用してもリストボックスの行を削除できないことがあります

しかもエラーメッセージが不思議な内容ででます

実はこれ、RowSourceを使用してリストボックスを表示すると起こる現象です
RowSourceを使用する場合であれば、削除はデータ元のエクセルで行う必要があります
他の方法でリストボックスを作成している場合はこの現象はありません
リストボックスを複数選択にする
これはユーザーフォームではこんな事もできるという紹介です

上の画像の「MultiSelect = fmMultiSelectMulti」を追加するだけで、リストボックスは複数選択にできます

これだとどこが選択されているか、どう選択したらいいか分かりにくい、という場合は次の一行を足します

そうすれば、次の画像のように各行にチェックボックスが表示されます

複数選択できるのは分かったけど、どう選択されたものを取得するの?
と思われた方も多いと思います
複数選択されたものを取得するには、リストボックスの各行を繰り返し処理で取得します
そしてポイントは「Selected」を使用して、選択行を特定することです
***
With ListBox1
For i = 0 To .ListCount – 1 ‘ListBoxの各行
If .Selected(i) Then ‘行が選択されている場合
MsgBox .List(i, 0)
.Selected(i) = False
End If
Next i
End With
***
これで複数行を取得できます

テキストボックス内で文字列を折り返す
テキストボックス内でセルと同じように折り返せないか?と思った方もいらっしゃると思います

この場合はプロパティで「MultiLine」をFalseからTrueに変更します

後、もう一か所関係がある箇所があります

WordWrapがTrueに設定してある必要があります
こちらは通常はTrueに設定されています
これで文字列は折り返されます

入力位置遷移(カーソル遷移)
テキストボックス間での遷移を変更したい時があります
以下のGIF画像では横にカーソルが動いています

この遷移を変えたい時には「TabIndex」を変更します

今回の場合で言えば、下のテキストボックスを3から1に変更します
このようにTabIndexを変えれば、カーソル遷移は変わります

<まとめ>
今回はエクセルVBAのユーザーフォームについて記事を書きました
私は正しい脱エクセルをかかげていますが、最近、改めてエクセルの浸透の深さに驚いています
他の言葉で言い換えれば、様々な企業で貴重なエクセル資産があります
わざわざ資産を他に移し替えるのはもったいないケースも多々ありますので、エクセルの研究は引き続き続けていきたいと思います
その研究テーマの一つが今回のユーザーフォームですね
ユーザーフォームは本当奥深いですね
今後も研究は続けていきたいものです
コメントを残す