如何在Excel VBA中创建一个搜索过滤器,以便在键入单词时在列表框中显示搜索结果? [英] How to make a Search Filter in Excel VBA that displays search result in the ListBox while typing a word?
问题描述
我现在正在尝试在用户窗体中进行为期数周的高级搜索,在输入值时它会过滤并在ListBox上显示结果.但是以某种方式,我用作过滤器的ComboBox已经具有下拉功能.
I'm trying to make an Advanced Search now for weeks in my Userform where it will filter and display the result on the ListBox while typing a value. But somehow my ComboBox that serves as a filter has a dropdown function already.
我不知道如何使它像我想要的那样.
I have no idea how can I make it like the way I wanted it.
我的用户窗体包含8列.
My UserForm contains 8 columns.
这是ComboBox过滤器的现有代码
Here is the existing code for the ComboBox filter
Private Sub cmbSearch_Change()
'The function of this code below is for the user to click a value from the ComboBox and then the result will be displayed on the TextBoxes and ListBox.
x = Sheets("DATA STOCK").Range("A" & Rows.Count).End(xlUp).Row
For y = 2 To x
If Sheets("DATA STOCK").Cells(y, 1).Text = cmbSearch.Value Then
cmbSchema.Text = Sheets("DATA STOCK").Cells(y, 1)
cmbEnvironment.Text = Sheets("DATA STOCK").Cells(y, 2)
cmbHost.Text = Sheets("DATA STOCK").Cells(y, 3)
cmbIP.Text = Sheets("DATA STOCK").Cells(y, 4)
cmbAccessible.Text = Sheets("DATA STOCK").Cells(y, 5)
cmbLast.Text = Sheets("DATA STOCK").Cells(y, 6)
cmbConfirmation.Text = Sheets("DATA STOCK").Cells(y, 7)
cmbProjects.Text = Sheets("DATA STOCK").Cells(y, 8)
UserForm1.listHeader.RowSource = "A" + CStr(y) + ": H" + CStr(y)
Exit For
End If
Next y
End Sub
预期结果:
- 用户在ComboBox中键入单词(由于下拉菜单功能,我选择了ComboBox作为过滤器)
- 用户输入时,它将显示结果到列表框.
问题是我不知道如何创建这种搜索过滤器,即使我的ComboBox中已经具有下拉功能,也可能创建该搜索过滤器
The problem is I don't know how to create that kind of search filter and if it is possible even though I already have a dropdown function in my ComboBox
推荐答案
看到您已经为此工作了数周.
Saw that you've been working for weeks on this.
我已经重构了表单的代码,并实现了您一直在寻找的功能.
I have refactored your form's code and implemented the functionality you've been looking for.
作为我对其他问题的另一种回答,我认为与列表范围内的项目相比,在列表框中添加和删除项目要容易得多. (
As my other answer to your other question, in my opinion it's easier to work adding and removing items to the listbox, rather than working with excel ranges. (How to fix this bug in my code that doesn't allow me to update other columns in excel userform?)
重要说明: -我已将工作表中的数据转换为Excel结构表(Ctrl + T) -我取了您以前的文件之一,因此表中的信息可能已过时 -测试我还修改了一些数据 -我建议您复制并粘贴最新数据,然后将其替换到表中
Important remarks: - I've converted the data inside the sheet to an Excel Structured Table (Ctrl + T) - I took one of your previous files, so the information you have inside the table may be out of date - Testing I also modified some of the data - I suggest you copy and paste your most recent data and replace it inside the table
您可以在此处根据数据下载文件: https://github.com/rdiazjimenez/excel-vba-userform-basic-listbox-demo/blob/master/MDM_DB_Checking_09122018_RD.xlsm
Here you can download the file based on your data: https://github.com/rdiazjimenez/excel-vba-userform-basic-listbox-demo/blob/master/MDM_DB_Checking_09122018_RD.xlsm
我介绍了将Excel数据加载到用户窗体内的列表框中的基本操作(创建,读取,更新,删除和搜索/筛选).
I covered basic operations (Create, Read, Update, Delete and Search/Filter) with Excel Data loaded into a Listbox inside a Userform.
这是表格后面的代码:
Option Explicit
' Code updated
Private Sub btnDelete_Click()
Application.EnableEvents = False
Call mCode.Delete
Application.EnableEvents = True
End Sub
' Code updated
Private Sub btnView_Click()
Application.EnableEvents = False
Call mCode.Read
Application.EnableEvents = True
End Sub
' Code updated
Private Sub cmbAdd_Click()
Application.EnableEvents = False
Call mCode.Create
Application.EnableEvents = True
End Sub
' Code updated
Private Sub cmbClearFields_Click()
Application.EnableEvents = False
Call mCode.ClearControls
Application.EnableEvents = True
End Sub
' Code updated
Private Sub cmbSearch_Change()
Application.EnableEvents = False
Call FilterList(Me.listHeader, Me.cmbSearch.Text)
Application.EnableEvents = True
End Sub
' Code updated
Private Sub cmbUpdate_Click()
Application.EnableEvents = False
Call mCode.Update
Application.EnableEvents = True
End Sub
' Code updated
Private Sub CommandButton5_Click()
Application.EnableEvents = False
Call mCode.ClearList
Application.EnableEvents = True
End Sub
' Code from this event was removed
Private Sub listHeader_Click()
End Sub
' Code added
Private Sub listHeader_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
Application.EnableEvents = False
Call mCode.LoadControls
Application.EnableEvents = True
End Sub
' Code partially updated
Private Sub UserForm_Initialize()
Me.cmbSearch.List = ThisWorkbook.Sheets("PRESTAGE DB").ListObjects("TableData").ListColumns(1).DataBodyRange.Value
Me.cmbEnvironment.AddItem "DEV"
Me.cmbEnvironment.AddItem "UAT"
Me.cmbEnvironment.AddItem "SIT"
Me.cmbEnvironment.AddItem "QA"
Me.cmbEnvironment.AddItem "PROD"
Me.cmbAccessible.AddItem "Y"
Me.cmbAccessible.AddItem "N"
Me.cmbIP.AddItem "1521"
Me.cmbProjects.AddItem "DP - proposed for DEV/SIT"
Me.cmbProjects.AddItem "PH EFUSE SIT"
Me.cmbProjects.AddItem "MyAXA SG DEV/DIT"
End Sub
这是名为mCode的模块中的代码:
And this is the code inside a module called mCode:
Option Explicit
' Global variables
Const sheetName As String = "PRESTAGE DB"
Const tableName As String = "TableData"
Public Sub ShowUserForm()
oUserForm.Show
End Sub
Public Sub Read()
' Comments: Loads the data from an excel table (listobject) into a listbox located inside a userform
' Params :
' Notes : Adapt the initialize variables section
' Created : 2019/01/25 RD www.ricardodiaz.co
' Modified:
' Define objects variables
Dim myUserForm As oUserForm ' Note: you're defining the variable as the class of the userform. This gives you access to the userform's controls later
Dim myListObject As Excel.listObject
Dim myRange As Excel.Range
' Define other variables
Dim columnCount As Integer
Dim selectedItem As Integer
Dim rowCounter As Long
Dim columnCounter As Integer
'''''''' Initialize objects ''''''''
' Init the userform
' Note: When you initialize it directly with the name of the form, you can access the controls of the userform too
Set myUserForm = oUserForm
' Load the data from the Excel table into a range variable
' Note: It's safer to refer to thisworkbook
Set myListObject = ThisWorkbook.Worksheets(sheetName).ListObjects(tableName)
'''''''' Initialize variables ''''''''
myUserForm.listHeader.ColumnWidths = "130 pt;60 pt;82 pt;55 pt;70 pt;195 pt;170 pt;130 pt"
' Set the number of columns to the same of the table in the Excel sheet
columnCount = myListObject.ListColumns.Count
' Get the current selected item
selectedItem = myUserForm.listHeader.ListIndex ' this returns -1 if none is selected
' Clear the listbox contents
Call mCode.ClearList
' Set the number of columns to load into the listbox
myUserForm.listHeader.columnCount = columnCount
' Loop through each row and load it into the listbox
' Note: begins with 2 because the first row are the table headers
For rowCounter = 2 To myListObject.Range.Rows.Count
With myUserForm.listHeader
.AddItem
' Load value of each column in the table row
For columnCounter = 0 To columnCount
.List(rowCounter - 2, columnCounter) = myListObject.Range.Cells(rowCounter, columnCounter + 1).Value
Next columnCounter
End With
Next
' Select previously selected row
If selectedItem < myUserForm.listHeader.ListCount Then
myUserForm.listHeader.ListIndex = selectedItem
End If
' Clean up objects
Set myListObject = Nothing
Set myUserForm = Nothing
End Sub
Public Sub Create()
' Comments: Adds a new row with the data entered by the user and reloads the listbox inside the userform
' Params :
' Notes : Adapt the initialize variables section
' Created : 2019/01/25 RD www.ricardodiaz.co
' Modified:
' Define objects variables
Dim myUserForm As oUserForm ' Note: you're defining the variable as the class of the userform. This gives you access to the userform's controls later
Dim myListObject As Excel.listObject
Dim myListRow As Excel.listRow
'''''''' Initialize objects ''''''''
' Init the userform
' Note: When you initialize it directly with the name of the form, you can access the controls of the userform too
Set myUserForm = oUserForm
' Add the information to the Excel table
Set myListObject = ThisWorkbook.Worksheets(sheetName).ListObjects(tableName)
' Validate if all the information is correct
If myUserForm.cmbEnvironment.Text = vbNullString _
Or myUserForm.cmbHost.Text = vbNullString _
Or myUserForm.cmbIP.Text = vbNullString _
Or myUserForm.cmbAccessible.Text = vbNullString _
Or myUserForm.cmbLast.Text = vbNullString Then
MsgBox "Some fields cannot be blank!", vbCritical, "Data Missing"
Exit Sub
End If
' Add a blank row at the end of the Excel table
Set myListRow = myListObject.ListRows.Add
' Set the information into de excel table
With myListRow
.Range(1) = myUserForm.cmbSchema.Text
.Range(2) = myUserForm.cmbEnvironment.Text
.Range(3) = myUserForm.cmbHost.Text
.Range(4) = myUserForm.cmbIP.Text
.Range(5) = myUserForm.cmbAccessible.Text
.Range(6) = myUserForm.cmbLast.Text
.Range(7) = myUserForm.cmbConfirmation.Text
.Range(8) = myUserForm.cmbProjects.Text
End With
MsgBox "Data Added!"
' Reload the data into the listbox
Call mCode.Read
' Select the last item in the listbox
myUserForm.listHeader.ListIndex = myUserForm.listHeader.ListCount - 1
' Clear control's contents
Call ClearControls ' Note that this is a private procedure inside the mCode module
' Clean up objects
Set myListRow = Nothing
Set myListObject = Nothing
Set myUserForm = Nothing
End Sub
Public Sub Update()
' Comments: Updates a row with the data entered by the user and reloads the listbox inside the userform
' Params :
' Notes : Adapt the initialize variables section
' Created : 2019/01/25 RD www.ricardodiaz.co
' Modified:
' Define objects variables
Dim myUserForm As oUserForm ' Note: you're defining the variable as the class of the userform. This gives you access to the userform's controls later
Dim myListObject As Excel.listObject
Dim myListRow As Excel.listRow
' Define variables
Dim selectedItem As Integer
'''''''' Initialize objects ''''''''
' Init the userform
' Note: When you initialize it directly with the name of the form, you can access the controls of the userform too
Set myUserForm = oUserForm
' Add the information to the Excel table
Set myListObject = ThisWorkbook.Worksheets(sheetName).ListObjects(tableName)
' Define selected row number
selectedItem = myUserForm.listHeader.ListIndex + 1
' Exit if there are no other rows
If selectedItem = 0 Then
MsgBox "There are no rows left!"
Exit Sub
End If
' Initialize the row at the end of the Excel table
Set myListRow = myListObject.ListRows(selectedItem)
' the following section is exactly as the Create procedure, so you theorically could make just one procedure for Create and Update
' Set the information into de excel table
With myListRow
.Range(2) = myUserForm.cmbEnvironment.Text
.Range(3) = myUserForm.cmbHost.Text
.Range(4) = myUserForm.cmbIP.Text
.Range(5) = myUserForm.cmbAccessible.Text
.Range(6) = myUserForm.cmbLast.Text
.Range(7) = myUserForm.cmbConfirmation.Text
.Range(8) = myUserForm.cmbProjects.Text
End With
' Reload the data into the listbox
Call mCode.Read
' Select the updated item in the listbox
myUserForm.listHeader.ListIndex = selectedItem - 1
MsgBox "Data Updated!"
' Clear control's contents
Call ClearControls ' Note that this is a private procedure inside the mCode module
' Clean up objects
Set myListRow = Nothing
Set myListObject = Nothing
Set myUserForm = Nothing
End Sub
Public Sub Delete()
' Comments: Deletes a row with the data entered by the user and reloads the listbox inside the userform
' Params :
' Notes : Adapt the initialize variables section
' Created : 2019/01/25 RD www.ricardodiaz.co
' Modified:
' Define objects variables
Dim myUserForm As oUserForm ' Note: you're defining the variable as the class of the userform. This gives you access to the userform's controls later
Dim myListObject As Excel.listObject
Dim myListRow As Excel.listRow
' Define variables
Dim selectedItem As Integer
'''''''' Initialize objects ''''''''
' Init the userform
' Note: When you initialize it directly with the name of the form, you can access the controls of the userform too
Set myUserForm = oUserForm
' Add the information to the Excel table
Set myListObject = ThisWorkbook.Worksheets(sheetName).ListObjects(tableName)
' Define selected row number
selectedItem = myUserForm.listHeader.ListIndex + 1
' Exit if there are no other rows
If selectedItem = 0 Then
MsgBox "There are no rows left or you didn't select a valid row!"
Exit Sub
End If
If MsgBox("Are you sure you want to delete this row?", vbYesNo + vbQuestion, "Yes") = vbNo Then
Exit Sub
End If
' Initialize the row at the end of the Excel table
Set myListRow = myListObject.ListRows(selectedItem)
' Delete the row
myListRow.Delete
' Reload the data into the listbox
Call mCode.Read
' Select the next item in the listbox
myUserForm.listHeader.ListIndex = WorksheetFunction.Min(selectedItem - 1, myUserForm.listHeader.ListCount) - 1
' Clean up objects
Set myListRow = Nothing
Set myListObject = Nothing
Set myUserForm = Nothing
End Sub
Public Sub ClearList()
' Comments: Clear the listbox
' Define objects variables
Dim myUserForm As oUserForm
' Init the userform
' Note: When you initialize it directly with the name of the form, you can access the controls of the userform too
Set myUserForm = oUserForm
myUserForm.listHeader.Clear
End Sub
Public Sub LoadControls()
' Comments: Loads the selected row's data into the controls
' Define objects variables
Dim myUserForm As oUserForm
Dim selectedItem As Integer
' Init the userform
' Note: When you initialize it directly with the name of the form, you can access the controls of the userform too
Set myUserForm = oUserForm
' Get the row of the selected item in the listbox
selectedItem = myUserForm.listHeader.ListIndex
' Set the control's text to each column of the selected item
myUserForm.cmbSchema.Value = myUserForm.listHeader.List(selectedItem, 0)
myUserForm.cmbEnvironment.Value = myUserForm.listHeader.List(selectedItem, 1)
myUserForm.cmbHost.Value = myUserForm.listHeader.List(selectedItem, 2)
myUserForm.cmbIP.Value = myUserForm.listHeader.List(selectedItem, 3)
myUserForm.cmbAccessible.Value = myUserForm.listHeader.List(selectedItem, 4)
myUserForm.cmbLast.Value = myUserForm.listHeader.List(selectedItem, 5)
myUserForm.cmbConfirmation.Value = myUserForm.listHeader.List(selectedItem, 6)
myUserForm.cmbProjects.Value = myUserForm.listHeader.List(selectedItem, 7)
' Clean up objects
Set myUserForm = Nothing
End Sub
Public Sub ClearControls()
' Comments: Reset controls to empty strings
' Define objects variables
Dim myUserForm As oUserForm
' Init the userform
' Note: When you initialize it directly with the name of the form, you can access the controls of the userform too
Set myUserForm = oUserForm
' Clear the controls
myUserForm.cmbSchema.Text = vbNullString
myUserForm.cmbEnvironment.Text = vbNullString
myUserForm.cmbHost.Text = vbNullString
myUserForm.cmbIP.Text = vbNullString
myUserForm.cmbAccessible.Text = vbNullString
myUserForm.cmbLast.Text = vbNullString
myUserForm.cmbConfirmation.Text = vbNullString
myUserForm.cmbProjects.Text = vbNullString
' Clean up objects
Set myUserForm = Nothing
End Sub
Public Sub FilterList(oLb As MSForms.ListBox, strFiltro As String)
Dim columnCounter As Integer
Dim listString As String
Dim rowCounter As Integer
oLb.ListIndex = -1
' Read the whole list
Call mCode.Read
' Remove unmatching items
For rowCounter = oLb.ListCount - 1 To 0 Step -1
listString = vbNullString
' Concat the list columns values in one string
For columnCounter = 0 To oLb.columnCount
listString = listString & oLb.Column(columnCounter, rowCounter)
Next columnCounter
If InStr(1, listString, strFiltro, 1) = 0 Then
' Remove items that don't match
oLb.RemoveItem rowCounter
End If
Next
End Sub
这篇关于如何在Excel VBA中创建一个搜索过滤器,以便在键入单词时在列表框中显示搜索结果?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!