MSDNフォーラムに「ユーザーフォーム上のコンボボックスで、任意の文字列でアイテムをフィルタリングしたい」といった質問がありました。
早い話がオートコンプリート(サジェスト)機能ですね!
コンボボックスにはMatchEntryプロパティも用意されていますが、今回の用途では物足りません。
そこで、KeyUpイベントを利用した代替手段を考えてみることにしました。
KeyUpイベントによるオートコンプリート機能の実装
さっそくコードです。
ちなみに、下記コードはExcelに限らずWordやPowerPointでもそのまま使用することができます。
'※UserFormに記述
Option Explicit
Private WithEvents cboAutoComplete As MSForms.ComboBox
Private cboStored As Object
Private Sub UserForm_Initialize()
Dim v As Variant
Dim i As Long
'コンボボックスのリスト設定
'下記氏名は http://kazina.com/dummy/ で作成したダミーデータ
v = Array("中原 草太", "柳 隆", "相田 功補", "武田 淳", "関根 守", "松井 美佐", "奥 博明", _
"井上 俊二", "山中 なつみ", "村瀬 由樹", "とよた 京子", "富岡 由宇", "泉 まみ", _
"福岡 憲一", "堀 サダヲ", "小柳 拓郎", "梅沢 季衣", "角 鉄洋", "古谷 詩織", _
"石田 雅之", "海老原 美咲", "遠山 郁恵", "西浦 光", "大沼 しぼり", "奈良 佳乃", _
"有村 美幸", "岩間 広司", "西 明日", "古沢 早織", "柴田 りえ", "西村 美幸", _
"三船 麻緒", "大熊 なつみ", "大泉 芽以", "坪井 有海", "今 玲那", "沢井 奈月", _
"伊藤 莉緒", "山中 春樹", "宮迫 裕司", "有田 ヒカル", "有田 あさみ", "田辺 砂羽", _
"日下 美佐子", "外山 陽子", "池田 ちえみ", "松崎 知史", "吉沢 浩太郎", "田原 惇", _
"金児 路子")
With ComboBox1
.MatchEntry = fmMatchEntryNone
For i = LBound(v) To UBound(v)
.AddItem v(i)
Next
End With
'保存用のComboBoxにリストをコピー
Set cboAutoComplete = ComboBox1
Set cboStored = CreateObject("Forms.ComboBox.1")
cboStored.List = cboAutoComplete.List
End Sub
Private Sub cboAutoComplete_KeyUp(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
Dim accCbo As Office.IAccessible
Dim accLst As Office.IAccessible
Dim i As Long
Set accCbo = cboAutoComplete
Select Case KeyCode
'動作するキー指定 ※必要に応じて変更
'変換(28),無変換(29)
Case 28, 29, vbKeyBack, vbKeySpace, vbKeyDelete, _
vbKeyA To vbKeyZ, vbKey0 To vbKey9, vbKeyNumpad0 To vbKeyNumpad9
'フィルタリングしてアイテム追加
cboAutoComplete.Clear
For i = 0 To cboStored.ListCount - 1
If cboStored.List(i) Like "*" & cboAutoComplete.Text & "*" Then
cboAutoComplete.AddItem cboStored.List(i)
End If
Next
'開いているドロップダウンを閉じる
If accCbo.accName(&H2&) = "閉じる" Then
Set accLst = accCbo.accChild(&H3&)
accLst.accDoDefaultAction &H0&
'DoEvents
End If
cboAutoComplete.DropDown
End Select
End Sub
仕組みは下記のように非常に単純です。
- ユーザーフォームが開いたとき(UserForm_Initialize)に、対象となるコンボボックスのリストを保存用のコンボボックスにコピーする。
- コンボボックスでキーが押されたとき(KeyUpイベント)に、入力された文字列を元にフィルタリングして、保存用のコンボボックスからリストを作成する。
唯一工夫した点は、DropDownメソッドで開いたリストを閉じる処理でしょうか。
下記コードの部分で実装していますが、これがなかなか上手くいきませんでした。
If accCbo.accName(&H2&) = "閉じる" Then Set accLst = accCbo.accChild(&H3&) accLst.accDoDefaultAction &H0& 'DoEvents End If
最初はユーザーフォームにキーコードを送信して無理やり閉じたりしていましたが、最終的には上記の形に落ち着きました。
(もしかしたら、OSやOfficeのバージョンによっては上手く動作しないかもしれません…。)
コンボボックスのオートコンプリート機能、使ってみると項目を選択しやすくなり、中々便利なものでした。
クラス化して使いまわしできるようにすれば、もっと使い勝手が良くなるかもしれませんが、私は普段ユーザーフォーム自体使う機会が少ないので、今回はここまでにしておきます。


















この記事へのコメントはありません。