Edit selected row in DataGridView in new form - vb.net

I have a management system which has a form with DataGridView showing records.
I want to be able to click on a row and click on a 'edit' button, new 'edit form' should come up with all of the record details.
The datagrid grid only shows a few of the fields from ms access around 7/21 fields using of course select statement.
How do I show all of the fields and its details in a new form when I click edit?
This is my DBControl class:
Imports System.Data.OleDb
Public Class DBControl
'create db connection
Private DBCon As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source=IPM_DB.accdb;")
'prepare db command
'variable for database commands
Private DBcmd As OleDbCommand
'db data
'a place to store our data
'storing and handling
'public because will be accessed from main form
'data adapter can perform select, insert, update and elete SQL operations in data source
'executing commands against database, perform actions ie filling data table
Public DBDA As OleDbDataAdapter
'data table
Public DBDT As DataTable
'query parameters
Public Params As New List(Of OleDbParameter)
'query statistics
Public RecordCount As Integer
Public Exception As String
Public Sub ExecQuery(Query As String)
'reset query statistics
RecordCount = 0
Exception = ""
Try
'open a connection
DBCon.Open()
'create db command
DBcmd = New OleDbCommand(Query, DBCon)
'load paramsinto db command
Params.ForEach(Sub(p) DBcmd.Parameters.Add(p))
'clear params list
Params.Clear()
'execute command and fill datatable
DBDT = New DataTable
DBDA = New OleDbDataAdapter(DBcmd)
RecordCount = DBDA.Fill(DBDT)
Catch ex As Exception
Exception = ex.Message
End Try
'close connection
If DBCon.State = ConnectionState.Open Then DBCon.Close()
End Sub
'include query & command parameters
Public Sub AddParam(Name As String, Value As Object)
Dim NewParam As New OleDbParameter(Name, Value)
Params.Add(NewParam)
End Sub
End Class
my current edit form:
Public Class Edit_Incident_Record
Privte Access As New DBControl
Private CurrentRecord As Integer = 0 'Incident.dgvData.SelectedRows(0).Index
Private Sub Edit_Incident_Record_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim currID As Integer = Incident.dgvData.SelectedRows(0).Cells("IncidentID").Value.ToString()
Access.ExecQuery("SELECT * from Incidents where IncidentID = '" & currID & "'")
Dim r As DataRow = Access.DBDT.Rows(currID)
'Access.ExecQuery("SELECT * from Incidents where IncidentID = '" & currID & "'")
txtIncidentID.Text = currID
'txtSummary.Text = r("Summary").ToString
End Sub
End Class
and finally my edit button
Private Sub btnEdit_Click(sender As Object, e As EventArgs) Handles btnEdit.Click
If Me.dgvData.SelectedRows.Count = 0 Or Me.dgvData.SelectedRows.Count > 1 Then
MessageBox.Show("Select just one row")
Return
End If
Edit_Incident_Record.Show()
End Sub
Thank You all!

Related

System.InvalidOperationException ExecuteNonQuery requires an open and available Connection

The following code is supposed to display information from a database but there is an error (the title of this question) on the DBCmd.ExecuteNonQuery() line of code.
Does anyone know how I can resolve this problem?
• I am using VB.NET
• I am using an Access database
The code is:
Imports System.Data.OleDb
Public Class frmCheckAvailablity
Private DBCon As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;" &
"Data Source=|DataDirectory|\NewHotel.mdb;")
Private Access As New DBControl
Dim QRY As String
Private DBCmd As OleDbCommand
Dim DBDR As OleDbDataReader
Public DBDA As New OleDbDataAdapter("SELECT RoomType FROM tblRoomBookings", DBCon)
Public DT As New DataTable
Public DS As New DataSet
Public DR As DataRow
Private Function NotEmpty(text As String) As Boolean
Return Not String.IsNullOrEmpty(text)
End Function
Private Sub frmCheckAvailability_Shown(sender As Object, e As EventArgs) Handles Me.Shown
'RUN QUERY
Access.ExecQuery("SELECT * FROM tblRoomBookings ORDER BY BookingID ASC")
If NotEmpty(Access.Exception) Then MsgBox(Access.Exception) : Exit Sub
End Sub
Private Sub frmCheckAvailability_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'TODO: This line of code loads data into the 'NewHotelDataSet.tblRoomBookings' table. You can move, or remove it, as needed.
Me.TblRoomBookingsTableAdapter.Fill(Me.NewHotelDataSet.tblRoomBookings)
If DBCon.State = ConnectionState.Closed Then DBCon.Open() : Exit Sub
End Sub
Private Sub Search()
DBDA.Fill(DT)
txtSearch.AutoCompleteCustomSource.Clear()
For Each DBDR In DT.Rows
txtSearch.AutoCompleteCustomSource.Add(DBDR.Item(0).ToString)
Next
txtSearch.AutoCompleteMode = AutoCompleteMode.SuggestAppend
txtSearch.AutoCompleteSource = AutoCompleteSource.CustomSource
End Sub
Private Sub SearchCustomers(RoomType As String)
'ADD PARAMETERS & RUN QUERY
Access.AddParam("#RoomType", "%" & RoomType & "%")
Access.ExecQuery("SELECT * FROM tblRoomBookings WHERE RoomType LIKE #RoomType")
'REPORT & ABORT ON ERRORS
If NotEmpty(Access.Exception) Then MsgBox(Access.Exception) : Exit Sub
End Sub
Private Sub txtSearch_TextChanged(sender As Object, e As EventArgs) Handles txtSearch.TextChanged
QRY = "SELECT FullName FROM tblRoomBookings WHERE RoomType'" & txtSearch.Text & "'"
DBCmd = New OleDbCommand(QRY, DBCon)
DBCmd.ExecuteNonQuery()
DBDR = DBCmd.ExecuteReader
If DBDR.Read Then
txtRoomType.Text = DBDR("RoomType")
txtFirstNight.Text = DBDR("FirstNight")
txtLastNight.Text = DBDR("LastNight")
txtNoNights.Text = DBDR("NoNights")
End If
End Sub
The only place in the code that I see DBcmd.ExecuteNonQuery is in search text changed event. Do really want to run this code every time the users types a letter?
Do not create a new connection at the class (Form) level. Every time the connection is used it needs to be disposed so it can be returned to the connection pool. Using...End Using blocks handle this for you even if there is an error.
Don't call .ExecuteNonQuery. This is not a non query; it begins with Select.
You can't execute a command without an Open connection.
Never concatenate strings for sql statments. Always use parameters.
The connection is open while the reader is active. Don't update the user interface while the connection is open.
Load a DataTable and return that to the user interface code where you update the user interface.
Private ConStr As String = "Your connection string"
Private Function GetSearchResults(Search As String) As DataTable
Dim dt As New DataTable
Dim QRY = "SELECT FullName FROM tblRoomBookings WHERE RoomType = #Search"
Using DBcon As New OleDbConnection(ConStr),
DBCmd As New OleDbCommand(QRY, DBcon)
DBCmd.Parameters.Add("#Search", OleDbType.VarChar).Value = Search
DBcon.Open()
Using reader = DBCmd.ExecuteReader
dt.Load(reader)
End Using
End Using
Return dt
End Function
Private Sub txtSearch_TextChanged(sender As Object, e As EventArgs) Handles txtSearch.TextChanged
Dim dtSearch = GetSearchResults(txtSearch.Text)
If dtSearch.Rows.Count > 0 Then
txtRoomType.Text = dtSearch(0)("RoomType").ToString
txtFirstNight.Text = dtSearch(0)("FirstNight").ToString
txtLastNight.Text = dtSearch(0)("LastNight").ToString
txtNoNights.Text = dtSearch(0)("NoNights").ToString
End If
End Sub

Error message - 'No value given for one or more required parameters'

RESOLVED
I am having a bit of trouble with querying an Access database in VB.NET and was hoping someone would be able to help.
When I enter into the TextBox it is supposed to show users that contain the inputted letters in their name.
There are no errors coming up in the code itself but there is an error message ('No value given for one or more required parameters') when I enter into the TextBox and click the button that is supposed to search the database for that surname and display the selected details of that customer only.
There are two pages of code, the first is a Control Class and the second is the code for the Query Form Code.
Control Class:
Imports System.Data.OleDb
Public Class DBControl
'CREATE YOUR DB CONNECTION
Private DBCon As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;" &
"Data Source=Hotel.mdb;")
'PREPARE DB COMMAND
Private DBCmd As OleDbCommand
'DB DATA
Public DBDA As OleDbDataAdapter
Public DBDT As DataTable
'QUERY PARAMETERS
Public Params As New List(Of OleDbParameter)
'QUERY STATISTICS
Public RecordCount As Integer
Public Exception As String
Public Sub ExecQuery(Query As String)
'RESET QUERY STATS
RecordCount = 0
Exception = ""
Try
'OPEN A CONNECTION
DBCon.Open()
'CREATE DB COMMAND
DBCmd = New OleDbCommand(Query, DBCon)
'LOAD PARAMS INTO DB COMMAND
Params.ForEach(Sub(p) DBCmd.Parameters.Add(p))
'CLEAR PARAMS LIST
Params.Clear()
'EXECUTE COMMAND & FILL DATABASE
DBDT = New DataTable
DBDA = New OleDbDataAdapter(DBCmd)
RecordCount = DBDA.Fill(DBDT)
Catch ex As Exception
Exception = ex.Message
End Try
'CLOSE YOUR CONNECTION
If DBCon.State = ConnectionState.Open Then DBCon.Close()
End Sub
'INCLUDE QUERY & COMMAND PARAMETERS
Public Sub AddParam(Name As String, Value As Object)
Dim NewParam As New OleDbParameter(Name, Value)
Params.Add(NewParam)
End Sub
End Class
Query Form Code:
Imports System.Data.OleDb
Public Class RoomQuery
Private Access As New DBControl
Private Function NotEmpty(text As String) As Boolean
Return Not String.IsNullOrEmpty(text)
End Function
Private Sub Query_Shown(sender As Object, e As EventArgs) Handles Me.Shown
'RUN QUERY
Access.ExecQuery("SELECT * FROM Customers ORDER BY Surname ASC")
If NotEmpty(Access.Exception) Then MsgBox(Access.Exception) : Exit Sub
'FILL DATAGRID
dgvCustomers.DataSource = Access.DBDT
'FILL COMBOBOX
For Each R As DataRow In Access.DBDT.Rows
cbxCustomers.Items.Add(R("Surname"))
Next
'DISPLAY FIRS NAME FOUND
If Access.RecordCount > 0 Then cbxCustomers.SelectedIndex = 0
End Sub
Private Sub SearchCustomers(Surname As String)
'ADD PARAMETERS & RUN QUERY
Access.AddParam("#Surname", "%" & Surname & "%")
Access.ExecQuery("SELECT Forename, Surname, Number, Email, City/County FROM Customers " &
"WHERE Surname LIKE #Surname")
'REPORT & ABORT ON ERRORS
If NotEmpty(Access.Exception) Then MsgBox(Access.Exception) : Exit Sub
'FILL COMBOBOX
dgvCustomers.DataSource = Access.DBDT
End Sub
Private Sub btnSearch_Click(sender As System.Object, e As EventArgs) Handles btnSearch.Click
SearchCustomers(txtSearch.Text)
End Sub
End Class
Thank you for your time and I look forward to any responses provided :)
Edit on the Query Form Code:
Public Class RoomQuery
Private Access As New DBControl
Private Function NotEmpty(text As String) As Boolean
Return Not String.IsNullOrEmpty(text)
End Function
Private Sub Query_Shown(sender As Object, e As EventArgs) Handles Me.Shown
'RUN QUERY
Access.ExecQuery("SELECT * FROM Customers ORDER BY Surname ASC")
If NotEmpty(Access.Exception) Then MsgBox(Access.Exception) : Exit Sub
'FILL DATAGRID
dgvCustomers.DataSource = Access.DBDT
'FILL COMBOBOX
For Each R As DataRow In Access.DBDT.Rows
cbxCustomers.Items.Add(R("Surname"))
Next
'DISPLAY FIRS NAME FOUND
If Access.RecordCount > 0 Then cbxCustomers.SelectedIndex = 0
End Sub
Private Sub SearchCustomers(Surname As String)
'ADD PARAMETERS & RUN QUERY
Access.AddParam("#Surname", "%" & Surname & "%")
Access.ExecQuery("SELECT Title, Forename, Surname, Number, Email, City FROM Customers WHERE Surname LIKE #Surname")
'REPORT & ABORT ON ERRORS
If NotEmpty(Access.Exception) Then MsgBox(Access.Exception) : Exit Sub
'FILL COMBOBOX
dgvCustomers.DataSource = Access.DBDT
End Sub
Private Sub btnSearch_Click(sender As System.Object, e As EventArgs) Handles btnSearch.Click
SearchCustomers(txtSearch.Text)
End Sub
End Class
It works now - thank you all for your comments :)

Exception message when trying to load data to DataGridView

Imports System.Data.SqlClient
Public Class SQLCONTROL
Private DBcon As New SqlConnection("Data Source=DESKTOP-DQ7NOIF\SQLEXPRESS;Integrated Security=True")
Private DBcom As New SqlCommand
Public DBDA As SqlDataAdapter
Public DBDT As DataTable
Public Params As New List(Of SqlParameter)
Public RecordCount As Integer
Public Exception As String
Public Sub New()
End Sub
Public Sub New(ConnctionString As String)
DBcon = New SqlConnection(ConnctionString)
End Sub
Public Sub ExecQuery(Query As String)
RecordCount = 0
Exception = ""
Try
DBcon.Open()
DBcom = New SqlCommand(Query, DBcon)
Params.ForEach(Sub(p) DBcom.Parameters.Add(p))
DBDT = New DataTable
DBDA = New SqlDataAdapter(DBcom)
RecordCount = DBDA.Fill(DBDT)
Catch ex As Exception
Exception = "ExecQuery Error" & vbNewLine & ex.Message
Finally
If DBcon.State = ConnectionState.Open Then DBcon.Close()
End Try
End Sub
Public Sub AddParam(Name As String, Value As Object)
Dim NewParam As New SqlParameter(Name, Value)
Params.Add(NewParam)
End Sub
Public Function HasException(Optional Report As Boolean = False) As Boolean
If String.IsNullOrEmpty(Exception) Then Return False
If Report = True Then MsgBox(Exception, MsgBoxStyle.Critical, "Exception:")
Return True
End Function
End Class
the exception message is "A first chance exception of type 'System.Data.SqlClient.SqlException' occurred in System.Data.dll
Additional information: Nom d'objet 'Utilisateurs' non valide."
thanks
Many database objects (including connections and commands) expose a .Dispose method which means that they may be using unmanaged resources which need to be released. To guarantee that .Dispose is called .net provides Using...End Using.
Any errors will bubble up to the calling code where you can handle them and inform the user. After all, your class could be used in a web app or phone app where MsgBox would not work. Leave informing the user to the User Interface code.
Public Class SQLCONTROL
Private ConStr As String = "Data Source=DESKTOP-DQ7NOIF\SQLEXPRESS;Integrated Security=True"
Public Function IsUserValid(userName As String, password As String) As Boolean
Dim RetVal As Integer
Using DBcon As New SqlConnection(ConStr),
DBcom As New SqlCommand("Select Count(*) From [Utilisateurs] Where UserName = #UserName And Password = #Password;", DBcon)
DBcom.Parameters.Add("#UserName", SqlDbType.NVarChar, 50).Value = userName
DBcom.Parameters.Add("#Password", SqlDbType.NVarChar, 100).Value = password
DBcon.Open()
RetVal = CInt(DBcom.ExecuteScalar)
End Using
If RetVal = 0 Then
Return False
End If
Return True
End Function
'To return a DataTable for a DataGridView
Public Function GetCustomerOrders(Customer As String) As DataTable
Dim dt As New DataTable
Using DBcon As New SqlConnection(ConStr),
DBcom As New SqlCommand("Select * From Orders Where CustomerName = #CustomerName;", DBcon)
DBcom.Parameters.Add("#CustomerName", SqlDbType.NVarChar, 100).Value = Customer
DBcon.Open()
dt.Load(DBcom.ExecuteReader)
End Using
Return dt
End Function
End Class
Usage in Form
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim sql As New SQLCONTROL
If sql.IsUserValid("Mary", "MySecretPassword") Then
'Do something
End If
End Sub
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Dim sql As New SQLCONTROL
DataGridView1.DataSource = sql.GetCustomerOrders("General Motors")
End Sub
Naturally, I only guessed at field names, types, and sizes. Check your database.
In a real application you would never store passwords as plain text.

Pass DataTable from Class to Main Form

I am stupidly new to VB.. I have my Class (dalv1) where all my functions are stored and my Main Form.
Code is as follows:
Public Sub getCustomerDetails()
Try
Dim cust_dataTable As New DataTable()
Dim Connection As String = "Provider=Microsoft.Jet.OLEDB.4.0;" & "Data Source = C:\Users\Public\Documents\VP - A1\Database\Database.mdb"
Dim SQL As String = ("SELECT * FROM tblCustomers")
Dim dataAdapter As New OleDbDataAdapter(SQL, Connection)
dataAdapter.Fill(cust_dataTable)
dataAdapter.Dispose()
Catch ex As Exception
MsgBox("ERROR : " & ex.Message.ToString)
End Try
End Sub
I want to pass the DataTable, cust_dataTable to the Main Form so I can populate text boxes when the form loads.
You need to turn it into a function so that the table gets returned to the caller:
Public Function getCustomerDetails() As DataTable
Dim cust_dataTable As New DataTable()
Try
Dim Connection As String = "Provider=Microsoft.Jet.OLEDB.4.0;" & "Data Source = C:\Users\Public\Documents\VP - A1\Database\Database.mdb"
Dim SQL As String = ("SELECT * FROM tblCustomers")
Dim dataAdapter As New OleDbDataAdapter(SQL, Connection)
dataAdapter.Fill(cust_dataTable)
dataAdapter.Dispose()
Catch ex As Exception
MsgBox("ERROR : " & ex.Message.ToString)
End Try
Return cust_dataTable
End Function
You didn't share your form's code, but here is an example of how you would call it:
Private da As New dalv1
Private _MyDataTable As DataTable
Protected Overrides Sub OnLoad(ByVal e As EventArgs)
MyBase.OnLoad(e)
_MyDataTable = da.getCustomerDetails
End Sub

how to use recordset movelast

i need help for the code that i can use old rs.movelast to vb.net 2010..
any simple way to query my record that automatic select the last..
here is my connection sample i just call it only in any form..///
Public Function ExecuteSQLQuery(ByVal SQLQuery As String) As DataTable
Try
Dim sqlCon As New OleDbConnection(CnString)
Dim sqlDA As New OleDbDataAdapter(SQLQuery, sqlCon)
Dim sqlCB As New OleDbCommandBuilder(sqlDA)
sqlDT.Reset() ' refresh
sqlDA.Fill(sqlDT)
Catch ex As Exception
MsgBox("Error : " & ex.Message)
End Try
Return sqlDT
End Function
sqlDT.rows(sqlDT.rows.count-1) will be the last record of your DataTable sqlDT. sqlDT.rows.count-1 will return you the last index of the rows in the filled table. Hope it will help you. Thanks
Imports System.Data.OleDb
Public Class Form1
Public CnString As String = "Provider=SQLOLEDB;Data Source=HP-PC\SQLEXPRESS;Persist Security Info=True;Password=sa;User ID=sa;Initial Catalog=Accounts"
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim ssql As String = "Select * from TBL_Access"
Dim dt As DataTable
dt = ExecuteSQLQuery(ssql)
TextBox1.Text = dt.Rows(dt.Rows.Count - 1)(0) 'Value of First Column of Last Row of DataTable dt
TextBox2.Text = dt.Rows(dt.Rows.Count - 1)(1) 'Value of Second Column of Last Row of DataTable dt
End Sub
Public Function ExecuteSQLQuery(ByVal SQLQuery As String) As DataTable
Try
Dim sqlCon As New OleDbConnection(CnString)
Dim sqlDA As New OleDbDataAdapter(SQLQuery, sqlCon)
Dim sqlCB As New OleDbCommandBuilder(sqlDA)
Dim sqlDT As New DataTable
sqlDT.Reset() ' refresh
sqlDA.Fill(sqlDT)
Return sqlDT
Catch ex As Exception
MsgBox("Error : " & ex.Message)
Return Nothing
End Try
End Function
End Class