通过文本框搜索以自动更新列表框条目 [英] Search via textbox to auto-update listbox entries

查看:59
本文介绍了通过文本框搜索以自动更新列表框条目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在用户窗体的列表框中实现搜索功能,以便更好地查看许多列,但是不幸的是我找不到解决方案.

I would like to implement a search function in a listbox in a userform getting a better view of the many columns and unfortunately I can't find a solution.

最佳解决方案是,如果我可以在文本框中搜索任何行内容(最多12列,其中包含名称,ID,位置,组织等数据),列表框将自动更新以显示所有内容匹配条目.

The optimal solution would be, if I could search in a textbox for any row content (up to 12 columns containing data like e.g. name, ID, position, organization, ...) and the listbox would automatically update itself showing all matching entries.

UserForm_Initialize 中,我按如下所示填充了列表框:

In UserForm_Initialize I filled the listbox as follows:

Private Sub UserForm_Initialize()
 
With UserForm1
  .StartUpPosition = 1
  .Top = 1
  .Left = 1
End With
 
Dim last As Integer
         last = ActiveSheet.Cells(Rows.Count, 1).End(xlUp).row + 1
 
ListBox1.ColumnCount = 12
ListBox1.ColumnHeads = True
ListBox1.ColumnWidths = "30;50;200;60;30;110;110;90;50;40;50;80;60"
ListBox1.RowSource = "A2:M" & last
 
End Sub

我想象过根据 Textbox1 中的输入,搜索功能可以过滤列表框.

I imagined the search function to filter the listbox depending on the input in Textbox1.

经过长时间的研究和考虑(不幸的是,我是绝对的vba业余爱好者),创建了以下代码:

After long research and consideration (unfortunately I am an absolute vba amateur) the following code was created:

Private Sub TextBox1_Change()
    Dim i As Long
    On Error Resume Next
    Me.TextBox1.Text = StrConv(Me.TextBox1.Text, vbProperCase)
    Me.ListBox1.Clear
    For i = 2 To Application.WorksheetFunction.CountA(ActiveSheet.Range("A:A"))
        For x = 1 To 12
            a = Len(Me.TextBox1.Text)
            If Left(ActiveSheet.Cells(i, x).Value, a) = Me.TextBox1.Text And Me.TextBox1.Text <> "" Then
                Me.ListBox1.AddItem ActiveSheet.Cells(i, x).Value
                For c = 1 To 12
                    Me.ListBox1.List(ListBox1.ListCount - 1, c) = ActiveSheet.Cells(i, c + 1).Value
                Next c
            End If
        Next x
    Next i
End Sub

我的问题:有没有人有一个更聪明/更精简的解决方案,或者也许可以帮助使我的代码正常工作,因为当前我在执行时遇到 runtime error'9'.

My question: Does anyone have a smarter / leaner solution or could maybe help to get my code working as currently I get the runtime error '9' on execution.

推荐答案

通过搜索项过滤来显示列表框

在原始帖子中出现了一个 set 个问题,因此您必须考虑几个点.

In the original post occurs a set of issues, so you have to consider several points.

由于其中一些人经常被当作纯粹的方法性问题而被问到,因此该汇编可能有助于获得更全面的了解.

As some of them get asked frequently as pure methodical questions, this compilation might help to gain a more overall view besides.

  • 一个重要的问题是,对于要显示的每个元素,都使用 .AddItem 方法,仅当您尝试显示更多列时,列表框的列数才默认为 10列
    因此会产生索引错误.

  • An important issue is that using the .AddItem method for each single element to be displayed, the listbox'es column count defaults to 10 columns only whereas you try to display more columns
    thus raising an indexing error.

如果您坚持使用重复的 .AddItem 方法,您可以使用解决方法来克服10列限制:临时将数组分配给列表框就足够了将列数增加到相应的数组列数.

If you stick to the repetitive .AddItem method, you may use a workaround to overcome the 10 columns limitation: a temporary array assignment to the list box is sufficient to increase the number of columns to the corresponding number of array columns.

此外,并且afaik不可能 自己清除或过滤列表框数据,如果它们受 .RowSource 属性的约束.因此,有必要不使用 .RowSource ,并以编程方式添加数据.
-或者,您也可以将 .RowSource 基于预先过滤的范围(例如,在隐藏的工作表中).

Furthermore and afaik it's not possible to clear or filter listbox data themselves, if they are bound by the .RowSource property. Therefore it would be necessary to do without .RowSource and to add data programmatically.
- Alternatively you might base .RowSource on a pre-filtered range (e.g. in a hidden sheet).

这意味着进一步的缺点:无法显示字幕只需将 .ColumnHeads 属性设置为 True ,而无需设置 .RowSource .--这就是为什么我通过在下面的答案中将heads作为第一个数据行来选择某种折衷的原因.

This means a further drawback: there's no way to display captions simply by setting the .ColumnHeads property to True without a set .RowSource. - That's why I chose sort of compromise by including heads as first data row in the answer below .

请注意,如果您在同一过程中将文本框字符串内容更改为适当的Case,则将再次调用 TextBox1_Change 事件.因此,您需要通过一些转义代码行来防止重复输入数据.

Note that the TextBox1_Change event will/would be called a second time if you change the textbox string content to proper Case within the same procedure. Therefore you need to prevent redoubled data entries by some escape code lines.

此外,找到给定搜索项的第一个匹配项并防止不必要的循环(例如,通过设置布尔变量 found )就足够了.

Furthermore it suffices to find the first occurrence of the given search item and to prevent unnecessary loops (e.g. by setting a boolean variable found).

以下示例代码演示了如何处理试图解决的所示问题尽可能遵循原始方法(即使通过VBA遍历 range 而不是 array 来获取更多数据集也很耗时,而且您的命名约定可能更喜欢使用比更有意义的变量名> x c ):

The following example code demonstrates how to handle the shown issues trying to follow the original approach as close as possible (even if looping through a range instead of an array by means of VBA can be time consuming for greater data sets and your naming convention could prefer more meaningful variable names than x or c):

Option Explicit                 ' declaration head of Userform code module

Private Sub TextBox1_Change()
    Dim ws as WorkSheet             ' declare data sheet as WorkSheet
    set ws = Sheet1             ' << define data sheet's Code(Name)
    With Me.ListBox1
        .Clear                                  ' remove any prior items from listbox
        .List = ws.Range("A1:M1").Value2        ' display head & provide for sufficient columns
    End With
    If Me.TextBox1.Text = "" Then Exit Sub      ' no further display, so escape
    Dim SearchText As String
    SearchText = StrConv(Me.TextBox1.Text, vbProperCase)
    If Me.TextBox1.Text <> SearchText Then      ' avoid double call of Change event
        Me.TextBox1.Text = SearchText           ' display ProperCase
        Exit Sub                                ' force 2nd call after text change
    End If
    With ws
        Dim i As Long
        For i = 2 To .Cells(.Rows.Count, 1).End(xlUp).Row
            Dim lngth As Long: lngth = Len(SearchText)
            Dim x As Long
            For x = 1 To 12                         ' range columns
                Dim found As Boolean
                If Left(.Cells(i, x).Value, lngth) = SearchText Then
                    Me.ListBox1.AddItem .Cells(i, x).Value
                    Dim c As Long
                    For c = 1 To 12
                        Me.ListBox1.List(ListBox1.ListCount - 1, c) = .Cells(i, c + 1).Value
                    Next c
                    found = True                    ' check for 1st occurrence avoiding redundant loops
                End If
                If found Then
                    found = False
                    Exit For                        ' 1st finding suffices
                End If
            Next x
        Next i
    End With
End Sub

Private Sub UserForm_Initialize()

With Me
  .StartUpPosition = 1
  .Top = 1
  .Left = 1
End With

With Me.ListBox1
    '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    'assign 2-dim array to .List property
    'to overcome default column count of 10 only!!
    '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    .Clear
    'needed to overcome default limit of 10 columns only!
    .List = Sheet1.[A1:M1].Value2          ' only column heads (i.e. 1 row) to start with
   '.RemoveItem 1                          ' (delete eventually if no head needed at all)
    .ColumnCount = 13
    .ColumnWidths = "30;50;100;60;30;110;110;90;50;40;50;80;60"
End With
  
End Sub

这篇关于通过文本框搜索以自动更新列表框条目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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