Data Type Mismatch Vb.net Access - database

I am trying to insert data into my Access database using vb for an application I am building. I have been BEATING my had off of an invisible wall trying to get the data to enter into the database. Below is the code, below that I will explain it more.
Private Sub btnSubmitExpense_Click(sender As Object, e As EventArgs) Handles btnSubmitExpense.Click
provider = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source ="
dataFile = "C:\PFADatabase.accdb"
connString = provider & dataFile
myConnection.ConnectionString = connString
myConnection.Open()
Dim str As String
str = "Insert into Expenses ([ExpenseTypeID], [DateOfExpense],[AmountOfExpense]) Values(?,?,?)"
Dim cmd As OleDbCommand = New OleDbCommand(str, myConnection)
cmd.Parameters.Add(New OleDbParameter("ExpenseTypeID", CType(cboCategoryOfExpense.Text, String)))
cmd.Parameters.Add(New OleDbParameter("DateOfExpense", CType(dateOfExpense.Text, String)))
cmd.Parameters.Add(New OleDbParameter("AmountOfExpense", CType(txtAmountOfExpense.Text, String)))
Try
cmd.ExecuteNonQuery()
cmd.Dispose()
myConnection.Close()
'clear the form below
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
[ExpenseTypeID] is actually a lookup. The object is a combobox in vb that I have programmed above the code I posted here.
[DateOfExpense] is also a Date object in VB. I just dragged it over. I want that to be associated with everything in that table.
[AmountOfExpense] is again, tied into the db.
Basically a user enters the date using the tool, then chooses a category of their expense and then enters the amount. This is all one table but the expenseType is a Lookup actually within Access to another table so we could have the dropdown. Everything works well until I click the save button. Then whenever i do that I get the exception the type is mismatched. How do I fix that? I'm GUESSING it is the text string being wrong, but I've tried other things so I am thinking it is a bit more than that which is why I came here to you professionals to get input.
Thank you.
EDIT: The error is coming in at
cmd.ExecuteNonQuery()
and says "Data type mismatch in criteria expression. "
'START THE POPULATE THE COMBO BOXES
'Gets the database and makes the connection
provider = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source ="
dataFile = "C:\PFADatabase.accdb"
connString = provider & dataFile
myConnection.ConnectionString = connString
'Generates a query command
Dim cmd As OleDbCommand = New OleDbCommand("SELECT [ExpenseType] FROM [ExpenseType]", myConnection)
myConnection.Open() 'Opens connection
Dim dr As OleDbDataReader = cmd.ExecuteReader
While dr.Read
cboCategoryOfExpense.Items.Add(dr.Item(0))
End While
myConnection.Close()
'END THE POPULATE OF COMBO BOXES
As you can see in the comments, it is saying how the combo boxes are populated.
EDIT: In the picture under Expenses is the main table. The circled value is the FK and it's leading to the PK of the ExpenseType. The data we are pulling the drop down from is the ExpenseType under ExpenseType. From what I understand, you guys are saying, and I agree, it's writing to the PK of ExpenseType and not the data. ALL I want it to do is keep the data categorized for a graph we will be using.

Convert your input to the appropriate datatype as required by your columns. If you don't specify the datatype of your parameters and pass always strings then you are easy target of this kind of errors
...
Dim cmd As OleDbCommand = New OleDbCommand(str, myConnection)
Dim expID As Integer
if Not Int32.TryParse(cboCategoryOfExpense.Text, expID) Then
MessageBox.Show("Invalid integer")
return
End If
cmd.Parameters.Add("ExpenseTypeID", OleDbType.Integer).Value = expID
Dim dtExp as DateTime
if Not DateTime.TryParse(dateOfExpense.Text, dtExp) Then
MessageBox.Show("Invalid Date")
return
End If
cmd.Parameters.Add("DateOfExpense", OleDbType.Date).Value = dtExp
Dim amount As Decimal
if Not Decimal.TryParse(txtAmountOfExpense.Text, amount) Then
MessageBox.Show("Invalid Decimal")
return
End If
cmd.Parameters.Add("AmountOfExpense", OleDbType.Currency).Value = amount
....
Looking at your edit and comments, perhaps this is what you need
' Be sure to have a combobox with DropDownList style to avoid
' user entering an unexpected value then....
'Load the combobox from the table ExpenseType
Dim cmd As OleDbCommand = New OleDbCommand("SELECT [ExpenseTypeID], " & _
"[ExpenseType] FROM [ExpenseType]", myConnection)
myConnection.Open() 'Opens connection
Dim dr As OleDbDataReader = cmd.ExecuteReader
Dim dt = new DataTable()
dt.Load(dr)
cboCategoryOfExpense.DataSource = dt
' The visible part of the combo contains value from ExpenseType field
cboCategoryOfExpense.DisplayMember = "ExpenseType"
' The hidden part refers to the ExpenseTypeID field
cboCategoryOfExpense.ValueMember = "ExpenseTypeID"
...
and now when converting the combobox value you coud write
Dim expID As Integer
' Sanity check in case the user want to insert but has not
' selected anything from the combobox
if cboCategoryOfExpense.SelectedValue Is Nothing Then
MessageBox.Show("Select an Expense")
return
End if
cmd.Parameters.Add("ExpenseTypeID", OleDbType.Integer).Value = Convert.ToInt32(cboCategoryOfExpense.SelectedValue)
....

Related

Inserting data into database with autonumber in VB.net

I'm trying to insert data into a database with an autonumber in MS Access as primary key. I get an error saying "Number of query values and destination fields are not the same. The data types in MS Access are Autonumber (I didn't include it in the INSERT statement), String (#OrderNo), String (#Product), Number (#Qty), and Date (#TDate). Here's the image:
Here's my code:
For Each row As DataGridViewRow In DataGridView1.Rows
Dim connString As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=Daily Inventory.accdb;"
Using conn As New OleDbConnection(connString)
Using cmd As New OleDbCommand("Insert into Table1 Values(#OrderNo, #Product, #Qty, #TDate)", conn)
cmd.Parameters.AddWithValue("#OrderNo", TxtOrder.Text.ToString)
cmd.Parameters.AddWithValue("#Product", row.Cells("Product").Value)
cmd.Parameters.AddWithValue("#Qty", row.Cells("Qty").Value)
cmd.Parameters.AddWithValue("#TDate", Date.Now.ToString("MM/dd/yyyy"))
If conn.State = ConnectionState.Open Then
conn.Close()
End If
conn.Open()
cmd.ExecuteNonQuery()
conn.Close()
End Using
End Using
Next
You need to change your sql to "Insert into Table1 (OrderNo,Product,Qty,TDate) Values(#OrderNo, #Product, #Qty, #TDate)".
The following code works for me.
DataGridView1.AllowUserToAddRows = False
For Each row As DataGridViewRow In DataGridView1.Rows
Dim connString As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=...;"
Using conn As New OleDbConnection(connString)
Using cmd As New OleDbCommand("Insert into Table1 (OrderNo,Product,Qty,TDate) Values(#OrderNo, #Product, #Qty, #TDate)", conn)
cmd.Parameters.AddWithValue("#OrderNo", TxtOrder.Text.ToString)
cmd.Parameters.AddWithValue("#Product", row.Cells("Product").Value)
cmd.Parameters.AddWithValue("#Qty", row.Cells("Qty").Value)
cmd.Parameters.AddWithValue("#TDate", Date.Now.ToString("MM/dd/yyyy"))
If conn.State = ConnectionState.Open Then
conn.Close()
End If
conn.Open()
cmd.ExecuteNonQuery()
conn.Close()
End Using
End Using
Next
Well, I think we dealing with a bit of a chicken and a egg problem here?
I mean, how did the grid get created?
How and where did you setup the columns in the grid?
lets drop a data grid view into a form. Drop in a button.
We have this code to load up the grid:
Private Sub HotelGridEdit_Load(sender As Object, e As EventArgs) Handles Me.Load
LoadGrid()
End Sub
Sub LoadGrid()
Using conn As New OleDbConnection(My.Settings.AccessDB)
Dim strSQL As String =
"SELECT ID, FirstName, LastName, City, HotelName, Description, Active FROM tblHotelsA
ORDER BY HotelName"
Using cmdSQL As New OleDbCommand(strSQL, conn)
conn.Open()
Dim rstData As New DataTable
rstData.Load(cmdSQL.ExecuteReader)
DataGridView1.DataSource = rstData
End Using
End Using
End Sub
So, now we have this:
Now, in a above, I can cursor around - make any edits I want.
I can also type in on the bottom blank row to add new rows.
I can click on the left side recordselector, and hit delete key.
Now, to save my edits, save my addtitions, and save my deletes?
I have the one button at the top, and this code works to do all updates, all addtitions, and all deletes.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
' save all edits, and new rows, and deletes
Using conn As New OleDbConnection(My.Settings.AccessDB)
Dim strSQL As String =
"SELECT ID, FirstName, LastName, City, HotelName, Description, Active FROM tblHotelsA"
Using cmdSQL As New OleDbCommand(strSQL, conn)
conn.Open()
Dim da As New OleDbDataAdapter(cmdSQL)
Dim daC As New OleDbCommandBuilder(da)
da.Update(DataGridView1.DataSource)
End Using
End Using
End Sub
So, not a lot of code.
In fact, often using a data table is a lot less work, since you don't have to mess with all those parameters anyway - even if your data grid was somehow not feed from the database. But, if you feeding the "grid" from the database, then really, you can just add rows - and then write some code to send the changes back to the database with the above code. And if you want to start out with a blank grid - not show previous rows, then just add to your sql like this:
SELECT * from tblHotels WHERE ID = 0 Order by Hotelname
Use above to create a data table without any rows but STILL bind that to the grid, and thus once again, to add, or delete rows, you just edit and add them, and again the SAME code I had above will work to save edits, deletes and additions.

My DataGridView updates temporarily as I stop the program and start it again. But my Access Database remains updated permanently

Would there be a chance to solve this problem? Once that I inserted a data from the Database, I wanted to update my DataGridView from the other form. Clearly the datagridview has to update as it SELECT on the table of the Database. But once that I updated the datagridview, I tried closing the system from running and restart it again. But when I checked there it didn't update. It goes like the usual datas that is from the Database. However my database is well updated and the data I inserted from the TextBoxes was there too.
Private Sub updateBtn_Click(sender As Object, e As EventArgs) Handles updateBtn.Click
Dim newtable = New DataTable()
provider = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source="
datafile = "C:\Users\Anthony\Desktop\thesis\DATABASE\BookLists.accdb"
connString = provider & datafile
myConnection.ConnectionString = connString
myConnection.Open()
Dim str As String
Try
str = "Select * from TVL12"
Dim cmd As OleDbCommand = New OleDbCommand(str, myConnection)
Dim da As OleDbDataAdapter = New OleDbDataAdapter()
da.SelectCommand = cmd
da.Fill(newtable)
cmd.Dispose()
myConnection.Close()
Catch ex As Exception
MsgBox(ex.Message)
End Try
TVL12.BookListTVL.DataSource = newtable
End Sub
Here's the code for Updating the DataGridView. Anyone had any ideas why does it only Temporarily updates the DataGridView?

SQL Server query parameter for copy data table to another table form ListView VB.net

I'm using VB.net 2013 and SQL Server Express. I want to copy data from the table that appears in the listview to the temporary table. But I got an error:
Operator '&' is not defined for types 'String' and 'System.Windows.Forms.ListViewItem.ListViewSubItem'
What are the correct parameters?
My code looks like this
For Each itm As ListViewItem In ListViewMasterBiaya.CheckedItems
Dim SIMPAN As String = "INSERT INTO TempEntriBiaya WHERE NoKode='" & ListViewMasterBiaya.SelectedItems(0).SubItems(0) & "'"
CMD = New SqlCommand(SIMPAN, CONN)
CMD.ExecuteNonQuery()
Next
End Sub
I also include the image as below, when I check it, the data will also copy to the temporary table
Comments and explanation in-line. Following LarsTech comments.
Dim SIMPAN As String = "INSERT INTO TempEntriBiaya (Column1Name, Column2Name) Values (#Column1, #Column2);"
'The Using...End Using blocks ensure that your ADO objects are closed and
'disposed event if there is an error
Using cn As New SqlConnection("Your connection string")
'The command and parameters only need to be declared once
'outside the loop, only the value of the parameters change
Using cmd As New SqlCommand(SIMPAN, cn)
cmd.Parameters.Add("#Column1", SqlDbType.Int)
cmd.Parameters.Add("#Column2", SqlDbType.VarChar)
'Open the connection at the last possible moment
cn.Open()
For Each itm As ListViewItem In ListViewMasterBiaya.CheckedItems
cmd.Parameters("#Column1").Value = itm.SubItems(0).Text
cmd.Parameters("#Column2").Value = itm.SubItems(1).Text
cmd.ExecuteNonQuery()
Next
End Using
End Using
EDIT Use event ListView.ItemChecked
Private Sub ListViewMasterBiaya_ItemChecked(sender As Object, e As ItemCheckedEventArgs) Handles ListViewMasterBiaya.ItemChecked
'e.Item returns the ListViewItem that changed its check
If e.Item.Checked = True Then
Dim SIMPAN As String = "INSERT INTO TempEntriBiaya (Column1Name, Column2Name) Values (#Column1, #Column2);"
'The Using...End Using blocks ensure that your ADO objects are closed and
'disposed event if there is an error
Using cn As New SqlConnection("Your connection string")
Using cmd As New SqlCommand(SIMPAN, cn)
cmd.Parameters.Add("#Column1", SqlDbType.Int).Value = e.Item.SubItems(0)
cmd.Parameters.Add("#Column2", SqlDbType.VarChar).Value = e.Item.SubItems(1)
'Open the connection at the last possible moment
cn.Open()
cmd.ExecuteNonQuery()
End Using
End Using
End If
End Sub

VB- number of query values and destination fields are not the same

I seriously can't see any problem here. But I get the error
Dim conn As New OleDbConnection("Provider=Microsoft.Jet.OleDb.4.0;Data Source=" & Server.MapPath("App_Data/Database5.mdb"))
conn.Open()
Dim sql As String = "INSERT INTO Users VALUES (#firstName, #lastName)"
Dim txtFname As New TextBox
Dim txtLname As New TextBox
Dim cmd As New OleDbCommand(sql, conn)
cmd.Parameters.AddWithValue("#firstName", txtFname.Text)
cmd.Parameters.AddWithValue("#lastName", txtLname.Text)
cmd.Connection = conn
cmd.ExecuteNonQuery()
cmd.Dispose()
conn.Close()
Database: Id; autonumber
firstName; text
lastName; text
In addition to the comment I made, it's best to employ Using blocks for disposable resources such as connections and commands. Also note the absence of the two TextBoxes you were creating.
Using conn = New OleDbConnection("Provider=Microsoft.Jet.OleDb.4.0;Data Source=" & Server.MapPath("App_Data/Database5.mdb"))
conn.Open()
Using cmd = New OleDbCommand("INSERT INTO Users (FirstName, LastName) VALUES (#firstName, #lastName)", conn)
cmd.Parameters.AddWithValue("#firstName", txtFname.Text)
cmd.Parameters.AddWithValue("#lastName", txtLname.Text)
cmd.ExecuteNonQuery()
End Using
End Using
Please correct your SQL:
INSERT INTO Users (firstName,lastName) VALUES (#firstName, #lastName)

VB.NET Dataset update

I'm new to vb.net and having quite a challenge with updating a field in a table using the For...Next construct on a data set. Sample code below - can anyone tell me what I'm missing? I know this particular example could be accomplished with a simple SQL update statement, but the actual use for what this code will become requires stepping through each record in the dataset. The example below is just a simple one to let me get the procedure down. Note that this runs without an exception, but just doesn't change the data in the table.
Help! :)
Dim objConn As SqlConnection = New SqlConnection("Data Source=DALLAS\;Initial Catalog=Adaptive;Integrated Security=True")
Dim selectCMD As SqlCommand = New SqlCommand("SELECT * from dwbprocref", objConn)
selectCMD.CommandTimeout = 30
Dim custDA As SqlDataAdapter = New SqlDataAdapter
custDA.SelectCommand = selectCMD
Dim custCB As SqlCommandBuilder = New SqlCommandBuilder(custDA)
custCB.QuotePrefix = "["
custCB.QuoteSuffix = "]"
Dim dRow As DataRow
Dim dTable As DataTable
objConn.Open()
Dim custDS As DataSet = New DataSet
custDA.Fill(custDS, "dwbprocref")
For Each dRow In custDS.Tables(0).Rows
If dRow.Item("pr_format") = "MDV" Then
dRow.Item("pr_tester") = "X"
End If
custDS.AcceptChanges()
Next
custDA.Update(custDS, "dwbprocref")
objConn.Close()
You're calling AcceptChanges. This marks all of the rows as being unmodified, so they are never updated in the database. Remove this call and you should be good.

Resources