【发布时间】:2021-06-16 15:42:56
【问题描述】:
我有一个用于搜索值(字母数字)的用户表单。它运作良好。但需要很长时间,有时会挂起 excel 程序。
在我的用户表单中,有三个文本框和三个列表框。
为了搜索我的查询,我可以在任何文本框中输入任何内容。并且来自三个 Listbox 的所有数据都经过过滤并相互依赖。 例如:在用户窗体初始化时,每个列表框显示 100 个项目列表。 当我在任何搜索框(文本框)中输入任何内容时,项目将从所有列表框中过滤掉。
(对不起,我的英语和语法可能很弱。)
试着用这张图来理解。
有什么方法可以提高我的搜索速度?
我的代码如下:-
Option Explicit
Private Sub UserForm_Initialize()
Call loadList
Me.tbox_srch_ID.SetFocus
End Sub
Private Sub tbox_srch_ID_Keyup(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
Me.tbox_srch_Word.Value = ""
Call loadList
End Sub
Private Sub tbox_srch_Word_Keyup(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
Me.tbox_srch_Party.Value = ""
Call loadList
End Sub
Private Sub tbox_srch_Party_Keyup(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
Me.tbox_srch_Word.Value = ""
Call loadList
End Sub
Sub loadList()
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Application.EnableEvents = False
Dim baseArray() As Variant
Dim resultArray() As Variant
Dim IDArray() As Variant
Dim wordArray() As Variant
Dim PartyArray() As Variant
Dim counter As Long, i As Long
'On Error Resume Next
'Clear current list boxes
Me.lbox_ID.Clear
Me.lbox_Word.Clear
Me.lbox_Party.Clear
'Assign source list to an array, unfiltered
baseArray = Sheet2.Range("C2:E100001")
'Set a default value to filter match counter
counter = 0
'Iterate through the source list, if search term is found add item to result array
For i = LBound(baseArray) To UBound(baseArray)
If ((InStr(1, baseArray(i, 1), Me.tbox_srch_ID.Value, vbTextCompare) > 0 And Me.tbox_srch_Word.Value = "" And Me.tbox_srch_Party.Value = "") Or _
(InStr(1, baseArray(i, 2), Me.tbox_srch_Word.Value, vbTextCompare) > 0 And Me.tbox_srch_ID.Value = "" And Me.tbox_srch_Party.Value = "") Or _
(InStr(1, baseArray(i, 3), Me.tbox_srch_Party.Value, vbTextCompare) > 0 And Me.tbox_srch_ID.Value = "" And Me.tbox_srch_Word.Value = "")) Then
counter = counter + 1
ReDim Preserve resultArray(1 To 3, 1 To counter)
resultArray(1, counter) = baseArray(i, 1)
resultArray(2, counter) = baseArray(i, 2)
resultArray(3, counter) = baseArray(i, 3)
End If
Next i
'If there is at least one match, separate result array to two arrays and load them to the listboxes
If counter > 0 Then
ReDim IDArray(1 To UBound(resultArray, 2), 1 To 1)
ReDim wordArray(1 To UBound(resultArray, 2), 1 To 1)
ReDim PartyArray(1 To UBound(resultArray, 2), 1 To 1)
For i = LBound(resultArray, 2) To UBound(resultArray, 2)
IDArray(i, 1) = resultArray(1, i)
wordArray(i, 1) = resultArray(2, i)
PartyArray(i, 1) = resultArray(3, i)
Next i
Me.lbox_ID.List = IDArray
Me.lbox_Word.List = wordArray
Me.lbox_Party.List = PartyArray
End If
On Error GoTo 0
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
【问题讨论】:
-
在您的文本中您说 100 但源范围是 10 万条记录?现在搜索需要多长时间?
-
真的有 100,000 行数据,还是只是抓取了超出需要的数据?如果你找到
lastRow,你可以使用一个更小的数组来提高速度。此外,如果您将数据预加载到Dictionary中,您可以保存几乎所有搜索该值的迭代,至少在 Date 列中。 -
在每个
Keyup中清除一个其他文本框 - 为什么只清除一个而不是其他两个? -
先生,我以 100 为例。而且我只有基本的VBA知识和英语知识。所以也许我无法澄清我的问题。
-
您可能要考虑使用 ADODB:查询电子表格并在
recordset中获取数据(单次读取),然后使用recordset的filter方法过滤为用户类型。这将需要使用 ADO 和使用 SQL 重新编码所有内容 - 包括读取、写入列表、构建过滤器字符串、用于连接的 ADO 样板等,但它可能会更快。
标签: vba