トップ > 逆引きで学ぶ ユーザーフォーム&コントロール > 追加章 現場で活かせる!実践ユーザーフォーム > B-04 キー入力にあわせて候補を絞り込むリストを作成

B-04 キー入力にあわせて候補を絞り込むリストを作成2022.05.31

次の書籍の第1章~5章を公開しています。
「Excel VBA 逆引きで学ぶ ユーザーフォーム&コントロール」

目次  前頁  索引

入力補助機能として「キー入力にあわせて候補を絞り込むリストを利用したい」といったことはないでしょうか。

今回は、キーを押すたびに候補が絞り込まれるリストを作成します。
リストボックスの実践応用サンプルです。
フォームはキーボードのみで操作できる仕様にしています。

【例】フォームのテキストボックスに商品コードと入力すると データベースから候補となるデータを抽出しリスト表示する

【動画】
・「入力補助」にチェックを入れると 薄い水色セル範囲を選択した場合にフォームが表示される
・フォームのテキストボックスに入力した値に応じてリストが作成される
・[Enter]キーを押すと 選択したリストの項目(商品コード)がセルに反映される


このような動作の実現にはいくつかの方法が考えられますが、最も簡単だと思われる方法で実装します。

サンプルファイル ダウンロード


準備 1シート

シートを2枚準備します。

■「入力」シート
B列に商品コードを入力すると、C列に商品名、D列にサイズが表示されるように数式を設定します。
そして入力補助On/Off用のチェックボックスをセル[E1]に配置します。


■「データ」シート
データベース用のシートです。


準備 2チェックボックス

■チェックボックスの挿入
「開発」タブ→「挿入」→「フォーム コントロール」→「チェックボックス」
チェックボックスを選択すると、マウスカーソルの形が変わります。その状態でシートをクリックするとチェックボックスが挿入されます。


■チェックボックスの設定
チェックボックスの右クリックメニューから「コントロールの書式設定」を選択すると、「コントロールの書式設定」ダイアログが表示されます。

ダイアログの「コントロール」タブにある「リンクするセル」にセル参照を設定します。
セルをリンクすると、チェックボックスのon/offにあわせ、リンクしたセルにTRUE/FALSEの値が自動で設定されます。
セルの値表示が気になる場合は、フォント色をセル背景色に同じにし、見えないようにすると良いでしょう。


準備 3フォーム

ユーザーフォームを挿入し、次のコントロールを追加します。
TextBoxコントロール
 役割:値入力用
 オブジェクト名:TextBox1
 個数:1


ListBoxコントロール
 役割:リスト表示・選択用
 オブジェクト名:ListBox1
 個数:1
 ColumnCount:2 (列数)
 ColumnWidths:49.95;160 (列幅)


サンプルコード

コードは、Sheet1、UserForm1、標準モジュールにそれぞれ記載します。


【Sheet1】
Option Explicit
'【定数】
Const TGT_RANGE As String = "B2:B11" '入力補助フォーム表示対象のセル範囲

'■シートイベント(Sheet1) '+++ SelectionChangeイベント +++ 'セルの選択が変更された場合に発生するイベント Private Sub Worksheet_SelectionChange(ByVal Target As Range) '「入力補助」チェックボックスがOffの場合は抜ける If CBool(Range("E1")) = False Then Exit Sub '選択されたセルが検索欄表示対象セル範囲外の場合は抜ける If Intersect(Range(TGT_RANGE), Target) Is Nothing Then Exit Sub '選択されたセルが複数の場合は抜ける If 1 < Target.Cells.Count Then Exit Sub '選択されたセルのアドレスをグローバル変数に格納 strTarget = Target.Address 'フォームを表示 UserForm1.Show End Sub
【UserForm1】
Option Explicit

Private varData   As Variant
Private lngSelect As Long

'■フォームイベント(UserForm) '+++ Initializeイベント +++ インスタンス生成時に発生 Private Sub UserForm_Initialize() 'フォームの表示位置設定 Dim sinLeft As Single Dim sinTop As Single Dim dblX As Double Dim dblY As Double With ActiveSheet.Range(strTarget) sinLeft = .Offset(, 1).Left '対象セルの一つ右のセル水平位置取得 sinTop = .Offset(, 1).Top '対象セルの一つ右のセル垂直位置取得 End With With ActiveWindow dblX = .PointsToScreenPixelsX(0) / 96 * 72 + sinLeft * .Zoom / 100 dblY = .PointsToScreenPixelsY(0) / 96 * 72 + sinTop * .Zoom / 100 End With With Me .StartUpPosition = 0 .Left = dblX .Top = dblY - 28 '-28:フォーム垂直位置調整(見出しの高さ分) End With '「商品データ」シートの商品コードと商品名を変数に格納 With Sheet2 Dim lngLastRow As Long lngLastRow = .Cells(.Rows.Count, "A").End(xlUp).Row If lngLastRow < 3 Then lngLastRow = 3 varData = .Range("A2:B" & lngLastRow).Value End With 'テキストボックスにフォーカスを移す TextBox1.SetFocus End Sub
'■テキストボックスイベント(TextBox1) '+++ Changeイベント +++ 値に変化があった時に発生 Private Sub TextBox1_Change() 'リストボックスのリストを全てクリア ListBox1.Clear 'テキストボックス1が空白の場合は抜ける Dim strText As String strText = TextBox1.Text If Len(strText) = 0 Then Exit Sub With ListBox1 Dim i As Long '変数varDataにテキストボックスの値が含まれる場合は配列を追加する For i = 1 To UBound(varData) If InStr(1, CStr(varData(i, 1)), strText, vbTextCompare) Then 'リスト(商品コード)を追加 .AddItem varData(i, 1) '2列目に商品名を追加 .List(.ListCount - 1, 1) = varData(i, 2) End If Next If .ListCount = 0 Then Exit Sub 'リストを選択状態にする If .ListCount - 1 < lngSelect Then lngSelect = .ListCount - 1 .ListIndex = lngSelect End With End Sub
'+++ KeyDownイベント +++ キーが押された時に発生 Private Sub TextBox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, _ ByVal Shift As Integer) With ListBox1 If .ListCount = 0 Then 'リストがない場合は抜ける '[Enter]か[Esc]が押されていたらフォームを閉じる If KeyCode = vbKeyReturn Or KeyCode = vbKeyEscape Then Unload Me Exit Sub End If Select Case KeyCode Case vbKeyReturn '[Enter]が押された '選択されている項目をセルに設定 Range(strTarget).Value = .List(lngSelect) Unload Me Case vbKeyEscape '[Esc]が押された Unload Me Case vbKeyUp '[↑]が押された lngSelect = lngSelect - 1 If lngSelect < 0 Then lngSelect = 0 .ListIndex = lngSelect Case vbKeyDown '[↓]が押された lngSelect = lngSelect + 1 If .ListCount - 1 < lngSelect Then lngSelect = .ListCount - 1 .ListIndex = lngSelect End Select End With End Sub
'+++ Exitイベント +++ フォーカスが抜ける時に発生 Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean) Cancel = True 'テキストボックスからフォーカスが移るのをキャンセルする End Sub
'■リストボックスイベント(ListBox1) '+++ DblClickイベント +++ ダブルクリックされた時に発生 Private Sub ListBox1_DblClick(ByVal Cancel As MSForms.ReturnBoolean) '選択されている項目をセルに設定 Range(strTarget).Value = ListBox1.List(ListBox1.ListIndex) Unload Me End Sub
【標準モジュール】
Option Explicit
'+++ 宣言セクション +++
'グローバル変数
Public strTarget As String

簡単な解説

■シートイベント
Sheet1のイベントの目的は、選択されたセルのアドレスを取得し、フォームを表示することです。
フォームの表示にあたって次の確認を行っています。
・入力補助機能のOn/Off
・フォーム表示対象セル範囲
・セル個数
これらの条件を満たした場合にフォームを表示させます。

コード内のRange(TGT_RANGE)は、フォーム表示対象セル範囲[B2:B11]を表します。
If Intersect(Range(TGT_RANGE), Target) Is Nothing Then Exit Sub は、
Range(TGT_RANGE)と選択されたセル(Target)の共通セルを確認しています。
共通セルがなければ、選択されたセルは[B2:B11]の範囲外なので、イベントを抜けるようにしています。

■フォームの表示位置
フォームは、Sheet1のセル範囲[B2:B11]が選択された場合に、アクティブセルの一つ右のセルに表示されます。
フォーム表示位置を設定する詳細はこちらをご覧ください。
フォームの表示対象セル範囲を変更する場合は、Sheet1モジュールの赤文字箇所を変更します。
Const TGT_RANGE As String = "B2:B11"

■リストの作成
フォームのInitializeイベントでSheet2(「商品データ」シート)のA列最終行を取得し、A列・B列(商品コード・商品名)の値を変数varDataに格納しています。
リスト作成時にはこの変数を参照しています。

実際のリストの作成は、テキストボックスのChangeイベントで行っています。
Changeイベントでは、リストを一度クリアし新たにリストを作成しています。

リストの追加判定は次のコードで行っています。
If 0 < InStr(1, varData(i, 1), strValue, vbTextCompare) Then
※vbTextCompareは大文字・小文字や全角・半角を区別しません
 区別させる場合は vbBinaryCompare を指定します

変数varDataの1列目に、テキストボックスの入力値が含まれているかを判定し、含まれている場合にリストを追加しています。
リストは、AddItemメソッドで追加し、1列目は商品コード、2列目は商品名を設定しています。(リスト内では、1列目は「0」、2列目は「1」のように、0から始まる番号で管理されています。行も同様になります。)
リストの追加を終えたら、ListIndexプロパティでリストを選択状態にしています。

■リストの選択と決定
リストの選択と決定は、テキストボックスのKeyDownイベントで行っています。
KeyDownイベントでは引数のKeyCodeで押されたキーを判定しています。
[↑][↓]が押された場合は選択項目の移動、
[Enter]の場合は選択している項目をセルに設定しフォームを閉じる、
[Esc]の場合は、何もせずにフォームを閉じています。

※KeyCode
引数 KeyCodeは押されたキーのコードを返します。
返されるコードは整数値ですが、対応した組み込み定数が準備されています。
一般的にはそれを利用することが多いです。型としてはvbKey○○になります。
[ MSDN KeyCode組み込み定数一覧 ]

■テキストボックスにフォーカスを留める
[Enter]や[Tab]、マウスのクリックでテキストボックスからフォーカスが移動すると、KeyDownイベントが発生しなくなります。それを防ぐためにExitイベントでフォーカスの制御を行っています。
Exitイベントは該当のコントロールからフォーカスが移動する時に発生します。引数のCancelを設定すると、フォーカスの移動をキャンセルします。


書籍紹介140以上のサンプルファイル付き!

知りたいがすぐわかる! やりたいがすぐできる!
「Excel VBA 逆引きで学ぶ ユーザーフォーム&コントロール」(Kindle版)
ユーザーフォームを扱えると、VBAでできることが大きく広がります!
本書では、知りたいこと、やりたいことから、逆引きで学びを深められます。

■ 購入:amazon

ページトップへ戻る
Copyright(C) 2009- 坂江 保 All Rights Reserved.