DataGridView selected row index - vb.net

Why is the dgView.CurrentCell.RowIndex always 0? I need to know which row and column a user is trying to edit. column 1 can only be edited if it is a new row. column 4 can be edited only if it is not a new row. No other columns can be edited.
I need to be able to add a new row.
I've tried .CellBeginEdit with e as DataGridViewCellCancelEventArgs
And no, I don't want to bind my data to the SQL table. I need to make sure the user knows they are changing the data when they save it.
I've tried with CellMouseClick and CellMouseLeeave with disastrous results. I found these two and thought I had them working but testing proves that not to be the case.
My code (some of which is redundant as I'm still trying to understand what events I should be working with):
Private Sub dgTools_CellBeginEdit(sender As Object, e As DataGridViewCellCancelEventArgs) Handles dgTools.CellBeginEdit
Dim i As Integer
With dgTools
i = .CurrentCell.RowIndex
Select Case e.ColumnIndex
Case 1
If .CurrentCell.RowIndex < .NewRowIndex Then
Dim msg As Object, hdr As Object
msg = "You may not edit the tool ID"
hdr = "Edit Error"
MsgBox(msg, MsgBoxStyle.Critical, hdr)
End If
Case 4
originalValue = .CurrentCell.Value
End Select
.EndEdit()
End With
End Sub
Private Sub dgTools_CellEndEdit(sender As Object, e As DataGridViewCellEventArgs) Handles dgTools.CellEndEdit
Dim dtCheck As New DataTable
Dim hdr As Object, msg As Object
With dgTools
.EndEdit()
Select Case e.ColumnIndex
Case 1
Select Case originalValue
Case ""
.CurrentCell.Value = UCase(.CurrentCell.Value)
dtCheck = GetDataTable("GetTool_x_BrochsteinsID", "#BrochsteinsID", .CurrentCell.Value)
' Brochsteins ID is not a valid ID
If dtCheck.Rows.Count = 0 Then
hdr = "Invalid Brochsteins ID"
msg = "Entry is not a valid Brochsteins ID." & vbCrLf & "Please enter a valid ID."
MsgBox(msg, MsgBoxStyle.Critical, hdr)
.Rows.RemoveAt(e.RowIndex)
Exit Sub
End If
' Check that Brochsteins ID is not already assigned to a toolbox
If dtCheck.Rows(0)("Toolstatus") > 1 Then
hdr = "Illegal Brochsteins ID Assignment"
msg = dtCheck.Rows(0)("BrochsteinsID") & " is already assigned to " & dtCheck.Rows(0)("ToolboxDesc") & vbCrLf &
"Please enter a different Brochsteins ID or Return this ID to the Tool Room first."
MsgBox(msg, MsgBoxStyle.Critical, hdr)
.Rows.RemoveAt(e.RowIndex)
Exit Sub
End If
.CurrentRow.Cells(0).Value = dtCheck.Rows(0)("ToolId")
.CurrentRow.Cells(2).Value = dtCheck.Rows(0)("ModelDesc").ToString
.CurrentRow.Cells(3).Value = dtCheck.Rows(0)("CategoryDesc").ToString
.CurrentRow.Cells(4).Value = dtCheck.Rows(0)("AssignedNote").ToString
Case Else
If originalValue <> .CurrentCell.Value Then
hdr = "Edit Brochsteins ID"
msg = "You may not edit a Brochsteins ID." & vbCrLf & "You may only Delete and/or Add a new Brochsteins ID."
MsgBox(msg, MsgBoxStyle.Critical, hdr)
.CurrentCell.Value = originalValue
Exit Sub
End If
End Select
End Select
Dim Note As String
If Not IsDBNull(.CurrentRow.Cells("AssignedNote").Value) Then Note = .CurrentRow.Cells("AssignedNote").Value Else Note = ""
UpdateTool_Toolbox(.CurrentRow.Cells("ToolID").Value, cboToolbox.SelectedValue, Note)
If dtCheck IsNot Nothing Then dtCheck.Dispose()
dgTools.EndEdit()
QueryTable("Tools")
QueryTable("Standard")
End With
End Sub

Related

DataGridView add checkbox and allow to select only records based on variable value via checkbox

In vb.net I have DataGidView showing all columns from my Access database. Then in form Load event I added this code to add check box column to DataGridView.
Dim chk As New DataGridViewCheckBoxColumn()
DataGridView1.Columns.Add(chk)
chk.HeaderText = "Select Question"
chk.Name = "chk"
Here I want user to only select those many records as my maxquestions variable integer value and do not let user select more questions. I also want that user cannot change values of my DataGridView. And thereafter I want to export selected questions to a new table mynewtable already created in database.
Thanks, help appreciated.
I have done something and it somehow works fine...
Private Sub DataGridView1_CellValueChanged(sender As Object, e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.CellValueChanged
If (TryCast(DataGridView1.CurrentCell, DataGridViewCheckBoxCell)) IsNot Nothing Then
Dim count As Integer = 0
For Each row As DataGridViewRow In DataGridView1.Rows
Dim isChecked As Boolean = CBool(row.Cells(6).EditedFormattedValue)
If isChecked Then
count = count + 1
Else
' count -= 1
End If
Next
If count > mark_1_questions Then
Label3.ForeColor = Color.Red
Else
Label3.ForeColor = Color.Black
End If
Label3.Text = "You Have Selected: " & count & " Questions."
If count = mark_11_questions Then
MessageBox.Show(Me, "Maximum/Required Questions Selected : " & mark_11_questions, "Caution")
'DataGridView1.EditMode = DataGridViewEditMode.EditProgrammatically
Button1.Enabled = True
ElseIf count > mark_11_questions Then
MessageBox.Show(Me, "Please unselect some questions : " & count - mark_11_questions, "Caution")
Button1.Enabled = False
Else
End If
End If
End Sub
Now the question is how to export selected records through checkbox to table altogether.
You can get the count like this.
Private Function GetCheckedCount() As Integer
Dim CheckedRows As Integer
For Each row As DataGridViewRow In DataGridView1.Rows
If CBool(row.Cells(8).Value) Then
CheckedRows += 1
End If
Next
Return CheckedRows
End Function

Search in datagrid using value in textbox

How can I display value in msgbox. In the first column in datagrid is looking value based on textbox and I want display value from second column and the same row in msgbox. Now I have only "Item found"
Here are columns
Private Sub PictureBox12_Click(sender As Object, e As EventArgs) Handles PictureBox12.Click
Dim temp As Integer = 0
For i As Integer = 0 To List2DataGridView.RowCount - 1
For j As Integer = 0 To List2DataGridView.ColumnCount - 1
If List2DataGridView.Rows(i).Cells(j).Value.ToString = TextBox2.Text Then
MsgBox("Intem found")
temp = 1
End If
Next
Next
If temp = 0 Then
MsgBox("Item not found")
End If
End Sub
You can enumerate List2DataGridView.Rows directly via For Each, there is no need to use indexing to visit them.
For Each row As DataGridViewRow In List2DataGridView.Rows
Then, for each row we test its value and when we find the matching row, we display a message incorporating its value. We have access to the value because it is in scope. When we find the matching element we exit the For Each
For Each row As DataGridViewRow In List2DataGridView.Rows
If row.Cells.Item(1).Value = TextBox2.Text Then
MsgBox("Item is found in row: " & row.Index)
MsgBox("Value of second column in this row: " & row.Cells.Item(1).Value)
Exit For
End If
Next
MsgBox("Item not found")
However this is not the most elegant solution and suffers from poor readability. Specifically, use of Exit For is somewhat ugly and makes the code harder to grok at a clance.
We can do better by using LINQ.
Dim Matches = From row As DataGridViewRow In List2DataGridView.rows
Let CellValue = row.Cells.Item(1).Value
Where CellValue = TextBox2.Text
Select New With {CellValue, row.Index}
Dim Match = Matches.FirstOrDefault()
If Match IsNot Nothing Then
MsgBox("Item is found in row: " & Match.Index)
MsgBox("Value of second column in this row: " & Match.CellValue)
End If
Private Sub PictureBox12_Click(sender As Object, e As EventArgs) Handles PictureBox12.Click
Dim barcode As String
Dim rowindex As String
Dim found As Boolean = False
barcode = InputBox("Naskenujte čárový kód ||||||||||||||||||||||||||||||||||||")
If Len(Trim(barcode)) = 0 Then Exit Sub 'Pressed cancel
For Each row As DataGridViewRow In List2DataGridView.Rows
If row.Cells.Item("DataGridViewTextBoxColumn1").Value = barcode Then
rowindex = row.Index.ToString()
found = True
Dim actie As String = row.Cells("DataGridViewTextBoxColumn2").Value.ToString()
MsgBox("Čárový kód: " & barcode & vbNewLine & "Číslo dílu je: " & actie, , "Vyhledání dílu")
Exit For
End If
Next
If Not found Then
MsgBox("Item not found")
End If
End Sub

Validation set in access breaks the program

The program breaks and displays this message once I input the wrong amount of numbers in a textbox and submited the form.
An unhandled exception of type 'System.Data.OleDb.OleDbException'
occurred in System.Data.dll
Additional information: One or more values are prohibited by the
validation rule 'Is Null Or Like "###########"' set for
'T_Jobs.Customer_Phone'. Enter a value that the expression for this
field can accept."
I have connected visual basic to access using the data source connecting wizard. I want the program to display a message saying "input 11 numbers" instead of it breaking.
You can create a validation function
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
If IsValidForm() Then
' Save the Record
' This line takes all the input from the boxes from adding a New job form, And puts it into
' corresponding boxes in the main menu = because only those boxes
' are connected to the database
' It uses the data adapter from form1
Form1.T_JobsTableAdapter.Insert(Me.TextBox2.Text, M, e.TextBox3.Text, Me.TextBox4.Text,
Me.TextBox5.Text, Me.TextBox6.Text, Me.TextBox7.Text, Me.TextBox8.Text)
'This line updates the table Jobs dataset with the information in the boxes in main menu
'The DataSet passes on the collected data to the database
Form1.T_JobsTableAdapter.Fill(Form1.JobsDBDataSet.T_Jobs)
MsgBox("Record added successfully")
' These lines clear the textboxes so that next job can be added
TextBox2.Text = ""
TextBox3.Text = ""
TextBox4.Text = ""
TextBox5.Text = ""
TextBox6.Text = ""
TextBox7.Text = ""
TextBox8.Text = ""
End If
End Sub
Private Function IsValidForm() As Boolean
Dim msg As String = String.Empty
' Ensure that a Valid Vehicle Model was entered
If TextBox3.Text = "" Then
' MsgBox("Please fill in Car Model", MsgBoxStyle.Information)
msg += "Enter a Car Model" & vbCr
End If
' Validate Date Received
If Not IsDate(TextBox2.Text) Then
msg += "Enter a valid Date Received" & vbCr
End If
' Validate Date Due
If Not IsDate(TextBox2.Text) Then
msg += "Enter a valid Date Due" & vbCr
End If
' Validate Phone Number
If Trim(TextBox8.Text) = "" Then
' NOTE I am not sure how you want to validate this phone number.
' You can do it with RegEx
' The Regular Expression tells VB to make sure that TextBox8 contains only
' Numbers 1 - 9 and only a length of 11. If it does not match, then
' display the validation message
If Not System.Text.RegularExpressions.Regex.IsMatch(TextBox8.Text, "^[0-9]{11}$") Then
msg += "Enter a Phone Number" & vbCr
End If
End If
If msg.Length > 0 Then
MessageBox.Show("Please fix the following errors before continuing:" & Microsoft.VisualBasic.ControlChars.CrLf & msg,
Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information)
Return False
Else
Return True
End If
End Function
this is the code for adding data, it also validates if a textbox isnt empty and if the date is in date format
If TextBox3.Text = "" Then
MsgBox("Please fill in Car Model", MsgBoxStyle.Information)
Else
'This checks if the Date Recieved and Date Due is in the correct format
If IsDate(TextBox2.Text) And IsDate(TextBox6.Text) Then
'This line takes all the input from the boxes from adding a new job form, and puts it into
'corresponding boxes in the main menu = because only those boxes
'are connected to the database
'It uses the data adapter from form1
Form1.T_JobsTableAdapter.Insert(Me.TextBox2.Text, Me.TextBox3.Text, Me.TextBox4.Text,
Me.TextBox5.Text, Me.TextBox6.Text, Me.TextBox7.Text, Me.TextBox8.Text)
'This line updates the table Jobs dataset with the information in the boxes in main menu
'The dataset passes on the collected data to the database
Form1.T_JobsTableAdapter.Fill(Form1.JobsDBDataSet.T_Jobs)
MsgBox("Record added sucessfully")
'These lines clear the textboxes so that next job can be added
TextBox2.Text = ""
TextBox3.Text = ""
TextBox4.Text = ""
TextBox5.Text = ""
TextBox6.Text = ""
TextBox7.Text = ""
TextBox8.Text = ""
Else
MsgBox("Please ensure the Date Recieved and Date Due is in dd/mm/yyyy format", MsgBoxStyle.Information)
End If
End If

Custom search from textbox switch/parameter

I think I am over engineering this a bit. Any assistance is greatly appreciated on how I can fix this little problem. I have an app that searches multiple sites. But if a user types a custom parameter of g=, then it will search google. The problem is I have right now is it strips the G from the first word of my search term. For example, If I type g=golf game, google pops up with olf game. With the other searches, the = character is getting stripped. Should I use contains instead of this custom firstChars function?
Here is my code:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
If TextBox1.Text = "" Then
MsgBox("Enter text to search on." & vbCrLf & Err.Description, MsgBoxStyle.Information, "Need search term to search on.")
TextBox1.Focus()
End If
Try
'CHECK FOR GOOGLE.COM SEARCHING
Dim MyString As String = TextBox1.Text
Dim MyChar() As Char = {"g", "G", "="}
Dim NewString As String = MyString.TrimStart(MyChar)
Dim myUri As New Uri("http://google.com/search?hl=en&q=" & NewString)
Dim first2Chars As String
Dim first3Chars As String
Dim first4Chars As String
first2Chars = TextBox1.Text.Substring(0, 2)
first3Chars = TextBox1.Text.Substring(0, 3)
first4Chars = TextBox1.Text.Substring(0, 4)
MsgBox(first2Chars)
If first2Chars = "G=" Or first2Chars = "g=" Then
System.Diagnostics.Process.Start(myUri.AbsoluteUri)
ElseIf first3Chars = "TS=" Or first3Chars = "ts=" Then
System.Diagnostics.Process.Start("https://localhost/search.do?query=" & Net.WebUtility.UrlEncode(TextBox1.Text))
ElseIf first4Chars = "PIC=" Or first4Chars = "pic=" Then
System.Diagnostics.Process.Start("https://localhost/search.do?query_pic=" & Net.WebUtility.UrlEncode(TextBox1.Text))
End If
Catch ex As Exception
MsgBox("Error running search. The error was: " & vbCrLf & Err.Description, MsgBoxStyle.Exclamation, "Error")
End Try
End Sub

How to use timer in vb.net

I have this code:
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
Dim num As String
Dim message As String
Dim name As String
message = txtMessage.Text
Dim count As Integer = Me.TblContactsBindingSource.Count
If i < TblContactsDataGridView.Rows.Count - 1 Then 'stay within bounds
i = i + 1 ' for all rows except Row0
TblContactsDataGridView.Rows(i - 1).DefaultCellStyle.BackColor = Color.White ' restore previous highlight
TblContactsDataGridView.Rows(i).DefaultCellStyle.BackColor = Color.Bisque 'new highlight
num = Me.TblContactsDataGridView.Rows(i).Cells(1).Value.ToString()
name = Me.TblContactsDataGridView.Rows(i).Cells(0).Value.ToString()
If SerialPort1.IsOpen() Then
SerialPort1.Write("AT" & vbCrLf)
SerialPort1.Write("AT+CMGF=1" & vbCrLf)
SerialPort1.Write("AT+CMGS=" & Chr(34) & num & Chr(34) & vbCrLf)
SerialPort1.Write(message & Chr(26))
MessageBox.Show("Message has been successfully sent to " & vbNewLine & name & " (" & num & ") ", "Message Sent", MessageBoxButtons.OK, MessageBoxIcon.Information)
End If
Else 'next row is off the bottom so
'i = 0 'reset index
'TblSmsDataGridView.Rows(TblSmsDataGridView.Rows.Count - 1).DefaultCellStyle.BackColor = Color.White 'restore bottom row
'TblSmsDataGridView.Rows(i).DefaultCellStyle.BackColor = Color.Bisque 'highlight top row
End If
In a command button I have this:
Timer1.Interval = 2000
Timer1.Enabled = True 'no need to enable it and start it; one or t'other
What happen is, the message box appears over and over. How can i trigger message box to automatically close once it is finished? I commented the code in the "else" because the it repeats over and over.
You have to use a custom message box. Normal message box wont do the thing you wanted. It will pop up every 2 second. best choice is to make a new form and show it as a message box. :)
You need to set timer1.enabled = false in the timer1.tick handler.