I created a search button to query my MS Access database and display the results but whenever I type in the ID and click search button it does nothing.
Everything else is working, it copies data from the VB form and stores it in the MS Access database but the search button does not query the database and retrieve the data.
Below is my code for the search button:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSearch.Click
Dim found As Boolean
Try
cm = New OleDb.OleDbCommand
With cm
.Connection = cn
.CommandType = CommandType.Text
.CommandText = "SELECT* FROM tblInfo WHERE (ID = #ID & txtFind.Text = #ID)"
dr = .ExecuteReader
End With
While dr.Read()
found = True
txtFirst1.Text = dr("Pfirst").ToString
txtMid1.Text = dr("Pmiddle").ToString
txtLast1.Text = dr("Plast").ToString
txtAdd1.Text = dr("Paddress").ToString
txtPhone1.Text = dr("Pphone").ToString
txtContact1.Text = dr("Pcontact").ToString
End While
cn.Close()
Exit Sub
If found = False Then MsgBox("Patient ID not found!", MsgBoxStyle.Critical)
dr.Close()
Catch ex As Exception
End Try
How can I solve this?
The issue is the attempt to pass the value of txtFind.Text into the command.
You want to use parameters:
With cm
.Connection = cn
.CommandType = CommandType.Text
.CommandText = "SELECT * FROM tblInfo WHERE ID = ?"
.Parameters.Add("#ID", OleDbType.[Type]).Value = txtFind.Text
dr = .ExecuteReader
End With
Note that I have used OleDbType.[Type]. You will want to replace this with the data type you have specified for column ID.
It also looks like you have missed opening the connection before calling ExecuteReader():
cn.Open()
I would consider implementing Using:
Sometimes your code requires an unmanaged resource, such as a file handle, a COM wrapper, or a SQL connection. A Using block guarantees the disposal of one or more such resources when your code is finished with them. This makes them available for other code to use.
Here is some sample code:
Using con As New OleDbConnection(connectionString),
cmd As New OleDbCommand("SELECT * FROM tblInfo WHERE ID = ?", con)
con.Open()
cmd.Parameters.Add("#ID", OleDbType.[Type]).Value = txtFind.Text
dr = cmd.ExecuteReader()
...
End Using
Related
I am trying to save a DataGridView data to an Access database (database is already connected to Visual Studio).
Here's my code:
Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
Try
Dim cn As OleDbConnection
cn = New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source= |DataDirectory|\GEFORSERVI V2.1.accdb;")
cn.Open()
Dim cmd As New OleDbCommand
cmd.Connection = cn
cmd.CommandType = Data.CommandType.Text
Dim Strcommandtext As String = "inserto into Factura(Designacao,PrecoUnitario,Qtd,Total,Nome,Entidade,NIF,Telefone,Morada,CodigoProduto,DataEmissao) VALUES(#Servico_Produto,#Valor,#Qtd,#Total,#Nome,#Entidade,#NIF,#Telemovel,#Bairro,#Data_de_Emissao)"
Dim values As String = ""
For i As Integer = 0 To Factura2DataGridView.Rows.Count - 1
values = Strcommandtext & Factura2DataGridView.Rows(i).Cells(11).Value & ")"
cmd.CommandText = values
cmd.ExecuteNonQuery()
Next i
cmd = Nothing
cn.Close()
MsgBox("Your Record Inserted Successfully ")
Catch myException As Exception
MsgBox("No Record Inserted" + myException.ToString())
Finally
'MsgBox("Closing Connection")
End Try
End Sub
Connections and Commands need to be disposed so they can release unmanaged resources. Using...End Using blocks are the best way to handle this since the will do this even if there is an error. In this code I both the connection and command are included in the Using block. Note the comma at the end of the first Using line.
Pass the CommandText and the Connection directly to the constructor of the command. I noticed you had missed one of the parameters that was in the field list. I also noticed the you typed "inserto". I believe it must be "Insert". It is not necessary to set CommandType since CommandType.Text is the default.
In OleDb the order that the parameters appear in the sql string must match the order that they are added to the Parameters collection.
Build the parameters collection once outside the loop. It is only the Values of the parameters that change in the loop.
Open the connection once, outside the loop.
Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
Try
Using cn As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source= |DataDirectory|\GEFORSERVI V2.1.accdb;"),
cmd As New OleDbCommand("Insert into Factura(Designacao,PrecoUnitario,Qtd,Total,Nome,Entidade,NIF,Telefone,Morada,CodigoProduto,DataEmissao)
VALUES(#Servico_Produto,#Valor,#Qtd,#Total,#Nome,#Entidade,#NIF,#Telemovel,#Bairro,#CodigoProduto,#Data_de_Emissao)", cn)
With cmd.Parameters
.Add("#Servico_Produto", OleDbType.Integer)
.Add("#Valor", OleDbType.VarWChar)
.Add("#Qtd", OleDbType.Integer)
.Add("#Total", OleDbType.Decimal)
.Add("#Nome", OleDbType.VarWChar)
.Add("#Entidade", OleDbType.VarWChar)
.Add("#NIF", OleDbType.VarWChar)
.Add("#Telemovel", OleDbType.VarWChar)
.Add("#Bairro", OleDbType.VarWChar)
.Add("#CodigoProduto", OleDbType.Integer)
.Add("#Data_de_Emissao", OleDbType.Date)
End With
cn.Open()
For i As Integer = 0 To Factura2DataGridView.Rows.Count - 1
cmd.Parameters("#Servico_Produto").Value = Factura2DataGridView.Rows(i).Cells(0).Value
cmd.Parameters("#Valor").Value = Factura2DataGridView.Rows(i).Cells(1).Value
cmd.Parameters("#Qtd").Value = Factura2DataGridView.Rows(i).Cells(2).Value
cmd.Parameters("#Total").Value = Factura2DataGridView.Rows(i).Cells(3).Value
cmd.Parameters("#Nome").Value = Factura2DataGridView.Rows(i).Cells(4).Value
cmd.Parameters("#Entidade").Value = Factura2DataGridView.Rows(i).Cells(5).Value
cmd.Parameters("#NIF").Value = Factura2DataGridView.Rows(i).Cells(6).Value
cmd.Parameters("#Telemovel").Value = Factura2DataGridView.Rows(i).Cells(7).Value
cmd.Parameters("#Bairro").Value = Factura2DataGridView.Rows(i).Cells(8).Value
cmd.Parameters("#CodigoProduto").Value = Factura2DataGridView.Rows(i).Cells(9).Value
cmd.Parameters("#Data_de_Emissao").Value = Factura2DataGridView.Rows(i).Cells(10).Value
cmd.ExecuteNonQuery()
Next
End Using
MsgBox("Your Record Inserted Successfully ")
Catch myException As Exception
MsgBox("No Record Inserted" + myException.Message)
End Try
End Sub
There are easier ways to do this. If you have a DataTable bound to the DataGridView you can use a DataAdpater.Update method.
Private Sub BtnReturn_Click(sender As Object, e As EventArgs) Handles btnReturn.Click
If BorrowAccession.Text = "" Or txtBorrowerstype.Text = "" Then
MsgBox("All fields are required.", MsgBoxStyle.Exclamation)
ElseIf txtremarks.Text = "Over Due" Then
sql = "Select * From `maintenance` fine ='" & txtfine.Text & "' "
reloadtxt(sql)
End sub
how will i display the fine in txtfine.text from my maintenance database after it satisfy the condition from txtremarks. i tried some youtube tutorials but only displaying it from data grid .. want i basically want is directly display it from database to textbox. btw im newbie in vb programming thank you in advance
for my reloadtxt this is the code.
Public Sub reloadtxt(ByVal sql As String)
Try
con.Open()
With cmd
.Connection = con
.CommandText = sql
End With
dt = New DataTable
da = New MySqlDataAdapter(sql, con)
da.Fill(dt)
Catch ex As Exception
' MsgBox(ex.Message & "reloadtxt")
Finally
con.Close()
da.Dispose()
End Try
End Sub
To populate an object with data from a database you need to access the objects text property.
Textbox1.Text = "Some Text, static or dynamic"
Since you are pulling the data from a datatable you would access the column named "fine" and put that value in the textbox.text property.
Textbox1.Text = dt.row(0).item("fine").tostring
Changed Or to OrElse because it short circuits the If and doesn't have to check the second condition if the first condition is True.
In the reloadtxt method you filled a DataTable and did nothing with it. I changed it to a Function that returns the DataTable. The connection and command are now included in a Using...End Using block so they are closed and disposed even if there is an error.
Never concatenate strings to build an sql statement. Always used parameters.
Private Sub BtnReturn_Click(sender As Object, e As EventArgs) Handles btnReturn.Click
If BorrowAccession.Text = "" OrElse txtBorrowerstype.Text = "" Then
MsgBox("All fields are required.", MsgBoxStyle.Exclamation)
ElseIf txtremarks.Text = "Over Due" Then
Dim dt = reloadtxt()
DataGridView1.DataSource = dt
End If
End Sub
Public Function reloadtxt() As DataTable
Dim dt As New DataTable
Using con As New MySqlConnection("Your connection string"),
cmd As New MySqlCommand("Select * From maintenance Where fine = #Fine", con)
cmd.Parameters.Add(#Fine, MySqlDbType.VarChar, 50).Value = txtfine.Text
Try
con.Open()
dt.Load(cmd.ExecuteReader)
Catch ex As Exception
MsgBox(ex.Message & "reloadtxt")
End Try
End Using
Return dt
End Function
Private Sub btnUpdate_Click(sender As Object, e As EventArgs) Handles btnUpdate.Click
Try
Dim con As New SqlConnection
Dim cmd As New SqlCommand
con.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=E:\Comp-296\Project1\Project1\Game_time.mdb"
con.Open()
cmd.Connection = con
cmd.Connection = con
cmd.CommandText = ("UPDATE User_Name SET User_Name = #User_Name, Game_Name = #Game_Name, Score = #Score, Time/Date = #Time/Date")
cmd.Parameters.Add("#User_Name", SqlDbType.VarChar).Value = txtUser.Text
cmd.Parameters.Add("#Game_Name", SqlDbType.VarChar).Value = txtGame.Text
cmd.Parameters.Add("#Score", SqlDbType.VarChar).Value = txtScore.Text
cmd.Parameters.Add("#Time/Date", SqlDbType.DateTime).Value = txtDate.Text
cmd.ExecuteNonQuery()
MessageBox.Show("Data Update successfully")
con.Close()
Catch ex As System.Exception
MessageBox.Show("Data Update has failed")
End Try
End Sub
The code is giving an Exception is an ArgumentException and also :Keyword not supported: 'provider'.
You are using Access. This database cannot be opened using the classes in System.Data.SqlClient. These classes are used when you want to connect to Sql Server, Sql Server Express or LocalDB.
If you want to reach an MSAccess database you need the classes in System.Data.OleDb and these classes are OleDbConnection, OleDbCommand etc...
Said that, please note, that your field Date/Time will give you headaches. Change that name or put always square brackets around it because the / will be interpreted as the division operator
So your code could be:
Using con = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=E:\Comp-296\Project1\Project1\Game_time.mdb")
Using cmd = new OleDbCommand("UPDATE User_Name
SET User_Name = #User_Name,
Game_Name = #Game_Name,
Score = #Score, [Time/Date] = #dt", con)
con.Open()
cmd.Parameters.Add("#User_Name", OleDbType.VarWChar).Value = txtUser.Text
cmd.Parameters.Add("#Game_Name", OleDbType.VarWChar).Value = txtGame.Text
cmd.Parameters.Add("#Score", OleDbType.VarWChar).Value = txtScore.Text
cmd.Parameters.Add("#dt", OleDbType.Date).Value = Convert.ToDateTime(txtDate.Text)
cmd.ExecuteNonQuery()
MessageBox.Show("Data Update successfully")
End Using
End Using
Other notes:
Disposable objects like the connection and the command should be enclosed inside a Using Statement to be disposed and closed as soon as possible.
The time field requires a DateTime value not a string. If you pass a string you will face the automatic conversion made by the engine and sometime the engine is unable to produce a valid date from your input string. This will raise another exception (DataType mismatch). Better check and convert the value before passing it.
Also the type of the parameters should be from the OleDbType enum.
I searched on some codes on how to do a Search Button in VB.net. But somehow, it won't work because of an error. And simply because, I cannot understand its algorithm and function. Newbie here. Anyway, here is the code for the search button:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
myConnection.Open()
crd.Clear()
fn.Clear()
ln.Clear()
Dim str As String
str = "SELECT * FROM tblReg WHERE (Code = '" & src.Text & "')"
Dim cmd As OleDbCommand = New OleDbCommand(str, myConnection)
dr = cmd.ExecuteReader
While dr.Read()
crd.Text = dr("crd").ToString
fn.Text = dr("fName").ToString
ln.Text = dr("lName").ToString
End While
myConnection.Close()
End Sub
And the error was on:
dr = cmd.ExecuteReader
And VB said:
An unhandled exception of type 'System.Data.OleDb.OleDbException' occurred in System.Data.dll
Additional information: No value given for one or more required parameters.
One should not follow online tutorials that teach very bad code. That code is very bad because it contains SQL injection and leaves database objects opened.
You should rewrite your code as follows:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
myConnection.Open()
crd.Clear()
fn.Clear()
ln.Clear()
Using cmd = New OleDbCommand("SELECT * FROM tblReg WHERE Code = ?", myConnection)
cmd.CommandType = CommandType.Text
With cmd.Parameters.Add(Nothing, OleDbType.VarChar, 50)
.Direction = ParameterDirection.Input
.Value = src.Text
End With
Using dr = cmd.ExecuteReader()
While dr.Read()
crd.Text = dr("crd").ToString
fn.Text = dr("fName").ToString
ln.Text = dr("lName").ToString
End While
End Using
End Using
myConnection.Close()
End Sub
You have to use question marks in place of parameters because you are using OleDbCommand that does not support named parameters.
Change OleDbType.VarChar to your actual column type.
Is this the link where you get the code?
http://www.visual-basic-tutorials.com/ReadFromAccess.htm
Kindly do not get the code read each data on the output shows and also check this part of the code.
crd.Text = dr("crd").ToString
fn.Text = dr("fName").ToString
ln.Text = dr("lName").ToString
are you sure crd,fname,lname are the name of your fields in your table? pls check it and also what is the field type of code? is it a text or INT that is Auto Increment? or just an INT? no matter what it is change your code.
from
str = "SELECT * FROM tblReg WHERE (Code = '" & src.Text & "')"
to
str = "SELECT * FROM tblReg WHERE Code =" & src.Text
Updated
I suggest better read or follow the whole instruction based on link where you get your code. I suggest do the same as what the link said create the same and when the program runs with no error then incorporate it with your program beacuse I tried it using VB.NET and Access and it worked Im sure you dont read it. Do this and Im sure you will not just get the code you need you will also learn.
I am using a while loop to populate a second combo based on the value of the first combobox selection. What is happening however, is that the loop is only displaying 1 item in the second combobox instead of about 20. If I set breakpoint on the while loop I can see that all items are being calculated but just not appearing in the combobox.
I would be grateful if someone could point my basic newbie error. Many thanks
Private Sub cmbCustomer_SelectedIndexChanged(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles cmbCustomer.SelectedIndexChanged
sql = "SELECT * from Departments WHERE Customer = '" & cmbCustomer.Text & "'"
Dim cmd As New OleDb.OleDbCommand
cmd.CommandText = sql
cmd.Connection = oledbCnn
dr = cmd.ExecuteReader
While dr.Read()
If (dr.HasRows) Then
cmbDept.Text = CStr((dr("Name"))) <--- 2nd combobox
End If
End While
cmd.Dispose()
dr.Close()
End Sub
The Text property of the combo box contains only what is displayed for the selected item. You need to add the items to the Items collection:
cmbDept.Items.Add(CStr(dr("Name")))
The combo boxes, list boxes etc. display items by calling their ToString() method. Therefore calling CStr should not even be necessary:
cmbDept.Items.Add(dr("Name"))
You are inserting a value in the SQL statement by concatenating strings. If you are just using your program for yourself, this is okay; however, on productive environments this is dangerous. Someone could enter a value that terminates the SELECT statement and introduces another malicious statement. E.g. a DELETE statement that deletes a whole table. This is called a SQL injection attack.
There are two ways to deal with this:
1) Escape the string:
sql = "SELECT * FROM Dep WHERE Cust = '" & s.Replace("'", "''") & "'"
2) Use command parameters:
sql = "SELECT * from Departments WHERE Customer = ?"
Dim cmd As New OleDbCommand(sql, oledbCnn)
cmd.Parameters.AddWithValue("#p1", cmbCustomer.Text)
If you are inserting dates this also has the advantage that you don't need to bother about date formats.
You can simplify your loop to:
While dr.Read()
cmbDept.Text = CStr(dr("Name"))
End While
There is no need to test for HasRows since dr.Read() would return False anyway if no rows were available.
You can have Dispose called automatically by VB with the Using statement:
Using cmd As New OleDbCommand(sql, oledbCnn)
'TODO: Work with cmd here.
End Using
Dispose will be called at the end of the Using block, even if an error occurs within the Using block or the Using block is left by Return or another statement.
You do not need to check if the data reader has rows every iteration, just check it before you loop.
You are not adding the items to the list, but rather setting the Text property of cmbDept, instead do this:
Private Sub cmbCustomer_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmbCustomer.SelectedIndexChanged
sql = "SELECT * from Departments WHERE Customer = '" & cmbCustomer.Text & "'"
Dim cmd As New OleDb.OleDbCommand
cmd.CommandText = sql
cmd.Connection = oledbCnn
dr = cmd.ExecuteReader
If (dr.HasRows) Then
While dr.Read()
cmbDept.Text = CStr((dr("Name"))) <--- 2nd combobox
End While
End If
cmd.Dispose()
dr.Close()
End Sub
Also, it is highly recommended that you use a parameterized query as to avoid a visit from Little Bobby Tables, like this:
Private Sub cmbCustomer_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmbCustomer.SelectedIndexChanged
sql = "SELECT * from Departments WHERE Customer = #Customer"
Dim cmd As New OleDb.OleDbCommand
cmd.Parameters.AddWithValue("#Customer", cmbCustomer.Text)
cmd.CommandText = sql
cmd.Connection = oledbCnn
dr = cmd.ExecuteReader
If (dr.HasRows) Then
While dr.Read()
cmbDept.Text = CStr((dr("Name"))) <--- 2nd combobox
End While
End If
cmd.Dispose()
dr.Close()
End Sub