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.
Related
Here's my .mdf database file that has 5 columns
I want to add each of those values from my Id column in a list
Private Sub Read_Click(sender As Object, e As EventArgs) Handles Read.Click
Try
If con.State = ConnectionState.Open Then
con.Close()
End If
con.Open()
cmd = con.CreateCommand()
cmd.CommandType = CommandType.Text
cmd.CommandText = "SELECT Id FROM tablekongbago"
cmd.ExecuteNonQuery()
Dim dr As SqlClient.SqlDataReader
dr = cmd.ExecuteReader(CommandBehavior.CloseConnection)
While dr.Read
element = dr.GetInt32(0).ToString()
End While
Catch ex As Exception
End Try
MessageBox.Show(element)
End Sub
The problem is that I can only retrieve the last row of my Id column and not all of the values from my Id column using
element = dr.GetInt32(0).ToString()
If I try to iterate and turn it into
dr.GetInt32(1).ToString()
it displays nothing.
I want to create a collection of Id's to a List(Of Integer) I know how to create a list and a for loop but I don't know how can I retrieve all of my Id's from my Id column, what kind of code should I use if "dr.GetInt32(0)" is only for the last row of the Id column?, is there a way I can loop starting from the very first top row up to the last row of my Id column? I want something like "list[0] - referring to the first row and list[2] - referring to the last row, so that I can add it my List(Of Integer).
I cringe whenever I see If con.State = ConnectionState.Open Then. Connections should be declared in the method where they are used. You should never have to question the ConnectionState.
You have executed your command twice. A Select in not a NonQuery. NoQuery is Insert, Update and Delete.
Your While loop keeps overwriting the element varaiable on each iteration so you only get the value in the last record.
Never write an empty Catch block. It will just swallow errors and you may get unexpected results with no clue why.
It is a good idea to separate you database code from you user interface code.
Create your connection and command with a Using...End Using block so you know they are properly disposed. Likewise with the reader. I like to do as little as possible with a reader because it requires and open connection and connections should be open for as short a time as possible.
Private ConStr As String = "Your connection string"
Private Sub Read_Click(sender As Object, e As EventArgs) Handles Read.Click
Dim dt As DataTable
Try
dt = GetIds()
Catch ex As Exception
MessageBox.Show(ex.Message)
Return
End Try
Dim ListOfIDs = (From row As DataRow In dt.AsEnumerable
Select CInt(row(0))).ToList
ListBox1.DataSource = ListOfIDs
End Sub
Private Function GetIds() As DataTable
Dim dt As New DataTable
Using con As New SqlConnection(ConStr),
cmd As New SqlCommand("SELECT Id FROM tablekongbago;", con)
con.Open()
Using reader = cmd.ExecuteReader
dt.Load(reader)
End Using
End Using
Return dt
End Function
You can simply create a List of Integer and add the ids to your collection during each call to dr.Read()
Dim ids = New List(Of Integer)()
While dr.Read()
ids.Add(dr.GetInt32(0))
End While
You code looks a bit messed up. This should work:
Note that a sql command object is VERY nice.
It has a reader built in - you don't need to define one
It has the command text - you don't need to define one
it has a connection object - again no need to create one (but you look to have one)
And using a dataTable is nice, since you can use for/each, or use the MyTable.Rows(row num) to get a row.
And a datatable is nice, since you don't need a loop to READ the data - use the built in datareader in sqlcommand object.
Using cmdSQL As New SqlCommand("Select Id FROM tblekingbago", con)
cmdSQL.Connection.Open()
Dim MyTable As New DataTable
MyTable.Load(cmdSQL.ExecuteReader)
' table is now loaded with all "ID"
' you can see/use/display/play/have fun with ID like this:
For Each OneRow As DataRow In MyTable.Rows
Debug.Print(OneRow("Id"))
Next
' display the 5th row (it is zero based)
Debug.Print(MyTable.Rows(4).Item("Id"))
End Using
Here is my general understanding of database from what I read so far: Save / Update / Delete to pre-existing file made that binds to form thru SQL.
Here is what I am trying to do - I have a pre-made Data Table in Form with all columns defined. Once app is closed or certain functions ran, I need that data to be saved / updated in SQL (on local). Once app is open I need all that data to be preserved.
So far I have NOT found a single solution to it anywhere most refer to binding to an existing file. When I worked with Excel data transfer cells had to be defined and referenced in form for population.
My assumption is when a database from VB.NET is used, table with values can be created automatically saved/loaded/updated. However this is only my assumption since I never worked with SQL before. I am not sure if I need to manage an actual database file I created with all the values and then bind them to data table. For example DataTable cell XX to database column XX.
Here is what I done so far I have created database and added to my project. I tried few codes and I keep getting Dataset Empty even though there is Data in Table I tried to use DataTable as well but so far nothing has worked.
Please suggest on what I am doing wrong also additional information regards to databases will be great. As per previous I do know how binding works when actual file exist. But creating and managing is confusing to me since I keep thinking there should be a binding file.
Dim connetionString As String
Dim sqlCnn As SqlConnection
Dim sqlCmd As SqlCommand
Dim adapter As New SqlDataAdapter
Dim ds As New DataSet
Dim sql As String
connetionString = "Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\Data_Ant.mdf;Integrated Security=True;Connect Timeout=30"
sql = "SELECT BN FROM DataTable" ' BN is my column name and DataTable is the name of my Table where data gets populated. This is also confusing to me How does it know which value is what? Is there are space/word/characters requirements?
' adapter.TableMappings.Add("DataTable", sql)
If ds.Tables.Count > 0 Then
sqlCnn = New SqlConnection(connetionString)
Try
sqlCnn.Open()
sqlCmd = New SqlCommand(sql, sqlCnn)
adapter.SelectCommand = sqlCmd
adapter.Update(ds)
adapter.Dispose()
sqlCmd.Dispose()
sqlCnn.Close()
Catch ex As Exception
MsgBox("Can not open connection !" & vbCrLf & Err.Description)
End Try
ElseIf ds.Tables.Count = 0 Then
MsgBox("Empty data")
End If
End Sub
Code I use to Create /Save Database. As per previous all columns/formats are pre-made, loaded.
Dim connetionString As String
Dim sqlCnn As SqlConnection
Dim sqlCmd As SqlCommand
Dim adapter As New SqlDataAdapter
Dim ds As New DataSet
Dim sql As String
connetionString = "Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\Data_Ant.mdf;Integrated Security=True;Connect Timeout=30"
sql = "Select BN FROM DataTable"
adapter.TableMappings.Add("BN", sql)
If DataTable.RowCount > 0 Then
sqlCnn = New SqlConnection(connetionString)
Try
sqlCnn.Open()
sqlCmd = New SqlCommand(sql, sqlCnn)
adapter.SelectCommand = sqlCmd
adapter.Update(ds, "BN")
adapter.Dispose()
sqlCmd.Dispose()
sqlCnn.Close()
Catch ex As Exception
MsgBox("Can not open connection !" & vbCrLf & Err.Description)
End Try
ElseIf DataTable.RowCount = 0 Then
MsgBox("Empty data")
End If
End Sub
Please see more info below:
Data Table columns/format are structured for visual representation.
When User start the App Database can be empty/Can contain Values.
When users Runs certain function Closes App values are save and only values.
If I would you an MS Access I would structure same table/values and cross reference it with form values. Form Values come from outside source and Format/Qty is always known.
Hope this helps to have a cleaner look at my issue. Perhaps SQL is not a right choice for me? Does SQL needs to be build before value manipulation.
UPDATE: I Got rid of the Invalid Object error. Table had to be created 1st as I originally thought. However, My DataSet always comes up as EMPTY when I try to save... Cells do contain BN data as" 1,2, ....) Even if I to remove "If" logic Save and Load table comes out as empty. Something does load because when I try to ADD BN it tells me binding bla bla bla(different issue)
CODE:
Private Sub SaveData()
Dim connetionString As String = "Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\Data_Ant.mdf;Integrated Security=True;Connect Timeout=30"
Dim sql As String = "SELECT BN FROM DataTable_d"
Dim sqlCnn As SqlConnection
Dim sqlCmd As SqlCommand
Dim adapter As New SqlDataAdapter
Dim ds As New DataSet()
adapter.TableMappings.Add("BN", sql)
If ds.Tables.Count > 0 Then
sqlCnn = New SqlConnection(connetionString)
Try
sqlCnn.Open()
sqlCmd = New SqlCommand(sql, sqlCnn)
adapter.SelectCommand = sqlCmd
adapter.Update(ds, "BN")
adapter.Dispose()
sqlCmd.Dispose()
sqlCnn.Close()
Catch ex As Exception
MsgBox("Can not open connection !" & vbCrLf & Err.Description)
End Try
ElseIf ds.Tables.Count = 0 Then
MsgBox("Empty data")
End If
End Sub
UPDATE: I got all the things working but I can't save multiple rows..... Could really use some help
In your SQL query remove WHERE DataTable ='. This statement is looking for a column name DataTable which I assume does not exist. The WHERE clause is used to help filter your query. You only use WHERE on column names in your table.
For instance:
SELECT BN FROM DataTable
will return all values from the BN column from DataTable.
Note that if you have multiple columns, the above query will still only return values from BN.
SELECT * FROM DataTable
will return every value in DataTable.
A helpful site to look at documentation for SQL is w3schools.
Let's start with just displaying some data. Add a DataGridView to a Form. You can call LoadData() from a button. I am not very sure of you connection string but give it a try.
Private dt As DataTable
Private sql As String = "Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\Data_Ant.mdf;Integrated Security=True;Connect Timeout=30"
Private Sub LoadData()
'***EDIT*** Add instantiation line
dt = New DataTable()
'The Using...End Using blocks will close and dispose your database objects
'even if there is an error
Using cn As New SqlConnection(sql)
'You can pass the command text and the connection directly to the constructor
'In the select statement use the actual names of the field and table as they appear in the database.
Using cmd As New SqlCommand("Select BN From [Insert the name of the table in the database]", cn)
cn.Open()
dt.Load(cmd.ExecuteReader)
End Using
End Using
DataGridView1.DataSource = dt
End Sub
This is the simplest way I can think of to display data. We will proceed with changing the data once this works. If you get an error on cn.Open() We will have to work on the connection string.
****EDIT****
Private Sub TestConnection()
Dim sql As String = "Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\Data_Ant.mdf;Integrated Security=True;Connect Timeout=30"
Using cn As New SqlConnection(sql)
cn.Open()
End Using
End Sub
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
Unable to delete data from database in vb.net using SQL Server.
Here is my code for deletion, can you tell me where I have gone wrong?
Name of the table is OneToOne:
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
cn.Open()
With cmd
.Connection = cn
.CommandText = " DELETE * FROM OneToOne WHERE SrNo = " & DataGridView1.SelectedRows(0).Cells(0).Value
i = cmd.ExecuteNonQuery
End With
If (i > 0) Then
MsgBox("Conversation Deleted")
End If
cn.Close()
showdata()
End Sub
To delete all rows at once, you can iterate through the selected rows and build a comma-separated string of the Cell(0) values.
Then instead of using WHERE srNo = , use WHERE srNo IN ({your string})
At least, this is the way to do it following your current approach. A better way would be to pass a table-valued parameter to a stored procedure, but that's a broad subject that you would need to research.
And, as with most programming questions, there are multiple other ways this can be done.
on_button_click
s = "DELETE FROM OneToOne WHERE SrNo IN(val1,val2.....valn)"
cn.Open()
cmd = New SqlCommand(s, cn)
i = cmd.ExecuteNonQuery()
If i > 0 Then
MsgBox("yup")
End If
cn.Close()
val1,val2.. are your SrNo values. It's on you how you retrieve/provide SrNo values
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)
....