I'm facing a bit confusing problem Don't know what's going on. I have two windows form 1. sales 2. pending payment. This both form work almost same just a little bit change is in sales I'm calling for the all sales of the day and in pending payment I'm calling all the pending payment group by customer name. Here problem is when I open form sales it works fine but after that in pending payment it gives me same output as sales form even the query is different and same with pending payment if I open it as soon as application run it will runs perfectly but then gives same output in sales form. Here I'm attaching code of both
Code of Sales form
Public Sub call_data(ByVal str As String)
'Try
Dim totalsales As Integer
Dim totalincome As Integer
DataGridView1.DataSource = Nothing
DataGridView1.Rows.Clear()
DataGridView1.Refresh()
ds.Clear()
cmd = New OleDb.OleDbCommand(str, cn)
da.SelectCommand = cmd
da.Fill(ds, "invoice")
DataGridView1.Rows.Clear()
For i = 0 To ds.Tables("invoice").Rows.Count - 1
DataGridView1.Rows.Add(ds.Tables("invoice").Rows(i)(2).ToString(), ds.Tables("invoice").Rows(i)(1).ToString(), ds.Tables("invoice").Rows(i)(0).ToString(), Convert.ToInt64(ds.Tables("invoice").Rows(i)(8).ToString()) + Convert.ToInt64(ds.Tables("invoice").Rows(i)(9).ToString()) + Convert.ToInt64(ds.Tables("invoice").Rows(i)(10).ToString()), Convert.ToInt64(ds.Tables("invoice").Rows(i)(11).ToString()))
totalsales += Convert.ToInt64(ds.Tables("invoice").Rows(i)(8).ToString()) + Convert.ToInt64(ds.Tables("invoice").Rows(i)(9).ToString()) + Convert.ToInt64(ds.Tables("invoice").Rows(i)(10).ToString())
totalincome += Convert.ToInt64(ds.Tables("invoice").Rows(i)(11).ToString())
Next
Label2.Text = totalsales
Label5.Text = totalincome
Label7.Text = totalsales - totalincome
' Catch ex As Exception
' End Try
End Sub
Private Sub add_Click(sender As Object, e As EventArgs) Handles add.Click
call_data("SELECT * from [invoice] Where [invoice_date] Between #" & from_date.Value.ToString("MM/dd/yyyy") & "# And #" & To_Date.Value.ToString("MM/dd/yyyy") & "#")
End Sub
Code of Pending payment form
Public Sub call_data(ByVal str As String)
Try
DataGridView1.DataSource = Nothing
DataGridView1.Rows.Clear()
DataGridView1.Refresh()
Dim totalpurchase As Integer
Dim totalpaid As Integer
Dim totalpending As Integer
ds.Clear()
cmd = New OleDb.OleDbCommand(str, cn)
cmd.Parameters.Clear()
da.SelectCommand = cmd
da.Fill(ds, "invoice")
DataGridView1.Rows.Clear()
For i = 0 To ds.Tables("invoice").Rows.Count - 1
totalpurchase = Convert.ToInt64(ds.Tables("invoice").Rows(i)(1).ToString()) + Convert.ToInt64(ds.Tables("invoice").Rows(i)(2).ToString()) + Convert.ToInt64(ds.Tables("invoice").Rows(i)(3).ToString())
totalpaid = Convert.ToInt64(ds.Tables("invoice").Rows(i)(4).ToString())
DataGridView1.Rows.Add(ds.Tables("invoice").Rows(i)(0).ToString(), totalpurchase, ds.Tables("invoice").Rows(i)(4).ToString(), totalpurchase - totalpaid)
Next
Catch ex As Exception
End Try
End Sub
Private Sub add_Click(sender As Object, e As EventArgs) Handles add.Click
call_data("SELECT client_name, Sum(invoice.freight_rate) AS SumOffreight_rate, Sum(invoice.total_basic_amount) AS SumOftotal_basic_amount, Sum(invoice.delivery_rate) AS SumOfdelivery_rate, Sum(invoice.advanced_amount) AS SumOfadvanced_amount FROM invoice GROUP BY invoice.client_name")
End Sub
Related
Im trying to use report viewer to print receipt with pos system but i get always the first order printing details not the current order details
i think the problem with PrintPreview code section where i can put the code exactly
Sub Savepayment()
Try
Dim sdate As String = Now.ToString("yyyy-MM-dd")
Dim stime As String = Now.ToString("hh:mm:ss")
cn.Open()
cm = New SqlCommand("Insert into TblSales(transno,total,sdate,stime,cashier,discount,totalbill) values (#transno,#total,#sdate,#stime,#cashier,#discount,#totalbill) ", cn)
With cm
.Parameters.AddWithValue("#transno", FrmPos.LblTransNo.Text)
.Parameters.AddWithValue("#total", CDbl(TxtBill.Text))
.Parameters.AddWithValue("#sdate", sdate)
.Parameters.AddWithValue("#stime", stime)
.Parameters.AddWithValue("#cashier", str_user)
.Parameters.AddWithValue("#Discount", CDbl(TxtDiscount.Text))
.Parameters.AddWithValue("#totalbill", CDbl(TxtTotal.Text))
'.Parameters.AddWithValue("#Cash", CDbl(TxtCash.Text))
'.Parameters.AddWithValue("#Change", CDbl(TxtChange.Text))
.ExecuteNonQuery()
End With
cn.Close()
cn.Open()
cm = New SqlCommand("Update tblcart set status='Completed' Where transno like '" & FrmPos.LblTransNo.Text & "'", cn)
cm.ExecuteNonQuery()
cn.Close()
MsgBox("Payment successfully Saved!", vbInformation)
With FrmReceipt
.PrintPreview("Select c.id, p.Description, c.price, c.qty, c.total From tblcart as c inner join tblproduct as p on c.pid=p.id where c.status like 'Completed' and TransNo like '" & FrmPos.LblTransNo.Text & "'")
.ShowDialog()
End With
With FrmPos
.LblTransNo.Text = .GetTransNo()
.loadcart()
End With
Me.Dispose()
Catch ex As Exception
cn.Close()
MsgBox(ex.Message, vbCritical)
End Try
End Sub
Your connection should always be declared in the method where is it used with a Using...End Using block. Connection and commands need to be disposed (have their Dispose method called) to release unmanaged resources. Using blocks handle this for us even if there is an error. It also closes the connection.
Don't Open the connection until directly before the Execute... .
Don't use AddWithValue with Sql Server. See http://www.dbdelta.com/addwithvalue-is-evil/
and
https://blogs.msmvps.com/jcoehoorn/blog/2014/05/12/can-we-stop-using-addwithvalue-already/
and another one:
https://dba.stackexchange.com/questions/195937/addwithvalue-performance-and-plan-cache-implications
Here is another
https://andrevdm.blogspot.com/2010/12/parameterised-queriesdont-use.html
You need to disconnect your database code from your user interface code. Show message boxes and interact with controls in the UI code.
I guessed that TransNo is a numeric type, a primary key and a foreign key. If it is an identity field, you should not be sending a value for it. Remove it from the field list, parameter list and the Add method for the Insert command.
Dates should be saved as dates. You will have problems later sorting and searching if they are not dates. I did not change this is the code.
Private cnStr As String = "Your connection String"
Sub Savepayment(TransNo As Integer, TotalBill As Decimal, str_user As String, Discount As Decimal, Total As Decimal)
Dim sdate As String = Now.ToString("yyyy-MM-dd")
Dim stime As String = Now.ToString("hh:mm:ss")
Using cn As New SqlConnection(cnStr)
Using cm As New SqlCommand("Insert into TblSales(transno,total,sdate,stime,cashier,discount,totalbill) values (#transno,#total,#sdate,#stime,#cashier,#discount,#totalbill);", cn)
With cm.Parameters
.Add("#transno", SqlDbType.NVarChar).Value = TransNo
.Add("#total", SqlDbType.Decimal).Value = TotalBill
.Add("#sdate", SqlDbType.NVarChar).Value = sdate
.Add("#stime", SqlDbType.NVarChar).Value = stime
.Add("#cashier", SqlDbType.NVarChar).Value = str_user
.Add("#Discount", SqlDbType.Decimal).Value = Discount
.Add("#totalbill", SqlDbType.Decimal).Value = Total
End With
cn.Open()
cm.ExecuteNonQuery()
End Using
Using cm As New SqlCommand("Update tblcart set status='Completed' Where transno = #TransNo", cn)
cm.Parameters.Add("#TransNo", SqlDbType.Int).Value = TransNo
cm.ExecuteNonQuery()
End Using
End Using
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim TransNo = CInt(FrmPos.LblTransNo.Text)
Dim User As String = "I don't know where this comes from"
Dim BillTotal As Decimal
If Not Decimal.TryParse(TxtBill.Text, BillTotal) Then
MessageBox.Show("Please enter a valid number in Total Bill.")
Exit Sub
End If
Dim Discount As Decimal
If Not Decimal.TryParse(TxtDiscount.Text, Discount) Then
MessageBox.Show("Please enter a valid number in Discount")
Exit Sub
End If
Dim TotalAfterDiscount As Decimal
If Not Decimal.TryParse(TxtTotal.Text, TotalAfterDiscount) Then
MessageBox.Show("Please enter a valid number in Total")
Exit Sub
End If
Try
Savepayment(TransNo, BillTotal, User, Discount, TotalAfterDiscount)
MsgBox("Payment successfully Saved!", vbInformation)
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
'I have no idea what this code is doing.
With FrmReceipt
.PrintPreview("Select c.id, p.Description, c.price, c.qty, c.total From tblcart as c inner join tblproduct as p on c.pid=p.id where c.status like 'Completed' and TransNo like '" & FrmPos.LblTransNo.Text & "'")
.ShowDialog()
End With
With FrmPos
.LblTransNo.Text = .GetTransNo()
.loadcart()
End With
End Sub
I get the solution i add this code of refresh report on the load form event of the report form
ReportViewer1.RefreshReport()
I'm fighting with something for a couple of days and I really need help from You because it's too difficult for me.
There are many debtor customers of the company I work in. Sometimes they cannot pay off all debt so they would like to pay off their arrears in installment/loan system. I'm working on it using VB.NET. I have to prepare the shedule which will divide every installment for individual invoices. I could easily split invoices to installments with payment deadlines for each one, but after that, in the second step, I have to divide each installment on invoices. There is an example of this accounting made manually in Excel for 2 exemplary invoices below. I know that loops used in the code should have 2 "if" conditions: Condition1: Installment amonunt < Invoice amount and Condition2: Installment amonunt >= Invoice amount, but app user (employee of the debt collection department) can generate mixed shedule (various amounts of each installment) where both of condition can be met.
Additionally the simplification is that the program will not charge interest at all (higher level[! decision).
I'll be very thankful for any help or any clue to solve this problem.
Maybe some of You have had such a problem before 🙂
Thanks in advance!
For accounting application, we have a matching table to bridge between the invoice and receipt(Instalment). When an instalment is scheduled, you match to the invoice accordingly base on FIFO. So you need to update the data to the matching table and at the same time you need to have a Amount Match and Amountunmatched field on you invoice to keep track of the partial payment.
so when the first schedule is done
Instalment : Inst 1
Invoice : Inv A
Amtmatched : 50
MatchDate : 2021-05-15
Debtor : ABC
At the same time you need update the Invoice A amountmatched to 50 and amountunmatched to 106.53 (outstanding)
2nd Instalement
Instalment : Inst 2
Invoice : Inv A
Amtmatched : 50
MatchDate : 2021-06-15
Debtor : ABC
3rd Instalement
Instalment : Inst 3
Invoice : Inv A
Amtmatched : 50
MatchDate : 2021-07-15
Debtor : ABC
4th Instalement, you need to update 2 records
Instalment : Inst 4
Invoice : Inv A
Amtmatched : 6.53
MatchDate : 2021-08-15
Debtor : ABC
Instalment : Inst 4
Invoice : Inv B
Amtmatched : 43.47
MatchDate : 2021-08-15
Debtor : ABC
You can see this patter is very similar to your table.
On the programming part, you need a date input of startdate, and number of instalment to work the amount for each instalment and the last instalment. You can use the oustanding divide by the outstanding and round it off and get the round off figure allocate to the last month.
Save the instalment schedule to a table first. After that loop the instalment schedule and generate the matching table and update the invoice outstanding for each loop. If you think this method can do the trick and you need further help. You just buzz me.
This is the database diagram and some data sample
This is the program UI
I will put in the number of instalment I want to schedule and Instalment prefix to generate the transaction no for the instalment.
Here goes the code
Imports System.Data.SqlClient
Public Class frmInstalment
Private Sub btnGenerateInstalment_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnGenerateInstalment.Click
Dim TotalOustanding = Modws.GetDecimalFromQuery("Select Sum(amtunmatched) from Invoice")
Dim InstNo As Integer = Val(txtInstalmentNo.Text)
Dim Balance = TotalOustanding
Dim i As Integer = 1
Do Until i = InstNo + 1
Dim InstalAmount = Math.Ceiling(TotalOustanding / InstNo)
Balance = Balance - InstalAmount
Dim Amount As Decimal
If Balance > 0 Then
Amount = InstalAmount
Else
Amount = InstalAmount + Balance
End If
Dim InstalNo As String = txtInsalPre.Text & i.ToString("00")
Modws.UpdateItem("Insert into Instalment(TransNo,Instalment,Amount) Values('" & InstalNo & "'," & i & ", " & Amount & ")")
i = i + 1
Loop
Modws.DisplayDataGrid(dgvInstalment, "Select TransNo,Instalment,Amount from Instalment Order by TransNo")
For x = 0 To dgvInstalment.Rows.Count - 1
AddMatching(dgvInstalment("TransNo", x).Value, Val(dgvInstalment("Amount", x).Value))
Next
Modws.DisplayDataGrid(dgvResult, "Select * from Matching Order by Instalment")
End Sub
Private Sub AddMatching(InstalmentNo As String, InstAmt As Decimal)
Dim StrConn As String = My.Settings.ImportLinkCS
Dim CN = New SqlConnection(StrConn)
CN.Open()
Dim StrSql As String = "Select * from Invoice Where AMTUNMATCHED <> 0 order by transdate, TransNo"
Dim cmdReader As SqlCommand = New SqlCommand(StrSql, CN)
cmdReader.CommandType = CommandType.Text
Dim SdrReader As SqlDataReader = cmdReader.ExecuteReader(CommandBehavior.CloseConnection)
'SdrReader = cmdReader.ExecuteReader
Try
With SdrReader
If .HasRows Then
While .Read
If .Item("Amtunmatched") > InstAmt Then
Modws.UpdateItem("Update Invoice set amtmatched = amtmatched + " & InstAmt & ",amtunmatched = amtunmatched - " & InstAmt & " Where TransNo = '" & .Item("TransNo") & "'")
Modws.UpdateItem("Insert into Matching(Invoice,Instalment,Amtmached,InvOutstanding) " + _
"Values('" & .Item("TransNo") & "','" & InstalmentNo & "', " & InstAmt & "," & (.Item("Amtunmatched") - InstAmt) & " )")
Exit Sub
Else
Modws.UpdateItem("Update Invoice set amtmatched = Total,amtunmatched = 0 Where TransNo = '" & .Item("TransNo") & "'")
Modws.UpdateItem("Insert into Matching(Invoice,Instalment,Amtmached,InvOutstanding) " + _
"Values('" & .Item("TransNo") & "','" & InstalmentNo & "'," & .Item("AMTUNMATCHED") & ",0 )")
InstAmt = InstAmt - .Item("Amtunmatched")
End If
End While
End If
End With
Catch ex As System.Exception
MsgBox(ex.Message, MsgBoxStyle.Critical, "Error")
End Try
End Sub
Private Sub btnReset_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnReset.Click
Modws.DeleteItem("Delete from Instalment")
Modws.DeleteItem("Delete from Matching")
Modws.UpdateItem("Update Invoice set amtmatched = 0, amtunmatched = Total")
End Sub
End Class
You also need to add a module class in your program
Imports System.Data
Imports System.Data.SqlClient
Imports ImportLink.GridPrintPreviewLib
Module Modws
Public Function GetDecimalFromQuery(ByVal SQLQuery As String) As Decimal
Dim StrConn As String = My.Settings.ImportLinkCS
Dim CN = New SqlConnection(StrConn)
GetDecimalFromQuery = 0
CN.Open()
Dim StrSql As String = SQLQuery
Dim cmdReader As SqlCommand = New SqlCommand(StrSql, CN)
cmdReader.CommandType = CommandType.Text
Dim SdrReader As SqlDataReader = cmdReader.ExecuteReader(CommandBehavior.CloseConnection)
'SdrReader = cmdReader.ExecuteReader
'GetDoubleFromQuery = 0
Try
With SdrReader
If .HasRows Then
While .Read
If .GetValue(0) Is DBNull.Value Then
'GetDoubleFromQuery = 20
'MsgBox("Null Value")
Else
If IsDBNull(.GetValue(0).ToString) Then
'GetDoubleFromQuery = 50
'MsgBox("Null Value")
Else
GetDecimalFromQuery = .GetValue(0).ToString
End If
End If
End While
Else
'MsgBox("No Row")
End If
End With
CN.Close()
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Exclamation, "Error")
End Try
End Function
Public Sub UpdateItem(ByVal SqlQuery As String)
Dim StrConn As String = My.Settings.ImportLinkCS
Dim CN = New SqlConnection(StrConn)
Try
CN.Open()
Dim StrSql As String = SqlQuery
Dim cmdupdate As New SqlCommand(StrSql, CN)
cmdupdate.CommandText = StrSql
cmdupdate.ExecuteNonQuery()
Catch ex As Exception
MsgBox(ex.Message & SqlQuery, MsgBoxStyle.Exclamation, "Error-UpdateItem")
End Try
CN.Close()
CN = Nothing
End Sub
Public Sub DisplayDataGrid(ByVal dgv As DataGridView, ByVal SQLSTR As String)
dgv.DataSource = Nothing
Try
Dim dbBindSource As New BindingSource
Dim strCon As String = My.Settings.ImportLinkCS
Dim strSQL As String = SQLSTR
Dim dataAdapter As SqlDataAdapter = New SqlDataAdapter(strSQL, strCon)
Dim commandBuilder As SqlCommandBuilder = New SqlCommandBuilder(dataAdapter)
'Populate a new data table and bind it to the BindingSource.
Dim table As DataTable = New DataTable()
table.Locale = System.Globalization.CultureInfo.InvariantCulture
dataAdapter.Fill(table)
dbBindSource.DataSource = table
'Resize the DataGridView columns to fit the newly loaded content.
dgv.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCellsExceptHeader)
dgv.DataSource = dbBindSource
dgv.Columns(2).Width = 200
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Critical, "error")
End Try
End Sub
End Module
And This is the result I'm getting
I have tried and it is working fine. In addition, you just need to add customer parameter so that it will process base on the customer.
Hello I have a simple method to update customer details in one of my database tables however when i try to update it an error occurs saying the database is locked. I have no idea how to fix this because my add and delete queries work just fine.
This is the error message:
System.Data.SQLite.SQLiteException: 'database is locked
database is locked'
Public Sub updateguest(ByVal sql As String)
Try
con.Open()
With cmd
.CommandText = sql
.Connection = con
End With
result = cmd.ExecuteNonQuery
If result > 0 Then
MsgBox("NEW RECORD HAS BEEN UPDATED!")
con.Close()
Else
MsgBox("NO RECORD HASS BEEN UPDATDD!")
End If
Catch ex As Exception
MsgBox(ex.Message)
Finally
con.Close()
End Try
End Sub
Private Sub IbtnUpdate_Click(sender As Object, e As EventArgs) Handles ibtnUpdate.Click
Dim usql As String = "UPDATE Customers SET fname = '" & txtFName.Text & "'" & "WHERE CustomerID ='" & txtSearchID.Text & "'"
updateguest(usql)
End Sub
Private Sub IbtnSearch_Click(sender As Object, e As EventArgs) Handles ibtnSearch.Click
Dim sSQL As String
Dim newds As New DataSet
Dim newdt As New DataTable
Dim msql, msql1 As String
Dim con As New SQLiteConnection(ConnectionString)
con.Open()
msql = "SELECT * FROM Customers Where Fname Like '" & txtSearchName.Text & "%'"
msql1 = "SELECT * FROM Customers Where CustomerID '" & txtSearchID.Text & "'"
Dim cmd As New SQLiteCommand(msql, con)
Dim cmd1 As New SQLiteCommand(msql1, con)
Dim dt = GetSearchResults(txtSearchName.Text)
dgvCustomerInfo.DataSource = dt
Dim mdr As SQLiteDataReader = cmd.ExecuteReader()
If mdr.Read() Then
If txtSearchName.Text <> "" Then
sSQL = "SELECT * FROM customers WHERE fname LIKE'" & txtSearchName.Text & "%'"
Dim con1 As New SQLiteConnection(ConnectionString)
Dim cmd2 As New SQLiteCommand(sSQL, con1)
con1.Open()
Dim da As New SQLiteDataAdapter(cmd2)
da.Fill(newds, "customers")
newdt = newds.Tables(0)
If newdt.Rows.Count > 0 Then
ToTextbox(newdt)
End If
dgvCustomerInfo.DataSource = newdt
con1.Close()
txtSearchID.Clear()
ElseIf txtSearchID.Text <> "" Then
sSQL = "SELECT * FROM customers WHERE CustomerID ='" & txtSearchID.Text & "'"
Dim con2 As New SQLiteConnection(ConnectionString)
Dim cmd2 As New SQLiteCommand(sSQL, con2)
con2.Open()
Dim da As New SQLiteDataAdapter(cmd2)
da.Fill(newds, "customers")
newdt = newds.Tables(0)
If newdt.Rows.Count > 0 Then
ToTextbox(newdt)
End If
dgvCustomerInfo.DataSource = newdt
con2.Close()
txtSearchName.Clear()
End If
Else
MsgBox("No data found")
End If
End Sub
Private Sub IbtnDelete_Click(sender As Object, e As EventArgs) Handles ibtnDelete.Click
Dim dsql As String = "DELETE FROM customers WHERE customerid = " & txtSearchID.Text & ""
deleteme(dsql)
updatedgv(dgvCustomerInfo)
txtSearchID.Clear()
txtSearchName.Clear()
End Sub
Public Sub deleteme(ByVal sql As String)
Try
con.Open()
With cmd
.CommandText = sql
.Connection = con
End With
result = cmd.ExecuteNonQuery
If result > 0 Then
MsgBox("NEW RECORD HAS BEEN DELTED!")
con.Close()
Else
MsgBox("NO RECORD HASS BEEN DELTED!")
End If
Catch ex As Exception
MsgBox(ex.Message)
Finally
con.Close()
End Try
End Sub
You made a good start on keeping your database code separate from you user interface code. However, any message boxes should be shown in the user interface and any sql statements should be written in the data access code.
I used Using...End Using blocks to ensure that database objects are closed and disposed. I used parameters to protect against sql injection. I am not too sure of the mapping of DbType types to Sqlite types. You might have to fool with that a bit. In you original Update statement you had the ID value in quotes. This would pass a string. When you use parameters, you don't have to worry about that or ampersands and double quotes. Just one clean string.
Private ConStr As String = "Your connection string"
Public Function updateguest(FirstName As String, ID As Integer) As Integer
Dim Result As Integer
Dim usql As String = "UPDATE Customers SET fname = #fname WHERE CustomerID = #ID;"
Using con As New SQLiteConnection(ConStr),
cmd As New SQLiteCommand(usql, con)
cmd.Parameters.Add("#fname", DbType.String).Value = FirstName
cmd.Parameters.Add("#ID", DbType.Int32).Value = ID
con.Open()
Result = cmd.ExecuteNonQuery
End Using
Return Result
End Function
Private Sub IbtnUpdate_Click(sender As Object, e As EventArgs) Handles ibtnUpdate.Click
Try
Dim Result = updateguest(txtFName.Text, CInt(txtSearchID.Text))
If Result > 0 Then
MsgBox("New RECORD HAS BEEN UPDATED!")
Else
MsgBox("NO RECORD HAS BEEN UPDATDD!")
End If
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
I'm making a POS system. in that, I have to include the top 3 selling products with quantity on the dashboard which is I'm unable to figure out how to do it. please help me to do the coding and the data should retrieve form access database.
This is what I did to get the top 1 selling Item. I need to get top 2nd item and 3rd item also.
Any help
Image of the result expectation
con = New OleDbConnection(cs)
con.Open()
Dim ct As String = "SELECT TOP 3 ProductName, Sum(Quantity) as Quantity FROM ProductSoldDB group by ProductName order by SUM(Quantity)"
cmd = New OleDbCommand(ct, con)
rdr = cmd.ExecuteReader()
While rdr.Read
lblProduct1Name.Text = rdr("ProductName")
lblQTYProduct1.Text = rdr("Quantity")
End While
If Not rdr Is Nothing Then
rdr.Close()
End If
con.Close()
#Always_a_learner did the hard work of getting a working Select statment.
I do not like to hold a connection open while I update the user interface. So, I filled a DataTable and passed it to the Button.Click thereby separating data access code from the user interface.
Connections and commands need to be disposed in addition to closed so use Using...End Using blocks.
Private Function RetrieveData() As DataTable
Dim sql = "SELECT TOP 10 ProductName, Sum(Quantity) as Quantity FROM ProductSoldDB Group By ProductName Order By SUM(Quantity)"
Dim dt As New DataTable
Using cn As New OleDbConnection("Your connection string"),
cmd As New OleDbCommand(sql, cn)
cn.Open()
dt.Load(cmd.ExecuteReader)
End Using
Return dt
End Function
I created an array of Labels so we could loop through to fill from the DataTable. i is the index of the row, incremented by one on each iteration.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim dt = RetrieveData()
Dim LabelsToFill = {Label1, Label2, Label3, Label4, Label5, Label6, Label7, Label8, Label9, Label10}
Dim i As Integer
For Each l As Label In LabelsToFill
l.Text = $"{dt.Rows(i)("ProductName")} - {dt.Rows(i)("Quantity")}"
i += 1
Next
End Sub
To fill 2 different labels, one for the quantity and one for the name...
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim dt = RetrieveData()
Dim QuanityLabels = {QLabel1, QLabel2, QLabel3, QLabel4, QLabel5, QLabel6, QLabel7, QLabel8, QLabel9, QLabel10}
Dim NameLabels = {NLabel1, NLabel2, NLabel3, NLabel4, NLabel5, NLabel6, NLabel7, NLabel8, NLabel9, NLabel10}
Dim i As Integer
For i = 0 To 9
NameLabels(i).Text = dt.Rows(i)("ProductName").ToString
QuanityLabels(i).Text = dt.Rows(i)("Quantity").ToString
Next
End Sub
EDIT
Re: The $. The $ indicates the beginning of an interpolated string which allows variables to be directly embedded if surrounded by braces { }. This became available in vb.net with Visual Studio 2015. In previous versions you can use String.Format for the same result.
l.Text = String.Format("{0} - {1})", dt.Rows(i)("ProductName"), dt.Rows(i)("Quantity"))
let's say you have 3 panel to show top 3 selling products and each panel have level in such way:
Panel 1 - label product name - lblProduct1Name , label Quanity name -lblQTYProduct1
Panel 2 - label product name - lblProduct2Name , label Quanity name -lblQTYProduct2
Panel 3 - label product name - lblProduct3Name , label Quanity name -lblQTYProduct3
We would get lblProductName and lblQTYProduct in each iteration and set value for
them.
Final code below:
con = New OleDbConnection(cs)
con.Open()
Dim ct As String = "SELECT TOP 3 ProductName, Sum(Quantity) as Quantity FROM ProductSoldDB group by ProductName order by SUM(Quantity) Desc"
cmd = New OleDbCommand(ct, con)
rdr = cmd.ExecuteReader()
Dim index As Integer = 1
While rdr.Read
Dim ctrlProduct As Control = Me.Controls.Find("lblProduct" + index.ToString() + "Name", True).FirstOrDefault()
ctrlProduct.Text = rdr("ProductName")
Dim ctrlQuantity As Control = Me.Controls.Find("lblQTYProduct" + index.ToString(), True).FirstOrDefault()
ctrlQuantity.Text = rdr("Quantity").ToString()
index = index + 1
End While
If Not rdr Is Nothing Then
rdr.Close()
End If
con.Close()
Output Here- change look and feel according to your requirement :
Here is the final code that solved my Problem with #mary 's help
Private Function RetrieveData() As DataTable
Dim sql = "SELECT TOP 3 ProductName, Sum(Quantity) as Quantity FROM ProductSoldDB group by ProductName order by Sum(Quantity) DESC"
Dim dt As New DataTable
Using cn As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\User\Desktop\EME.accdb;Persist Security Info=False;"),
cmd As New OleDbCommand(sql, cn)
cn.Open()
dt.Load(cmd.ExecuteReader)
End Using
Return dt
End Function
Private Sub Load_TopSellingProducts()
Dim dt = RetrieveData()
Dim QuanityLabels = {lblQTYProduct1, lblQTYProduct2, lblQTYProduct3}
Dim NameLabels = {lblProductName1, lblProductName2, lblProductName3}
Dim i As Integer
For i = 0 To 2
NameLabels(i).Text = dt.Rows(i)("ProductName").ToString
QuanityLabels(i).Text = dt.Rows(i)("Quantity").ToString
Next
End Sub
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Load_TopSellingProducts()
End Sub
And Finally, I got the result as I expected
Result
how to insert and update data in database(sql server) with single button in vb.net i tried but not get the result.
here is my code.......
Private Sub Button5_Click(sender As System.Object, e As System.EventArgs) Handles Button5.Click
Try
Dim reader As SqlDataReader
Dim query As String
Dim n As Integer
n = 0
sqlcom1 = New SqlCommand("select * from mydatabase.masters")
sqlcom1.ExecuteReader()
sqlcom = New SqlCommand("select * from mydatabase.masters")
sqlcom.ExecuteReader()
reader = sqlcom1.ExecuteReader
reader = sqlcom.ExecuteReader
sqlcom = New SqlCommand("Update masters SET EmpName=#EmpName, Age=#Age, Address=#Address where Empid=#Empid", conn)
sqlcom.Parameters.Add("#EmpName", SqlDbType.VarChar).Value = TextBox4.Text
sqlcom.Parameters.Add("#Age", SqlDbType.Int).Value = TextBox3.Text
sqlcom.Parameters.Add("#Address", SqlDbType.VarChar).Value = TextBox2.Text
sqlcom.Parameters.Add("#Empid", SqlDbType.Int).Value = TextBox1.Text
sqlcom1 = New SqlCommand("insert into masters(Empid, EmpName, Age, Address) values(#Empid, #EmpName, #Age, #Address)", conn)
sqlcom1.Parameters.AddWithValue("#Empid", TextBox1.Text)
sqlcom1.Parameters.AddWithValue("#EmpName", TextBox4.Text)
sqlcom1.Parameters.AddWithValue("#Age", TextBox3.Text)
sqlcom1.Parameters.AddWithValue("#Address", TextBox2.Text)
conn.Open()
While reader.Read
n = n + 1
End While
If table.Rows.Count = n Then
sqlcom1.ExecuteNonQuery()
ElseIf table.Rows.Count = n + 1 Then
sqlcom.ExecuteNonQuery()
End If
Catch ex As Exception
MessageBox.Show("error" + ex.Message)
End Try
End Sub
Using block ensures that your connection object is closed and disposed even if there is an error.
Normally I put comments in line but the code got so cluttered that had to move most of them up here. I hope you can figure out where they belong.
Dim reader As SqlDataReader - Unused
Dim query As String - Unused
Integers are automatically initialized to zero
Pass the query and the connection to the constructor of the command.
Your connection string will tell SQL Server what database to use. It is not necessary in the query.
Apparently all you want is the count, not all the data.
This query is exactly the same as sqlcom1
Dim sqlcom As New SqlCommand("select * from mydatabase.masters", cn)
sqlcom.ExecuteReader()
You did this twice
reader = sqlcom1.ExecuteReader
Not necessay, we already retrieved the count
`While reader.Read
n = n + 1
End While`
I made the assumption that table was a DataTable populated at some other time. Using the count as comparison to the count in the table is not a great way to determine if the command is Insert or Update but it might work as long as database and table were not used with a DataAdapter that updated the database.
Private Sub Button5_Click(sender As System.Object, e As System.EventArgs) Handles Button5.Click
Try
Dim n As Integer
Using cn As New SqlConnection("Your connection string")
Dim sqlcom1 As New SqlCommand("select Count(*) from masters", cn)
cn.Open()
n = CInt(sqlcom1.ExecuteScalar) 'n is now the number of rows in the database table
Dim sqlcom As New SqlCommand
sqlcom.Parameters.Add("#EmpName", SqlDbType.VarChar).Value = TextBox4.Text
'Age is not a good idea to enter in a database. It changes over time.
'Enter the birth date and calculate the age as needed.
sqlcom.Parameters.Add("#Age", SqlDbType.Int).Value = CInt(TextBox3.Text)
sqlcom.Parameters.Add("#Address", SqlDbType.VarChar).Value = TextBox2.Text
If table.Rows.Count > n Then
'Normally EmpId would be an auto increment (identity) field
'and would NOT be included in an insert.
sqlcom.CommandText = "insert into masters(EmpName, Age, Address) values(#EmpName, #Age, #Address)"
Else
sqlcom.CommandText = "Update masters SET EmpName=#EmpName, Age=#Age, Address=#Address where Empid=#Empid"
sqlcom1.Parameters.Add("#Empid", SqlDbType.Int).Value = CInt(TextBox1.Text)
End If
sqlcom.ExecuteNonQuery()
End Using
Catch ex As Exception
MessageBox.Show("error" + ex.Message)
End Try
End Sub
On second thought, forget the whole thing. Use a DataGridView and a DataAdapter. Then you can just use Update and it will update, insert and delete.