powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft Access [игнор отключен] [закрыт для гостей] / Отоварьте классом !
1 сообщений из 1, страница 1 из 1
Отоварьте классом !
    #32182640
Пытаюсь найти какое либо решение в области инкрементального поиска.
Подскажите кто чего может - а заодно и свои идеи подкиньте.
Задача - создать поисковичек в БД. - причем в любой форме. - хотя бы даже в списке, Но вот выдержит ли список базу в 40 тыс записей.. Отсюда и пляшем.


Для понятности - пример из Гетца.
Создаем Class Modules с именем IncrementalSearch.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
316.
317.
318.
319.
320.
321.
322.
323.
324.
325.
326.
327.
328.
329.
330.
331.
332.
333.
334.
335.
336.
337.
338.
339.
340.
341.
342.
343.
344.
345.
346.
347.
348.
349.
350.
351.
352.
353.
354.
355.
356.
357.
358.
359.
360.
361.
362.
363.
364.
365.
366.
367.
368.
369.
370.
371.
372.
373.
374.
375.
376.
377.
378.
379.
380.
381.
382.
383.
384.
385.
386.
387.
388.
389.
390.
391.
392.
393.
394.
395.
396.
397.
398.
399.
400.
401.
402.
403.
404.
405.
406.
407.
408.
409.
410.
411.
412.
413.
414.
415.
416.
417.
418.
419.
420.
Option Compare Database
Option Explicit

' From Access 2002 Desktop Developer's Handbook
' by Litwin, Getz, and Gunderloy. (Sybex)
' Copyright  2001 .  All rights reserved.

' Incremental Search Class

' Set this constant to False to
' use ADO instead of DAO.
#Const USEDAO = True

Private WithEvents mlst As ListBox
Private WithEvents mtxt As TextBox

Private Enum ObjectType
    otNone = 0
    otTable = 1
    otDynaset = 2
End Enum
Private mot As ObjectType

#If USEDAO Then
Private mdb As DAO.Database
Private mrst As DAO.Recordset
#Else
Private mrst As ADODB.Recordset
#End If

Public DisplayField As String
Public BoundField As String
Public Index As String

Public Property Set TextBox(txt As TextBox)
    Set mtxt = txt
    mtxt.OnChange = "[Event Procedure]"
    mtxt.OnLostFocus = "[Event Procedure]"
End Property

Public Property Get TextBox() As TextBox
    Set TextBox = mtxt
End Property

Public Property Set ListBox(lst As ListBox)
    Set mlst = lst
    mlst.AfterUpdate = "[Event Procedure]"
#If USEDAO Then
    Call SetupRstDAO
#Else
    Call SetupRstADO
#End If
End Property

Public Property Get ListBox() As ListBox
    Set ListBox = mlst
End Property

#If USEDAO Then
Private Sub SetupRstDAO()
    
    Dim qdf As DAO.QueryDef
    Dim prm As DAO.Parameter
    Dim strSource As String
    
    ' We can handle:
    ' * Tables
    ' * Queries with no parameters
    ' * Queries with resolvable parameters.
    ' * SQL SELECT strings with no parameters.
    ' * SQL SELECT strings with resolvable parameters.
    
    On Error Resume Next
    
    strSource = mlst.RowSource
    
    ' Attempt to open a table-type recordset.
    Set mdb = CurrentDb()
    Set mrst = mdb.OpenRecordset(strSource, dbOpenTable)
    
    ' If there wasn't an error, you managed
    ' to open a table-type recordset, and all is well.
    ' Now attempt to assign an index.
    If Err =  0  Then
        mrst.Index = Index
        If Err =  0  Then
            mot = otTable
            GoTo ExitHere
        End If
    End If

    ' You're only here if you didn't manage to open a table-type
    ' recordset and set its index.
    Err.Clear
    Set qdf = mdb.QueryDefs(strSource)
    If Err.Number <>  0  Then
        ' This isn't a querydef, but probably
        ' a SQL string. This may have parameters,
        ' so try one more thing: create a new
        ' querydef, so you can evaluate its
        ' parameters.
        Err.Clear
        Set qdf = mdb.CreateQueryDef( "", strSource)
    End If
    
    ' Fill in parameter values, if possible.
    ' This will still fail for parameters that
    ' require user input.
    If Err.Number = 0 Then
        For Each prm In qdf.Parameters
            prm.Value = Eval(prm.Name)
        Next prm
        Set mrst = qdf.OpenRecordset(dbOpenDynaset)
    End If
    
    If Err.Number = 0 Then
        mot = otDynaset
    Else
        mot = otNone
    End If
    
ExitHere:
    Err.Clear
End Sub

#Else
Private Sub SetupRstADO()
    ' Open a recordset, based on the RowSource of the
    ' specified listbox.
    ' On Error Resume Next
    Dim cmd As ADODB.Command
    Dim intCount As Integer
    Dim strSource As String
    
    ' We can handle:
    ' * Tables
    ' * Queries with no parameters
    ' * Queries with resolvable parameters.
    ' * SQL SELECT strings with no parameters.
    ' * SQL SELECT strings with resolvable parameters,
    '   except with DAO wildcards.
    
    ' IMPORTANT NOTE: ADO understands " % " and " _ "
    ' as wildcard characters. Without parsing the SQL
    ' ourselves, we can't make Jet wildcards ("*" and "?")
    ' work here. Basically, if you supply SQL as the RowSource
    ' property for the list box, you cannot use "*" or "?".
    ' The problem is that Access can't handle "%" and "_"
    ' as wildcards, and ADO can't handle "*" and "?".
    ' If you use the query processor (that is, use a
    ' predefined query) as your RowSource, this won't be
    ' a problem -- Access takes care of the conversion for you.
    ' Although you COULD rewrite this code to handle
    ' this (replacing "*" and "?" in the WHERE clause)
    ' it seems like overkill. Just use a table, a query, or
    ' a simple SQL string as the RowSource and you'll be all set.
    
    ' Inline error handling is simpler here.
    On Error Resume Next
        
    Set mrst = New ADODB.Recordset
    mrst.Source = mlst.RowSource
    mrst.CursorType = adOpenStatic
    mrst.LockType = adLockOptimistic
    Set mrst.ActiveConnection = CurrentProject.Connection
        
    ' Attempt to open a table directly.
    mrst.Open Options:=adCmdTableDirect
    If Err.Number <> 0  Then
        ' That didn't succeed. Now try
        ' using adCmdTable, and this may
        ' require satisfying parameters.
        Err.Clear
        mrst.Open Options:=adCmdTable
        ' You may need to satisfy parameters. Do it here?
        If Err.Number <> 0 Then
            If Err.Number = -2147217904 Then
                Err.Clear
                Set mrst = HandleParametersADO(ct:=adCmdTable)
            End If
        End If
    End If
    If Err.Number <> 0 Then
        ' That didn't succeed. Now try
        ' using adCmdTable, and this may
        ' require satisfying parameters.
        Err.Clear
        mrst.Open Options:=adCmdText
        ' You may need to satisfy parameters. Do it here?
        If Err.Number <>  0  Then
            If Err.Number = - 2147217904  Then
                Set mrst = HandleParametersADO(ct:=adCmdText)
            Else
                GoTo HandleErrors
            End If
        End If
    End If
                 
    If Len(Index) >  0  Then
        ' Just go ahead and try.
        Err.Clear
        mrst.Index = Index
        If Err.Number = 0 Then
            mot = otTable
        Else
            ' Oops. Can't set the Index
            ' property. Therefore, clear
            ' out the Index string
            ' so later code knows there's
            ' no index in use.
            mot = otDynaset
        End If
    Else
        mot = otDynaset
    End If
    Err.Clear
    If mrst.State = adStateClosed Then
        mot = otNone
    End If

ExitHere:
    Exit Sub
    
HandleErrors:
    mot = otNone
    Err.Raise Err.Number, _
     "IncrementalSearch.SetupRstADO ", Err.Description
End Sub

Private Function HandleParametersADO( _
 Optional ct As CommandTypeEnum = adCmdTableDirect) _
 As ADODB.Recordset
    ' First, check to see the the row source
    ' has any parameters. This won't work
    ' for text you type directly into
    ' the RowSource property, but it will work
    ' for queries that have parameters based
    ' on form values. If you want to support
    ' generalized queries that have other types
    ' of parameters, you'll need to add support
    ' for that here.
    
    Dim cmd As ADODB.Command
    Dim intCount As Integer
    Dim prm As ADODB.Parameter
        
    On Error GoTo HandleErrors
        
    ' Open a new Command object.
    Set cmd = New ADODB.Command
    Set cmd.ActiveConnection = CurrentProject.Connection
    cmd.CommandText = " ( " & mlst.RowSource & " ) "
    cmd.CommandType = ct
    intCount = cmd.Parameters.Count
    
    ' If there are any parameters,
    ' evaluate them now.
    If intCount > 0  Then
        For Each prm In cmd.Parameters
            prm.Value = Eval(prm.Name)
        Next prm
        ' If you've set up a Command
        ' object like this, you cannot
        ' use the Index, or the Seek method later.
        ' Indicate that this is a dynaset-like
        ' thing.
        mot = otDynaset
    End If
    Set HandleParametersADO = cmd.Execute
    
ExitHere:
    Exit Function
    
HandleErrors:
    Select Case Err.Number
        Case Else
            Err.Raise Err.Number, _
             "IncrementalSearch.HandleParametersADO ", _
             Err.Description
    End Select
    Resume ExitHere
End Function
#End If

Private Sub Class_Terminate()
    On Error Resume Next
    mrst.Close
    Set mrst = Nothing
    Set mtxt = Nothing
    Set mlst = Nothing
End Sub

Private Sub mlst_AfterUpdate()
    mtxt.Value = mlst.Value
End Sub

Private Sub mtxt_Change()
    Dim strFilter As String
    Dim strTemp As String
    Dim strDelimiter As String
    
    On Error GoTo HandleErrors
    
    DoCmd.Hourglass True
    If Len(BoundField) = 0  Then
        BoundField = DisplayField
    End If
    If Len(mtxt.Text) >  0  Then
        ' Is there text in the text box?
        ' If so, filter based on that text.
#If USEDAO Then
        Select Case mot
            Case otNone
                ' Nothing to do!
                GoTo ExitHere
            Case otDynaset
                strFilter = DisplayField & _
                 " >= " & FixQuotes(mtxt.Text)
                mrst.FindFirst strFilter
            Case otTable
                ' If there is an index set,
                ' you can use Seek.
                mrst.Seek ">=", mtxt.Text
        End Select
#Else
        Select Case mot
            Case otNone
                ' Nothing to do!
                GoTo ExitHere
            Case otDynaset
                If Len(strDelimiter) =  0  Then
                    strDelimiter = "'"
                End If
TryAgain:
                strFilter = DisplayField & _
                 " >= " & FixQuotes(mtxt.Text, strDelimiter)
                mrst.Filter = strFilter
            Case otTable
                ' If there is an index set,
                ' you can use Seek.
                mrst.Seek mtxt.Text, adSeekAfterEQ
        End Select
#End If
        ' Did we find any rows at all?
        ' If so, set the value of the
        ' list box to be the value you found.
        If Not mrst.EOF Then
            mlst.Value = mrst.Fields(BoundField)
        End If
        
#If USEDAO Then
        ' Nothing special to do, if you're using DAO.
#Else
        ' Reset the filter for next time.
        mrst.Filter = vbNullString
#End If
    Else
        ' If no text, then
        ' move to the first row,
        ' set the value to be that value
        ' (so the list box scrolls to the top)
        ' and then set the value to be Null,
        ' so nothing's selected.
        mrst.MoveFirst
        mlst.Value = mrst.Fields(BoundField)
        mlst.Value = Null
    End If

ExitHere:
    DoCmd.Hourglass False
    Exit Sub

HandleErrors:
    DoCmd.Hourglass False
    Select Case Err.Number
#If USEDAO Then
        ' No special errors, for DAO.
#Else
        Case 3001   ' The stupid ADO quotes problem.
            ' ADO can't handle parsing this stupid thing.
            ' What to do?
            
            ' If the delimiter is currently  "'"
            ' then try " # ". This might work. If there's both
            ' two apostrophes and a " # " in there, you're in trouble.
            If strDelimiter = "'"  Then
                strDelimiter =  "#" 
                Resume TryAgain
            Else
                MsgBox  "ADO is unable to parse the expression you entered." 
                Resume ExitHere
            End If
#End If
        Case Else
            Err.Raise Err.Number, _
              "IncrementalSearch.TextChange" , Err.Description
            Resume
    End Select
    Resume ExitHere
End Sub

Private Function FixQuotes(strValue As String, _
 Optional strDelimiter As String = "'") As String
    ' In:
    '   strValue:   Value to fix up.
    '   strDelimiter: (Optional) Delimiter to use.
    ' Out:
    '   Return value: the text, with delimiters fixed up.
    
    FixQuotes = _
     strDelimiter & _
     Replace(strValue, strDelimiter, strDelimiter & strDelimiter) & _
     strDelimiter
End Function

Private Sub mtxt_LostFocus()
    On Error Resume Next
    mtxt.Value = mlst.Value
End Sub




Далее для формы

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
Option Compare Database
Option Explicit

' From Access 2002 Desktop Developer's Handbook
' by Litwin, Getz, and Gunderloy. (Sybex)
' Copyright  2001 .  All rights reserved.

Private mis As IncrementalSearch

Private Sub Form_Load()
    Set mis = New IncrementalSearch
    mis.DisplayField =  "Company" 
    
    ' BoundField and Index
    ' are optional. Index will only
    ' have an effect if the application
    ' can make use of it (if you ask
    ' to read data from a table directly).
    ' Use  "PrimaryKey"  if you want to specify
    ' the primary key index, and you've never
    ' changed its name.
    ' BoundField allows you to
    ' have a field to which the list box
    ' is bound, but isn't the display field.
    ' The BoundField property must match the
    ' field indexed in the Index property.
    
    ' You should set these properties
    ' before you set the ListBox property,
    ' which hooks up all the data.
    mis.BoundField =  "Company" 
    mis.Index =  "Company" 
    
    Set mis.ListBox = lstIncSrch
    Set mis.TextBox = txtIncSrch
    
End Sub

Private Sub Form_Unload(Cancel As Integer)
    ' This isn't really necessary, but can't hurt.
    Set mis = Nothing
End Sub




На форму соответсвенно "наложить" (не поймите привратно)

label - txtIncSrch
list - lstIncSrch


Какие еще варианты есть ?
Метод хорош но !!.. Ограниечение в записях. и .. скорость обработки
!!
...
Рейтинг: 0 / 0
1 сообщений из 1, страница 1 из 1
Форумы / Microsoft Access [игнор отключен] [закрыт для гостей] / Отоварьте классом !
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]