vb.net Search for Full or partial match in Datagridview from TextBox and select the first match while displaying the full datagrid - vb.net

I have a customers table that is displayed in a datagridview. I would like the user to be able to enter the customers full or partial last name and click a buttom that would then find the first customer that met the match in the text box. As an example: The user types "wil" into the text box and the first record found is for "williams" even though the user is looking for "wilson". The record would be highlighted(selected) and the user could scroll to look at other records and select "wilson" manually (the manual part I can code).
I have searched for hours on the internet and cannot find this type of code. Most of it is filtering or searching every cell and returning every value.
I am currently reworking a project I did with an access database and vba several years ago. I had thought vb.net would be very similar but it is not similar enough for me to modify this code. I'm also going to use a sql database.
The index field is obviously cell(0) and last name is cell(1).
I have found a solution although I did have to modify it. It will do everything I need except one thing. If I type the letter "H" and do a search on last name, it finds the first lastname that has an "H" in the last name but in a different position from the first letter. I need it to go to the first last name that begins with an "H". I have listed my code below.
Dim srch As String
Dim irowindex As Integer
Dim strl As Integer
srch = txtSearch.Text
dgvCustomers.ClearSelection()
For i As Integer = 0 To dgvCustomers.Rows.Count - 1
If dgvCustomers.Rows(i).Cells(0).Value IsNot Nothing Then
If dgvCustomers.Rows(i).Cells(1).Value.ToString.ToUpper.Contains(srch.ToUpper) Then
dgvCustomers.Rows(i).Selected = True
dgvCustomers.RowsDefaultCellStyle.SelectionBackColor = Color.DimGray
irowindex = dgvCustomers.SelectedCells.Item(0).Value
MessageBox.Show(irowindex)
Exit For
End If
End If
Next
End Sub

try this sir.
for each row as datagridviewrow in nameofdatagrid.rows
if row.cells("Lastname").value = txtbox.text then
nameofdatagrid.clearselection()
row.cells("Lastname").selected = true
exit for
end if
next
I think this is your problem? finding lastname match in the datagrid and select it?
hope this will help you :)

Dim srch As String
Dim irowindex As Integer
Dim strl As Integer
srch = txtSearch.Text
dgvCustomers.ClearSelection()
For i As Integer = 0 To dgvCustomers.Rows.Count - 1
If dgvCustomers.Rows(i).Cells(0).Value IsNot Nothing Then
If dgvCustomers.Rows(i).Cells(1).Value.ToString.ToUpper.StartsWith(srch.ToUpper) Then
dgvCustomers.Rows(i).Selected = True
dgvCustomers.RowsDefaultCellStyle.SelectionBackColor = Color.DimGray
irowindex = dgvCustomers.SelectedCells.Item(0).Value
MessageBox.Show(irowindex)
Exit For
End If
End If
Next

Related

Runtime error 3164 for Access when copying [duplicate]

I am having a difficult time how to properly copy specific field data from previous records on my user form. I don't have a code sample to show but my request is very simplistic.
Currently, out of 12 fields, I have 6 that I often repeat data. I can click on and press Ctrl+' ("Insert the value from the same field in the previous record") and it performs the task I want. However, it adds a lot of time to the task. I simply want to write VBA code to perform that command to those specific fields.
I haven't been able to get SendKeys to work. DLast appears to provide random data at times. I feel like this should be a very simple request but for some reason I am not finding a functional solution for it.
Don't fiddle with arrays or queries - use the power of DAO:
Private Sub CopyButton_Click()
CopyRecord
End Sub
If a record is selected, copy this.
If a new record is selected, copy the last (previous) record.
Private Sub CopyRecord()
Dim Source As DAO.Recordset
Dim Insert As DAO.Recordset
Dim Field As DAO.Field
' Live recordset.
Set Insert = Me.RecordsetClone
' Source recordset.
Set Source = Insert.Clone
If Me.NewRecord Then
' Copy the last record.
Source.MoveLast
Else
' Copy the current record.
Source.Bookmark = Me.Bookmark
End If
Insert.AddNew
For Each Field In Source.Fields
With Field
If .Attributes And dbAutoIncrField Then
' Skip Autonumber or GUID field.
Else
Select Case .Name
' List names of fields to copy.
Case "FirstField", "AnotherField", "YetAField" ' etc.
' Copy field content.
Insert.Fields(.Name).Value = Source.Fields(.Name).Value
End Select
End If
End With
Next
Insert.Update
Insert.Close
Source.Close
End Sub
This also, by the way, is an excellent example of the difference between the RecordsetClone and the Clone of a recordset - the first being "the records of the form", while the second is an independant copy.
This also means, that the form will update automatically and immediately.
Provided that it's a simple form to edit a simple table, and that the bound data field names match the control names, you may get away with
If Me.Recordset.AbsolutePosition > 0 Then
With Me.Recordset.Clone()
.AbsolutePosition = Me.Recordset.AbsolutePosition - 1
Dim control_name As Variant
For Each control_name In Array("field1", "field2", "field3", "field4", "field5", "field6")
Me.Controls(control_name).Value = .Fields(control_name).Value
Next
End With
End If
which you assign to a separate button on the same form.
You have a good idea post here already.
You could also say place a function in the before insert event. This event ONLY fires when you start typing into a NEW reocrd, and it becomes dirty.
So, maybe this:
Private Sub Form_BeforeInsert(Cancel As Integer)
Dim rstPrevious As DAO.Recordset
Dim strSQL As String
strSQL = "SELECT TOP 1 * FROM tblPeople ORDER BY ID DESC"
Set rstPrevious = CurrentDb.OpenRecordset(strSQL)
' auto file out some previous values
If rstPrevious.RecordCount > 0 Then
Me.Firstname = rstPrevious!Firstname
Me.LastName = rstPrevious!LastName
End If
End Sub
And some good ideas in say having a "list" or "array" of controls/fields to setup, so you don't have to write a lot of code. (as suggested in the other post/answer here)

MS Access VBA equivalent to Ctrl+'?

I am having a difficult time how to properly copy specific field data from previous records on my user form. I don't have a code sample to show but my request is very simplistic.
Currently, out of 12 fields, I have 6 that I often repeat data. I can click on and press Ctrl+' ("Insert the value from the same field in the previous record") and it performs the task I want. However, it adds a lot of time to the task. I simply want to write VBA code to perform that command to those specific fields.
I haven't been able to get SendKeys to work. DLast appears to provide random data at times. I feel like this should be a very simple request but for some reason I am not finding a functional solution for it.
Don't fiddle with arrays or queries - use the power of DAO:
Private Sub CopyButton_Click()
CopyRecord
End Sub
If a record is selected, copy this.
If a new record is selected, copy the last (previous) record.
Private Sub CopyRecord()
Dim Source As DAO.Recordset
Dim Insert As DAO.Recordset
Dim Field As DAO.Field
' Live recordset.
Set Insert = Me.RecordsetClone
' Source recordset.
Set Source = Insert.Clone
If Me.NewRecord Then
' Copy the last record.
Source.MoveLast
Else
' Copy the current record.
Source.Bookmark = Me.Bookmark
End If
Insert.AddNew
For Each Field In Source.Fields
With Field
If .Attributes And dbAutoIncrField Then
' Skip Autonumber or GUID field.
Else
Select Case .Name
' List names of fields to copy.
Case "FirstField", "AnotherField", "YetAField" ' etc.
' Copy field content.
Insert.Fields(.Name).Value = Source.Fields(.Name).Value
End Select
End If
End With
Next
Insert.Update
Insert.Close
Source.Close
End Sub
This also, by the way, is an excellent example of the difference between the RecordsetClone and the Clone of a recordset - the first being "the records of the form", while the second is an independant copy.
This also means, that the form will update automatically and immediately.
Provided that it's a simple form to edit a simple table, and that the bound data field names match the control names, you may get away with
If Me.Recordset.AbsolutePosition > 0 Then
With Me.Recordset.Clone()
.AbsolutePosition = Me.Recordset.AbsolutePosition - 1
Dim control_name As Variant
For Each control_name In Array("field1", "field2", "field3", "field4", "field5", "field6")
Me.Controls(control_name).Value = .Fields(control_name).Value
Next
End With
End If
which you assign to a separate button on the same form.
You have a good idea post here already.
You could also say place a function in the before insert event. This event ONLY fires when you start typing into a NEW reocrd, and it becomes dirty.
So, maybe this:
Private Sub Form_BeforeInsert(Cancel As Integer)
Dim rstPrevious As DAO.Recordset
Dim strSQL As String
strSQL = "SELECT TOP 1 * FROM tblPeople ORDER BY ID DESC"
Set rstPrevious = CurrentDb.OpenRecordset(strSQL)
' auto file out some previous values
If rstPrevious.RecordCount > 0 Then
Me.Firstname = rstPrevious!Firstname
Me.LastName = rstPrevious!LastName
End If
End Sub
And some good ideas in say having a "list" or "array" of controls/fields to setup, so you don't have to write a lot of code. (as suggested in the other post/answer here)

(VB.Net) Prevent Duplicates from being added to a list box

I'm having some trouble with catching duplicates in an assignment I'm working on.
The assignment is a track and field race manager. Times are read from a text file, a bib number is then entered for each time loaded from the text file (aka, however many rows there are in the time text file)
The bib numbers and times are then synced in the order from which they were entered. A requirement is that the Bib numbers must be entered one at a time using an input box. Every time a bib number is entered, it is loaded to a list box called lstBibs.
The Issue
I have limited experience working with input boxes, and any attempts Ive made so far to check for duplicates has been ignored in Runtime. I'm also unsure where I would put a loop that checks for duplicates in the input box. Below is my code so far.
Dim i As Integer = 0
Dim Bibno As Integer = 0
Dim strrow As String = ""
Dim count As Integer = 0
Dim errorCount1 As Integer = 0
'Reads through the number of rows in the Time Text File.
'The Number of rows we have in the text file corresponds to the number
'of bib numbers we need. Thus the input box will loop through bib
'numbers until
'we reach the amount of loaded times
Try
For Each item In lstTimeEntry.Items
i += 1
For Bibno = 1 To i
count += 1
Bibno = InputBox("Enter Bib #" & count)
lstBibs.Items.Add(count & " - " & Bibno)
btnSyncTimesBibs.Enabled = True
Next
Next
Catch ex As Exception
'Catches any invalid data that isnt a number
MsgBox("Invalid Input, Please Try Again", , "Error")
lstBibs.Items.Clear()
btnSyncTimesBibs.Enabled = False
End Try
So I'm assuming that I must use a for loop that checks each list box item for a duplicate, I'm just unsure where this loop would go in relation to the code above.
Any and all help is very much appreciated. Thank you.
Don't use exception handling for something that isn't exceptional. Exceptionsl things are things beyond our control like a network connection that isn't available. A user failing to enter proper input is not at all exceptional. Validate the input. Don't make the user start all over again by clearing the list, just ask him to re-enter the last input.
I validate the user input with a TryParse. If the first condition succeeds then the AndAlso condition is checked. It the TryParse fails then the AndAlso condition is never evaluated so we will not get an exception. The second condition is checking if the number has already been used. Only if both conditions pass do we add the number to the used numbers list, update the lstBibs and increment the count.
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim Bibno As Integer
Dim count As Integer = 1
Dim usedNumbers As New List(Of Integer)
Do While count <= lstTimeEntry.Items.Count
Dim input = InputBox("Enter Bib #" & count)
If Integer.TryParse(input, Bibno) AndAlso Not usedNumbers.Contains(Bibno) Then
usedNumbers.Add(Bibno)
lstBibs.Items.Add(count & " - " & Bibno)
count += 1
Else
MessageBox.Show("Please enter a number that does not appear in the list box")
End If
Loop
End Sub
As per Steven B suggestion in the comments, you can check it like this:
If Not listTimeEntry.Items.Contains(itemToBeInserted) Then
listTimeEntry.Items.Add(itemToBeInserted)
End If

How to search in and edit Table by using DataGridView

I have a SQL database with a table "Employees" in it (with large number of rows). By using DataGridView, I want to search for specific "Employee's Name" and change it's "Job". How can I achieve that. I'm using VB.net. Please Help Me.
Not sure if this will help but write a loop that goes through all the values if it finds a match its true if not it is false ,if found the item can be displayed in a textbox and edited
if not a message is displayed saying "no match found"
the editing part can be done using a procedure that will update the value in your grid with what is entered
i can supply code for this if need be but i am unsure if this is what you wish
and there is most likely a better way of doing it
you can loop through your grid, and check if the data you wish to edit exists using the For loop:
Supposing you are using a textbox as the input, and you use a label to hold the employee ID:
Dim EmpIDColumn as Integer = 'array number of your EmpID Column
Dim EmpNameColumn as Integer = 'The array number of the column where your EmpName is
Dim JobColumn as Integer = 'The array number of your job column
For each dr as Datagridviewrow in Datagridview1.Rows
If dr.cells(EmpNameColumn).value = TxtSearchBox.text Then
txtEmpJob.text = dr.cells(JobColumn).value
lblEmpID.Text = dr.cells(EmpIDColumn).value
End if
Next
Okay, so you've searched the record successfully. Next step (after editing the job, and even other details like the name) would be to update the record in the grid. Remember you set the lblEmpID's text to empID in the column? Use it to find the
Record you wish to change in the grid using the same technique above!
Dim EmpIDColumn as Integer = 'array number of your EmpID Column
Dim EmpNameColumn as Integer = 'The array number of the column where your EmpName is
Dim JobColumn as Integer = 'The array number of your job column
For each dr as Datagridviewrow in Datagridview1.Rows
If dr.cells(EmpIDColumn).value = lblEmpID.text Then
dr.cells(JobColumn).value = txtEmpJob.text
dr.cells(EmpNameColumn).value = txtEmpName.text
'then, type in here your SQL Query Update!
End if
Next

Search Listbox and return specific number of items defined in another field - VB.net

I'm running a search query that pulls the search string from one text box, then searches a listbox for the string and displays the results in a second listbox. I would like to define the number of items that it returns based on a second text box. So far I am able to get all list items with be given string to show in the second box. But I have yet to get it to limit the search to 1 item etc. The functional code I've used to show all results is:
Private Sub btnGo_Click(sender As Object, e As EventArgs) Handles btnGo.Click
lstResults.Items.Clear()
If txtSearch.Text.Length > 0 Then
For index As Integer = 0 To lstCountries.Items.Count - 1
Dim txt = lstCountries.Items(index).ToString()
If txt.StartsWith(txtSearch.Text, StringComparison.CurrentCultureIgnoreCase) Then
lstResults.Items.Add(txt)
End If
Next
End If
I've tried using while txtnumber.text > 1 then ahead of this but seem to have created a loop. Any ideas as to what I'm missing?
The datasource is going to have the final say on how many results there are. If the user specifies 3 and there are only 2 in the source, thats all you will get. Something like this will move the results from one to the other until the max is found:
Dim Max as integer = Convert.Toint32(txtNumber.Text)
Dim Count as integer = 0
lstResults.Items.Clear()
For index As Integer = 0 To lstCountries.Items.Count - 1
if lstCountries.Items(index).StartsWith(txtSearch.Text, StringComparison.CurrentCultureIgnoreCase) Then
lstResults.Items.Add(lstCountries.Items(index))
count += 1
end if
' exit the loop if we found enough
If count>= Max Then
Exit For
End If
Next
If the listbox just contains text (strings) then you do not need the ToString: lstCountries.Items(index).StartsWith(strSearch). Basically, you need to exit the loop once the user desired number have been found OR if you run out of data...if I understood right. while txtnumber.text > 1 would not work because textboxes contain strings not numerics (23 is not the same as "23").
The LINQ extensions would work well here as well:
lstResults.Items.AddRange((From item In lstCountries.Items
Let strItem As String = item.ToString
Where strItem.StartsWith(txtSearch.Text, StringComparison.CurrentCultureIgnoreCase)
Select strItem).Take(Integer.Parse(txtnumber.Text)).ToArray)
This assumes that all your data has already been validated.