Update in access with vb.net - vb.net

I'm making an invoice making software where I have 2 tables 1 for invoice and another for invoice items.
Now problem is if user wants to edit previous invoice and wanted to add some more items or remove some items I wrote query of update set but it needs to be insert also my update query updates all data to same as it is.
here is my update items query
Public Sub update_items()
ds.Clear()
str = ""
If cn.State = ConnectionState.Open Then
cn.Close()
End If
DBConfig.conn()
cn.Open()
For i As Integer = 0 To DataGridView1.Rows.Count - 2
cmd.Parameters.Clear()
cmd.Connection = cn
cmd.CommandText = "update invoice_items set [item_name]=#item_name,[qty]=#qty,[rate]=#rate where [invoice_id]=#invoice_id and [item_code]=#itemcode"
cmd.Parameters.AddWithValue("#item_name", DataGridView1.Rows(i).Cells(2).Value)
cmd.Parameters.AddWithValue("#qty", DataGridView1.Rows(i).Cells(3).Value)
cmd.Parameters.AddWithValue("#rate", DataGridView1.Rows(i).Cells(4).Value)
cmd.Parameters.AddWithValue("#invoice_id", invoice_id.Text.ToString)
cmd.Parameters.AddWithValue("#item_code", DataGridView1.Rows(i).Cells(1).Value)
cmd.ExecuteNonQuery()
Next
End Sub
my data is in datagridview which has one combobox too.Here is how my vb form looks like Here when page loads in side dgv data loads from table called item where item name is combobox and other calculation happens on bases of price and quantity. When it saves all of the data stores in to two diffrent tables one is invoice and second is invoice_items where I store data with item name, quantity, price, invoice no. Rest data is stored in invoice table.
Now where user wants to edit data he has to search with invoice no on search click I get data from invoice table as well as invoice_items and display as it is now I want to update all the data on update click data updates in invoice table perfectly but it starts problem with invoice_items table. which I had written before.

Golly, I suggest you consider using the dataset desinger. (or Entity frame work desinger). Dataset designer works much like EF, but it will auto matic bind and wire up for you automatic all of the data operations.
The results are VERY much like data bound ms-access forms.
so, if I use the data set designer, then I can drag + drop fields on to the form.
and you even get a navigation bar with record movement, and save, and add and delete features ALL automatic done for you.
So, you get say a form like this:
Same goes for datagrids - you can edit, add or even delete.
All of above works with without you having to write code.
Same goes for say a datagrid.
Say we drop in a button (to save), and then a data grid.
We have this:
Total code for this - inclding the save button code is now this:
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
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
ORDER BY HotelName"
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
Note the save code. We send all edits, deletes, and even addtions in one shot.
So, you don't need (nor want) to write code just for a insert, just for edit, and just for adding). You can get the .net system and the form to do all of this work for you.

Related

SQL Aggregation keeping non aggregated columns from separate tables in VB.NET

I am utilizing VB.NET to pull data from a database via an SQLDataAdapter, place it into a DataSet, and then display it in a DataGridView. This all works fine but I need to Group the data by the EquipmentName column and then display only the Max StateChangeID of the group while still display the non-aggregated fields as well (EquipmentStateName etc...). I also know how to create the query that selects just EquipmentName and StateChangeID wile grouping and aggregating but getting the data from both is stumping me.
Initially ask this as a VB.NET question thinking there may be a way to pull two seperate querys and then combine them but I never could figure that out. I was advised to amend the question to focus on SQL so I have.
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim myConnection As SqlConnection
Dim myCconnectionString As String = "Server=SCDCMMSSQL02;Database=CMMS_PROD;Trusted_Connection=yes;"
Dim mySqlAdapter As SqlDataAdapter
Dim myDS As New DataSet
myConnection = New SqlConnection(myCconnectionString)
myConnection.Open()
mySqlAdapter = New SqlDataAdapter("
SELECT
RTP.vwt_EquipmentStateChange.EquipmentStateChangeID,
RTP.vwt_Equipment.EquipmentName,
RTP.vwt_EquipmentState.EquipmentStateName,
RTP.vwt_EquipmentStateChange.Comments,
RTP.vwt_EquipmentStateChange.LastUpdatedBy,
RTP.vwt_EquipmentStateChange.LastUpdated
FROM
RTP.vwt_EquipmentStateChange
LEFT OUTER JOIN
RTP.vwt_EquipmentState
ON RTP.vwt_EquipmentStateChange.EquipmentStateID = RTP.vwt_EquipmentState.EquipmentStateID
LEFT OUTER JOIN
RTP.vwt_Equipment
ON RTP.vwt_EquipmentStateChange.EquipmentID = RTP.vwt_Equipment.EquipmentID
WHERE
(RTP.vwt_EquipmentStateChange.CreatedDate > DATEADD(WEEK,-4,GETDATE()) )
AND
(RTP.vwt_EquipmentStateChange.Comments NOT LIKE '%Cluster%')
ORDER BY
RTP.vwt_Equipment.EquipmentName ASC", myConnection)
'Reading from DB to DataSet and displaying by data grid
mySqlAdapter.Fill(myDS, "EXEC")
DataGridView1.DataSource = myDS
DataGridView1.DataMember = "EXEC"
myConnection.Close()
myConnection.Dispose()
End Sub
What would be the best way to accomplish this. Should I do it within the initial SQL (Which I cant figure out). Should I manipulate it while it is in the DataSet. Should I attempt accomplish the Group By / Aggregation using LINQ (Which I would need to learn and would).
Any pointers would be appreciated!

Filtering SQL data into multiple DataTables in a single DataSet

This should be simple, but it's escaping me right now as I have not written in VB in over a decade.
I have a stored procedure that gets a list of students and their assigned homeroom teacher.
Very basic - just the three columns: FirstName, LastName, Teacher.
What I need is to load the data into a DataSet where each Teacher has their own DataTable filled with the students assigned to them.
Sample data:
So in the example above, I would end up with 3 DataTables named Adams, Taggert and Dublin, each populated with the students associated with them all in a single DataSet in such a way that I could call the data with:
For Each dr As DataRow In ds.Tables("Taggert").Rows
' Do something with dr("FirstName").ToString
Next
Any help would be appreciated.
I ultimately used elements from both answers to find a solution. I ended up using DataViews to create the tables, and added them into the new DataSet. It works perfectly. It iterates through every record, but for the few hundred students it handles, it's actually quite
efficient. Thanks for the comments.
For Each row As DataRow In ds.Tables(0).Rows
Dim Teacher As String = row("Teacher").ToString()
If Not dsOutput.Tables.Contains(Teacher) Then
Dim dvStudents = ds.Tables(0).DefaultView
dvStudents.RowFilter = "Teacher = '" & Teacher & "'"
Dim subTable As New DataTable(Teacher)
subTable = dvStudents.ToTable(Teacher)
dsOutput.Tables.Add(subTable)
End If
Next
old_datatable with all teachers , i will declare this but you use your own
Dim old_datatable As New DataTable
Dim new_dataset As New DataSet
For Each row As DataRow In old_datatable.Rows
Dim teacher As String = row("Teacher")
If new_dataset.Tables.Contains(teacher) = False Then
Dim new_datatable As New DataTable
new_dataset.Tables.Add(new_datatable)
End If
new_dataset.Tables(teacher).Rows.Add(row)
Next
For Each dr As DataRow In new_dataset.Tables("Taggert").Rows
' Do something with dr("FirstName").ToString
Next

Visual Studio VB - Query from datatable instead of database

I'm a veteran Excel VBA coder who has been thrown into the deep end on this form <> Access database project. I'm working on one part of the form where users (employees) will select the site location (84 total, but not all will show based on what team they're on) and then select the department within that site. There are 2,189 total departments, so the department list should only show those for that site.
The database that we query from and update to is on a VERY slow server, so I want to pull a whole lookup table at the beginning (restricted down to those that team works on) into a datatable, then populate the first combo box with unique sites within that datatable, then populate the second combo box with all of the departments at that site.
The datatable is more or less just | ID | Site | Department |. I can fill that datatable just fine and leave it sitting in cache. And I could loop through the datatable to populate the combo boxes, but that's slower than it can be.
So is there a way to perhaps query from that datatable to either directly populate the combo boxes, or to fill a secondary datatable then to the combo boxes? For the first box, it's finding UNIQUE sites that is the challenge. Then for the second, it's departments where the site equals the one selected in the first box.
Thanks!
You can use Linq to Sql as mentioned by "Andrew Morton", i have made an exemple for you :
Dim da As SqlDataAdapter = New SqlDataAdapter("select * from YourDatatable, con)
Dim dt As New Data.DataTable()
da.Fill(dt)
'You can change here your condition as you need
Dim query = (From d1In dt.AsEnumerable() _
Where d1.Field(Of Integer)("ID") = 1 And d1.Field(Of Integer)
Select d1!ID, order!Site , d1!Department ,
If query.Count > 0 Then
comboBox1 .Items .Add (query(0).Site) 'Fill your Combobox1
end if
Dim query2 = (From d2 In dt.AsEnumerable() _
Where d2.Field(Of Integer)("ID") = 2 And d2.Field(Of Integer)
Select d2!ID, order!Site , d2!Department ,
If query2.Count > 0 Then
comboBox2 .Items .Add (query2(0).Department ) 'Fill your Combobox2
end if

Save all items of Listbox to access Database Table in VB.Net

I am working on a project and have hit a brick wall again. I have a listbox with some math operations in it (i.e. "1+2=3"). I am trying to save all items in the listbox to an access database, and I think I am getting close. The database has two entries I put in manually, but when I use the following code I only get -1's (plus the two manual entries) in the listbox (when I clear the listbox and load the database into the listbox). The other issue is I need to limit the database to 10 rows which I have no idea how to do. What I would like to do is check the database each time I save to it to see how many rows it has. If the number of listbox items I am saving will exceed 10 rows in the database then clear the database and start from 0 rows. Here is the code I have (which only attempts to save to database):
con.ConnectionString = "Provider = Microsoft.ACE.OLEDB.12.0; Data Source = Mathops.accdb; Persist Security Info=False;"
Dim cmd As New OleDbCommand
Dim var1 As String
con.Open()
cmd.Connection = con
Try
For i As Integer = 0 To lstDisplay.Items.Count - 1
var1 = lstDisplay.Items.Item(i).ToString
cmd.CommandText = ("INSERT into Records (Operations) VALUES(" + var1 + ")")
cmd.ExecuteNonQuery()
Next
Catch ex As Exception
MsgBox(ex.Message)
End Try
con.Close()
Thank you for any assistance you can provide!
John
Oh...and the database has 2 fields; ID and Operations where ID is the Primary Key.
Try using listdisplay.items(i) to get the text from your listbox.
Then to sort out the 10 items issue:
If you do an SQL query:
SELECT Max(id) FROM Records that will give you the biggest id value in the table
Then check if the value you get back >= 10, and if it is use the SQL:
DELETE FROM Records to clear the table.

Querying 2 tables using dataset in Visual basic

I need help with my visual basic project. I have a Store.accdb database
which has 2 tables, customers and orders. I would like to be able to enter a customer's name (or part of a name) in a textbox and then display the name/s in a DataGridView when the search button is clicked. And then On a separate DataGridView I'd like to display the orders of the selected customer from my first DataGridView when the user clicks the Display button.
Edit: This is what the 2 tables look like
Customers table = custNum, custName, custAddress, custPhone
Orders table = orderNum, orderItem, custNum, price, qty
con.ConnectionString = dbProvider & dbSource
Try
con.Open()
sql = "SELECT custName FROM tblCustomers WHERE custName LIKE '%" & tbSearch.Text.ToUpper & "%'"
ds = New DataSet
da = New OleDb.OleDbDataAdapter(sql, con)
da.Fill(ds, "CustomerDataset")
gridCustomers.DataSource = ds
gridCustomers.DataMember = "CustomerDataSet"
con.Close()
Catch ex As Exception
MessageBox.Show("Could not establish a connection", "Database Error")
End Try
This code works fine, it populates my customers datagridview. I get multiple rows whenever I only enter part of a customer's name. If I enter 'sm' in the textbox, it would display all customers with 'sm' in their name. How can I display the selected customer's (from 1st datagridview) orders in my 2nd datagridview when i click the display button? I hope I am making sense, english is not my first language so please bear with me.
Thanks!
You have to play with many events.
when selecting a customer from datagridview you have to use datagridview's selectedIndexChange event(assuming you have button to select in datagridview)
You have to use the same procedure in datagridview's selectedIndexChange event
con.ConnectionString = dbProvider & dbSource
Try
con.Open()
sql = "SELECT * FROM tblorders WHERE custName ='" & gridSelectedValue & "'"
//Assuming you have custName column in order table
ds = New DataSet
da = New OleDb.OleDbDataAdapter(sql, con)
da.Fill(ds, "OrderDataset")
gridCustomers.DataSource = ds
gridCustomers.DataMember = "OrderDataset"
con.Close()
Catch ex As Exception
MessageBox.Show(ex.message)
End Try
Edit
If you dont have custName in order Then you should have CustNum in your query of DataGridView.
Step 1 - change the query that works. Instead of selecting just the customer name, select the customer id, or whatever the primary key of that table is.
Step 2 - when displaying your data, add an anchor tag with a query string that links to a new page showing the orders. The html should look like something like this:
Fred
In orders.aspx, call a query that brings back all the orders for customer_id = 1.
Oh, yes, by the way, convert all form and url variables to parameters before sending them to your database.
Actually, you only need to define a "Foreign Key" between the two tables, you can see this article to know how:
www.codeproject.com/Articles/28273/Xml-Database-Demo
Read the "Adding the DataTable Relation" section.
If you had made your db with Access, you have to the same thing. The same thing if you're using SQL.