Ik heb op't www een mooie class gevonden die een autocomplete voor een textveld regeld vanuit een listbox die de class zelf aanmaakt.
Het nadeel is dat de class geen rekening gehouden heeft met de ItemData property die, indien de waardes vanuit een database gevuld worden, de corresponderende ID's meeneemt.
Aangezien ik niet zo'n ervaring heb met classes
maar wel graag die property zou willen toevoegen vraag ik jullie om tips.
De class werkt in princiepe hetzelfde als een gewone listbox dus in je form kun je gebruik maken van .addItem maar dus niet van .ItemData.
Zouden jullie mij op weg kunnen helpen dit voor elkaar te krijgen?
Bedankt voor jullie medewerking, de code staat hieronder
Het nadeel is dat de class geen rekening gehouden heeft met de ItemData property die, indien de waardes vanuit een database gevuld worden, de corresponderende ID's meeneemt.
Aangezien ik niet zo'n ervaring heb met classes
De class werkt in princiepe hetzelfde als een gewone listbox dus in je form kun je gebruik maken van .addItem maar dus niet van .ItemData.
Zouden jullie mij op weg kunnen helpen dit voor elkaar te krijgen?
Bedankt voor jullie medewerking, de code staat hieronder
code:
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
| Option Explicit
'Beware, the length of strings used is determined by the following const. For use of longer
'words or sentences increase the const first
Private Const StringL As Long = 20
Private Const MaxItemsInDropdown As Long = 10
Private Const DropdownViewTime = 3 'seconds the dropdown stays visible. Set to 0 to keep visible
Private WithEvents TB As TextBox
Private WithEvents DropDown As ListBox
Private DropDownCreated As Boolean, TimerStart!, LineHeight%, blnCancelTimer As Boolean
Private NumberOfItems As Long, sItems As String, LastFill As String, UseDropDown As Boolean
Public OnlyAllowList As Boolean
Property Let UseDropDownList(B As Boolean)
UseDropDown = B
If B Then
CreateDropDown
ElseIf DropDownCreated Then
RemoveDropDown
End If
End Property
Property Get UseDropDownList() As Boolean
UseDropDownList = UseDropDown
End Property
Property Set AutoCompleteTextbox(T As TextBox)
If DropDownCreated And Not TB Is Nothing Then
If Not TB.Parent Is T.Parent Then RemoveDropDown
End If
Set TB = T
LastFill = ""
TB_GotFocus
CreateDropDown
End Property
Sub AddItems(ParamArray Items())
Dim varX
For Each varX In Items
AddItem CStr(varX)
Next
End Sub
Private Sub RemoveDropDown()
If Not DropDownCreated Then Exit Sub
Dim sName As String
sName = DropDown.Name
DropDown.Clear
Set DropDown = Nothing
TB.Parent.Controls.Remove sName
DropDownCreated = False
blnCancelTimer = True
End Sub
Private Sub CreateDropDown()
If Not UseDropDown Then Exit Sub
If Not DropDownCreated Then Set DropDown = TB.Parent.Controls.Add("vb.listbox", "lstDropDownAutoC1")
If Not TB Is Nothing Then
With DropDown
.Move TB.Left, TB.Top + TB.Height, TB.Width, 1000
.ZOrder
.TabStop = False
.BackColor = TB.BackColor
Dim F As Font
Set F = .Parent.Font
Set .Parent.Font = TB.Font
Set .Font = TB.Font
LineHeight = .Parent.TextHeight("atpPjkKyX") + 30
Set .Parent.Font = F
End With
End If
DropDownCreated = True
End Sub
Private Sub HideDropDown()
If DropDownCreated Then DropDown.Visible = False
End Sub
Private Property Get Item(ByVal Index As Long) As String
Item = Mid$(sItems, Index * StringL + 1, StringL)
End Property
Public Sub AddItem(sInput As String)
If Len(sInput) = 0 Then Exit Sub
Dim S As String * StringL
S = sInput
Dim I&
For I = 0 To NumberOfItems - 1
If Item(I) > S Then Exit For
Next
If I = NumberOfItems Then
sItems = sItems & S
Else
I = I * StringL
sItems = Left$(sItems, I) & S & Mid$(sItems, I + 1)
End If
NumberOfItems = NumberOfItems + 1
End Sub
Property Get GetList() As String()
Dim Arr() As String, I&
ReDim Arr(NumberOfItems - 1)
For I = 0 To NumberOfItems - 1
Arr(I) = RTrim$(Item(I))
Next
GetList = Arr
End Property
Sub ShowList(Optional AdditionalMessage As String = "List contains the following words")
Dim I&, S$
For I = 0 To NumberOfItems - 1
S = S & vbCrLf & Item(I)
Next
MsgBox AdditionalMessage & vbCrLf & S, vbInformation
End Sub
Private Sub Class_Initialize()
'default values
UseDropDown = True
End Sub
Private Sub Class_Terminate()
Set TB = Nothing
blnCancelTimer = True
End Sub
Private Property Get DropDownVisible() As Boolean
If DropDownCreated Then
DropDownVisible = DropDown.Visible
End If
End Property
Private Sub DropDownChosen()
TB.SetFocus
HideDropDown
TB.SelStart = 0
TB.SelLength = Len(TB.Text)
End Sub
Private Sub DropDown_Click()
TB.Text = DropDown.Text
End Sub
Private Sub DropDown_DblClick()
DropDownChosen
End Sub
Private Sub DropDown_KeyDown(KeyCode As Integer, Shift As Integer)
If KeyCode = 13 Then DropDownChosen
End Sub
Private Sub TB_GotFocus()
TB.SelStart = 0
TB.SelLength = Len(TB.Text)
End Sub
Private Sub TB_KeyDown(KeyCode As Integer, Shift As Integer)
If KeyCode = 40 And DropDownVisible Then
DropDown.SetFocus
DropDown.ListIndex = 0
End If
End Sub
Private Sub TB_KeyPress(keyascii As Integer)
If keyascii < 32 Then
LastFill = ""
HideDropDown
Exit Sub
End If
Dim P As Long, C As String * 1
C = Chr$(keyascii)
P = TB.SelStart + 1
If Len(LastFill) Then
If StrComp(Mid$(LastFill, P, 1), C, vbTextCompare) = 0 Then
TB.SelStart = P
TB.SelLength = Len(TB.Text)
keyascii = 0
If DropDownVisible Then
'check the items in the dropdown, if they still qualify. The first one always qualifies
Dim T As String
T = Left$(TB.Text, TB.SelStart)
With DropDown
For P = .ListCount - 1 To 1 Step -1
If InStr(1, .List(P), T, vbTextCompare) <> 1 Then .RemoveItem P
Next
.Visible = .ListCount > 1
If .Visible Then SetHeightDropDown
End With
End If
Exit Sub
End If
End If
If FindItem(Left$(TB.Text, P - 1) & C) Then
keyascii = 0
ElseIf OnlyAllowList Then
Beep
keyascii = 0
Else
LastFill = ""
End If
End Sub
Private Function FindItem(strText As String) As Boolean
If Len(strText) = 0 Then Exit Function
Dim P As Long, Start As Long, L As Long
Do
P = InStr(P + 1, sItems, strText, vbTextCompare)
If P = 0 Then Exit Do
If (P - 1) Mod StringL = 0 Then
If Start = 0 Then
Start = P \ StringL
LastFill = RTrim$(Item(Start))
L = Len(strText)
TB.Text = strText & Mid$(LastFill, L + 1)
TB.SelStart = L
TB.SelLength = Len(TB.Text)
FindItem = True
If Not UseDropDown Then Exit Function '<- !exit point!
Else
L = P
End If
End If
Loop
If UseDropDown Then
With DropDown
.Clear
L = L \ StringL
.Visible = Start > 0 And (L > Start)
If .Visible Then
For P = Start To L
.AddItem RTrim$(Item(P))
Next
SetHeightDropDown
End If
End With
End If
End Function
Private Sub SetHeightDropDown()
Dim I&
With DropDown
I = .ListCount
If I > MaxItemsInDropdown Then I = MaxItemsInDropdown
I = LineHeight * I
.Height = I
'make sure the listbox is within the forms range
I = .Parent.ScaleHeight - .Top - .Height
If I < 0 Then .Height = .Height + I
End With
StartTimer
End Sub
Private Sub StartTimer()
If DropdownViewTime = 0 Then Exit Sub
TimerStart = Timer '(re)set timer
Static InTimer As Boolean
If InTimer Then Exit Sub 'if already in the loop, exit sub. timer can be reset to stay in loop longer
InTimer = True
blnCancelTimer = False
Do While Timer - TimerStart < DropdownViewTime And Not blnCancelTimer
DoEvents
Loop
On Error Resume Next ' necessary to prevent errors on unloading!
If Not DropDown Is Nothing Then
If Not DropDown.Parent.ActiveControl Is DropDown Then HideDropDown
End If
InTimer = False
End Sub
Private Sub TB_LostFocus()
If Not TB.Parent.ActiveControl Is DropDown Then HideDropDown
End Sub
Private Sub TB_Validate(Cancel As Boolean)
If Len(LastFill) Then
'extra to be sure capitals are the same
TB.Text = LastFill
ElseIf OnlyAllowList And Len(TB.Text) > 0 Then
Cancel = Not FindItem(TB.Text)
If Cancel Then MsgBox "Item not in list!", vbExclamation
End If
If DropDownVisible Then DropDown.Clear
End Sub |