如何在Excel VBA中创建一个搜索过滤器,以便在键入单词时在列表框中显示搜索结果? [英] How to make a Search Filter in Excel VBA that displays search result in the ListBox while typing a word?

查看:109
本文介绍了如何在Excel VBA中创建一个搜索过滤器,以便在键入单词时在列表框中显示搜索结果?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我现在正在尝试在用户窗体中进行为期数周的高级搜索,在输入值时它会过滤并在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

预期结果:

  1. 用户在ComboBox中键入单词(由于下拉菜单功能,我选择了ComboBox作为过滤器)
  2. 用户输入时,它将显示结果到列表框.

问题是我不知道如何创建这种搜索过滤器,即使我的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-b​​asic-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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆