Auto-Complete partially done
I have a text box and a '4' column ListView on a form.
When the user types into the text box I have got it to auto-complete and also highlight the selection in the listview.
What I would like it to also do is:
- Check against a different column in the listview than the first column
- Scroll the listview to show the selected item
- Highlight the listview as in THIS threads post #1
I have used this code, from the above thread, which partially does what I am after:
vb Code:
Private Sub txtSearch_Change()
'Run through the available items and grab the first matching one.
Dim LvwItm As ListItem
Dim Strt As Integer
lvwMembers.FindItem(txtSearch.Text, , , 1).Selected = True
'If something was chosen then we get the rest of it
Strt = Len(txtSearch.Text)
txtSearch.Text = lvwMembers.SelectedItem.Text
txtSearch.SelStart = Strt
txtSearch.SelLength = Len(txtSearch.Text) - Strt
End Sub
Re: Auto-Complete partially done
I found this in a post by RobDog888,
Quote:
Originally Posted by RobDog888
These are the parameters for the finditem method -
.FindItem (string, value, index, match)
string: string to be search for.
value: lvwText, lvwSubitem, lvwTag
index: specifies the index location from which to begin the search.
match: lvwWholeWord, lvwPartial
So I have tried to use this to get mine to search on the third column of the listview, but I get the error:
Object variable or With block variable not set
on this line of code:
vb Code:
lvwMembers.FindItem(txtSearch.Text, lvwSubItem, 2, lvwPartial).Selected = True
Re: Auto-Complete partially done
Sounds like it isn't finding a match. Maybe declare a variable As ListItem, Set that variable to the result of FindItem, and check if the variable Is Nothing before trying to set it as the SelectedItem?
Also, my interpretation of the Index parameter is that it isn't talking about which SubItem, but rather which Item in the list. So I read your call as searching within all SubItems, starting with the 2nd ListItem.
I could be wrong, though.
Re: Auto-Complete partially done
Quote:
Originally Posted by Ellis Dee
Sounds like it isn't finding a match. Maybe declare a variable As ListItem, Set that variable to the result of FindItem, and check if the variable Is Nothing before trying to set it as the SelectedItem?
Your correct, it is returning Nothing. I used the following to check:
vb Code:
If TypeName(lvwMembers.FindItem(txtSearch.Text, lvwSubItem, , lvwPartial)) <> "Nothing" Then
MsgBox "something"
Else
MsgBox "Nothing"
End If
It should be finding something though! There is data to find! :confused:
Quote:
Originally Posted by Ellis Dee
Also, my interpretation of the Index parameter is that it isn't talking about which SubItem, but rather which Item in the list. So I read your call as searching within all SubItems, starting with the 2nd ListItem.
I could be wrong, though.
If you are wrong, then how would I specify the third column?
Re: Auto-Complete partially done
Just an FYI: When checking whether an object is valid or not, you don't need to use the TypeName function. This is simpler:
vb Code:
If lvwMembers.FindItem(txtSearch.Text, lvwSubItem, , lvwPartial) Is Nothing Then
I wish I could help you more, but I honestly haven't a clue how to specify which subitem to search. I tend to doubt it's even possible without manually writing a the search yourself. (eg: Iterating through all the list items, comparing each list item's appropriate SubItem/column against your criteria. Sloooooooowwwww.)
Re: Auto-Complete partially done
How about when I load the listview, I load a hidden listview with the items from the third column and the row number. Match the row number with the first listview and select it that way?
Re: Auto-Complete partially done
Anybody else help with the three following 'challenges'?
- Check against a different column in the listview than the first column
- Scroll the listview to show the selected item
- Highlight the listview as in THIS threads post #1
Re: Auto-Complete partially done
Re: Auto-Complete partially done
No, don't bother with hidden listviews; that would be a tremendous waste of resources even if you put them into a control array.
Better would be to create an array and add all the listitems and subitems to it for easy searching.
The more-readable but less portable method would be to use a UDT array. Something like:
Code:
Private Type ListDataType
Index As Long
Column(0 To 2) As String
End Type
Private udtList() As ListDataType
Sub LoadList()
Do
Add all items to ListView
Loop
With ListView
ReDim Preserve udtList(.ListItems.Count)
For i = 0 To .ListItems.Count
With .ListItem(i)
udtList(i).Index = i
udtList(i).Columns(0) = .Text
udtList(i).Columns(1) = .SubItem(1)
udtList(i).Columns(2) = .SubItem(2)
End With
Next
End With
Obviously this is poorly thrown-together pseudocode.
The downside to this approach is that sorting udt arrays is annoying; you have to write non-reusable code specific to that UDT. If the list is reasonably small you can ignore sorting & searching altogether and just use a brute-force iteration to find matches.
Re: Auto-Complete partially done
Thanks again Ellis :D
I have decided to leave it that the search is on the first column only. It's not a major problem, I just thought it would have been a nice touch that was all.
(That said, if anybody does find a way to search one of the SubItems - please feel free to post ;))
Re: Auto-Complete partially done
You'll have to loop cause lvwPartial won't work with lvwSubitem.
http://www.vbforums.com/showthread.p...ght=lvwpartial
I'm not aware of any API solution for the listview find.
Re: Auto-Complete partially done
Hi aikidokid, that is not a listview in the other thread. It's a listbox.
Here is a sample autocomplete listview.
Code:
Dim DelKey As Boolean
Private Sub Text1_Change()
On Error GoTo ErrMsg
Dim LstItm As ListItem
ListView1.FindItem(Text1.Text, , , 1).Selected = True
If Not DelKey Then
'If something was chosen then we get the rest of it
strt = Len(Text1.Text)
Text1.Text = ListView1.SelectedItem.Text
Text1.SelStart = strt
Text1.SelLength = Len(Text1.Text) - strt
End If
DelKey = False
Exit Sub
ErrMsg:
ListView1.SelectedItem.Selected = False
End Sub
Private Sub Text1_KeyDown(KeyCode As Integer, Shift As Integer)
If KeyCode = vbKeyDelete Or KeyCode = 8 Then DelKey = True
End Sub
Private Sub Form_Load()
'KPD-Team 1998
'URL: http://www.allapi.net/
'E-Mail: [email protected]
'Add some items to the listbox
With ListView1.ListItems
.Add , , "Computer"
.Add , , "Screen"
.Add , , "Modem"
.Add , , "Printer"
.Add , , "Scanner"
.Add , , "Sound Blaster"
.Add , , "Keyboard"
.Add , , "CD-Rom"
.Add , , "Mouse"
End With
End Sub
Just play with it.
Re: Auto-Complete partially done
Here is autocomplete for listbox.
Code:
Option Explicit
'API call to listbox
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" ( _
ByVal hwnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
ByRef lParam As Any _
) As Long
Const LB_FINDSTRING = &H18F
Dim DelKey As Boolean
Dim bNoClick As Boolean
Private Sub List1_Click()
'to prevent executing the click event
If bNoClick Then Exit Sub
Text1.Text = List1.Text
End Sub
Private Sub List1_GotFocus()
SendKeys "{DOWN}"
End Sub
Private Sub List1_KeyDown(KeyCode As Integer, Shift As Integer)
List1_Click
End Sub
Private Sub Text1_Change()
'autocomplete feature
Dim strt As Long, nIndex As Long
Dim nLen As Long, sText As String
Const LB_GETTEXTLEN As Long = &H18A
Const LB_GETTEXT As Long = &H189
Static blnBusy As Boolean
If blnBusy Then
Exit Sub
End If
bNoClick = True
blnBusy = True
'Retrieve the item's listindex
List1.ListIndex = SendMessage(List1.hwnd, LB_FINDSTRING, -1, ByVal CStr(Text1.Text))
If Not DelKey Then
If List1.ListIndex <> -1 Then
strt = Len(Text1.Text)
Text1.Text = List1.List(List1.ListIndex)
Text1.SelStart = strt
Text1.SelLength = Len(Text1.Text) - strt
Else
End If
End If
DelKey = False
blnBusy = False
bNoClick = False
End Sub
Private Sub Text1_Click()
'select all the text
Text1.SelStart = 0
Text1.SelLength = Len(Text1)
End Sub
Private Sub text1_KeyDown(KeyCode As Integer, Shift As Integer)
'for delete and backspace
If KeyCode = vbKeyDelete Or KeyCode = 8 Then
DelKey = True
Exit Sub
ElseIf KeyCode = vbKeyDown Then
List1.SetFocus
End If
End Sub
That is assuming, the listbox has already items on it. Try it out and see what fits your program best.