【问题标题】:Excel Userform to search in textbox and filter in a listboxExcel Userform 在文本框中搜索并在列表框中进行过滤
【发布时间】:2019-02-07 03:21:30
【问题描述】:

您好,我正在寻求帮助,我在 Excel 用户窗体中有一个文本框和一个列表框,除了一个小的细节外,它完美无缺:只要结果出现在列表框中,它们就代表所有列中的搜索。但是,当我在文本框中键入时,第一列是隐藏的,如何确保该列在搜索期间保持可见? 提前致谢

代码如下:

Private Sub UserForm_Initialize()

End Sub

Private Sub TextBox1_Change()

With Sheets("Sheet1")

lr = .Range("A" & Rows.Count).End(xlUp).Row
ReDim arr(1 To lr - 1)
ReDim sn(1 To lr - 1, 1 To 13)
For i = 1 To UBound(arr)
    arr(i) = .Range("A" & i + 2) & " " & .Range("B" & i + 2) & " " & .Range("C" & i + 2) & " " & .Range("D" & i + 2) & " " & .Range("E" & i + 2) & " " & .Range("F" & i + 2)
    If InStr(1, arr(i), TextBox1) > 0 Then
        j = j + 1
        For X = 2 To 8
            sn(j, X - 1) = .Cells(i + 2, X)
        Next
    End If
Next
ListBox1.List = sn

End With

End Sub 

【问题讨论】:

标签: excel vba search listbox userform


【解决方案1】:

一致数组方法

在创建过滤列表框列表时,您的原始代码显示了 arrayrange 循环的混合。为了通过仅循环数组 *) 在这里更加一致,您可以按如下方式优化您的代码(例如,通过 Instr 使用相同的匹配检查):

用户表单事件过程TextBox1_Change()

Private Sub TextBox1_Change()
  Const STARTROW = 3
  Dim i&, iCnt&, r&, c&                                                       ' array counters for "rows" and "columns"
  Dim sn, tmp                                                                 ' variant 2-dim 1-based arrays
  With Sheets("Sheet1")
      iCnt = .Range("A" & Rows.Count).End(xlUp).Row - STARTROW + 1            ' items counter
      ReDim sn(1 To iCnt, 1 To 13)                                            ' provide for filtered data array
      For i = 1 To iCnt
         'assign current data row to 2-dim 1-based temporary array
          tmp = .Range("A" & (i + 2) & ":F" & (i + 2))                        ' current data row (c.f. OP)
         'compare search string with concatenated data string from current row
          If InStr(1, concat(tmp), TextBox1.Text) > 0 Then                    ' check occurrence e.g. via Instr
              r = r + 1                                                       ' new rows counter
              For c = 1 To UBound(tmp, 2)                                     ' col counter
                  sn(r, c) = tmp(1, c)                                        ' collect found row data
              Next
          End If
      Next
      ListBox1.List = sn                                                      ' assign array to .List property
  End With

End Sub

上述事件过程调用的辅助函数concat()

Private Function concat(ByVal arr, Optional ByVal delim$ = " ") As String
' Purpose: build string from 2-dim array row, delimited by 2nd argument
' Note:    concatenation via JOIN needs a "flat" 1-dim array via double transposition
  concat = Join(Application.Transpose(Application.Transpose(arr)), delim)
End Function

备注

*) 通过 VBA 循环遍历一个范围总是很耗时,所以用数组来代替。

您可能还对以下演示列表框Column property 使用的解决方案感兴趣。通过玩这个可以帮助您删除列表框中多余的空白行。

【讨论】:

  • 你好 T.M.感谢您抽出时间回答我的问题,您提供的代码完美无缺,它解决了我的问题能力 :) 所以感谢像 stackoverflow 这样的网站和像你这样的贡献者,我能够以我喜欢的方式实现我的用户表单。非常感谢。
  • 不客气。 - 如果您不了解代码行的特殊构造,并且在帮助参考或其他 SO 站点中找不到简单的帮助,请随时询问。
  • 您好,我现在使用搜索选项和 T.M. 提供的代码。它工作得很好,就像我需要它工作一样,我还有一个问题:是否可以修改代码以查找单元格值,无论它们是大写还是小写?
  • 这很简单(总是先查看帮助:-):只需将参数vbTextCompare1 添加到Instr 函数中,如下所示:If InStr(1, concat(tmp), TextBox1.Text, vbTextCompare) > 0。默认情况下,通过 vbBinaryCompare (= 0) 搜索值,当此参数没有像 OP 中那样明确指出时,区分大小写。
  • 知道了,谢谢 T.M.周末愉快。
猜你喜欢
  • 2018-03-13
  • 2015-06-19
  • 2022-08-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-10
相关资源
最近更新 更多