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()
Related
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
Imports System.Data.SqlClient
Public Class Form2
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim A As New SqlConnection
Dim cmdd As New SqlCommand
Dim R As SqlDataReader
A.ConnectionString = "Data Source=(LocalDB)\v11.0;AttachDbFilename=C:\Users\SurAj\AppData\Local\Temporary Projects\RPS\connectivity.mdf;Integrated Security=True"
A.Open()
cmdd.Connection = A
cmdd.CommandType = CommandType.Text
cmdd.CommandText = "select * from T where emailid='" & emailid.Text & "' "
R = cmdd.ExecuteReader
If R.HasRows Then
MsgBox("ADD Another Email Id", MsgBoxStyle.Critical, "Error: Try Again")
A.Close()
Else
A.Close()
A.Open()
cmdd = New SqlCommand("INSERT INTO T values('" & fullnames.Text & "','" & emailid.Text & "','" & loginU.Text & "','" & loginP.Text & "')", A)
If (fullnames.Text = String.Empty Or emailid.Text = String.Empty Or loginU.Text = String.Empty Or loginP.Text = String.Empty) Then
MessageBox.Show("You missed some details", "ERROR")
Else
cmdd.ExecuteNonQuery()
MsgBox("Successfully registered.", MsgBoxStyle.Information, "Success")
Me.Hide()
Form3.Show()
fullnames.Clear()
emailid.Clear()
loginU.Clear()
loginP.Clear()
End If
A.Close()
End If
A.Close()
' Catch ex As Exception
'MsgBox("Error")
'End Try
End Sub
End Class
I get an error at cmdd.ExecuteNonQuery:
An unhandled exception of type 'System.Data.SqlClient.SqlException' occurred in System.Data.dll
Additional information: Column name or number of supplied values does not match table definition.
even though all columns are mentioned. What's wrong? I'm not getting it.
Your table is defined as:
CREATE TABLE [dbo].[T]
(
[Id] INT NOT NULL,
[fullnames] VARCHAR(50) NOT NULL,
[emailid] VARCHAR(50) NOT NULL,
[loginU] VARCHAR(50) NOT NULL,
[loginP] VARCHAR(50) NOT NULL
);
and your insert statement only inserts value for fullnames, emailid, loginU and loginP - but NOT for Id:
cmdd = New SqlCommand("INSERT INTO T VALUES('" & fullnames.Text & "','" & emailid.Text & "','" & loginU.Text & "','" & loginP.Text & "')", A)
--> you're NOT proving values for all columns in your table.
Furthermore, as I mentioned in comments - you should NEVER EVER concatenate together your SQL statements like this - use parameters - ALWAYS!
Also, it is a generally accepted best practice to list your columns of the table you're inserting into.
So all in all, your insert statement should be something like:
string insertQry = #"INSERT INTO T (id, fullnames, emailid, loginU, loginP)
VALUES (#id, #fullnames, #emailid, #loginU, #loginP);";
cmdd.CommandText = insertQry;
// add the parameters and their values here
I have divided the code into user interface and data access. The user interface knows nothing about where the data is being sent. It could be Oracle, MS Access or even a text file. It doesn't matter to the user interface.
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
'Do your validation first
If fullnames.Text = String.Empty OrElse emailid.Text = String.Empty OrElse loginU.Text = String.Empty OrElse loginP.Text = String.Empty Then
MessageBox.Show("You missed some details", "ERROR")
Exit Sub
End If
Dim id As Integer 'I don't know where this value is coming from
Try
Dim inserts = InsertUser(id, fullnames.Text, emailid.text, loginU.Text, loginP.Text)
If inserts = 1 Then
MsgBox("Successfully registered.", MsgBoxStyle.Information, "Success")
Me.Hide()
Form3.Show()
fullnames.Clear()
emailid.Clear()
loginU.Clear()
loginP.Clear()
Else
MessageBox.Show("Addition not successful. The email already exists.")
End If
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
Likewise, the InsertUser function where the data is coming from. It could be a Web app, a WPF application or WinForms.
The command text combines checking if the email already exists in the database and the actually insert.
Using...End Using blocks ensure that your database objects are closed and disposed even it there is an error.
Always use Parameters. 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
Private Function InsertUser(id As Integer, name As String, email As String, user As String, pword As String) As Integer
Dim RecordsEntered As Integer
Dim sql = "If Not Exists(Select * From T Where emailid = #emailid)
Insert Into T (Id, fullnames, emailid, loginU, loginP)
Values (#Id, #fullnames, #emailid, #loginU, #loginP);"
Using A As New SqlConnection("Data Source=(LocalDB)\v11.0;AttachDbFilename=C:\Users\SurAj\AppData\Local\Temporary Projects\RPS\connectivity.mdf;Integrated Security=True"),
cmdd As New SqlCommand(sql, A)
With cmdd.Parameters
.Add("#Id", SqlDbType.Int).Value = id
.Add("#fullnames", SqlDbType.VarChar, 50).Value = name
.Add("#emailid", SqlDbType.VarChar, 50).Value = email
.Add("#loginU", SqlDbType.VarChar, 50).Value = user
.Add("#loginP", SqlDbType.VarChar, 50).Value = pword
End With
A.Open()
RecordsEntered = cmdd.ExecuteNonQuery 'Returns -1 if no records are inserted
End Using
Return RecordsEntered
End Function
Another problem which I did not is address is passwords. They should NEVER be stored as plain text. Have a look at encryption.
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
I have this sub in one form of my program to calculate and display a total profit from my database:
Public Sub Profit()
Try
Using connection As New OleDbConnection(connectionstring)
connection.Open()
Dim Command As New OleDbCommand("SELECT SUM(Price) FROM ItemsSold", connection)
Dim command2 As New OleDbCommand("SELECT SUM(TotalCost) FROM Inventory", connection)
Dim Turnover As Double = Convert.ToDouble(Command.ExecuteScalar())
Dim Cost As Double = Convert.ToDouble(command2.ExecuteScalar())
Dim TotalProfit As Double = Turnover - Cost
lblProfit.Text = "Profit: £" & TotalProfit
lblProfit2.Text = "Profit: £" & TotalProfit
lblProfit3.Text = "Profit: £" & TotalProfit
lblProfit4.Text = "Profit: £" & TotalProfit
connection.Close()
End Using
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
Also, in a different form of the program, I am updating a database table with a value provided by the user. What I want to do, is add this input value to this profit that is displayed in the label in the Profit() sub.
How can I go about doing this? Would I need to somehow make this profit variable a public shared variable to be able to access it in my other form? Is there another way to just increase this value and display the new increased variable?
How does shared variable supposed to help you?
you should to split functions which works with data and which works with form. In other words, when you need display data, you call GetProfit, and when you need to update profit you call SetProfit(ByVal profit As Double). And then use them in your project.
Based on your code, I suppose it should looks something like that
Public Sub GetProfit()
Dim profit As Double
Try
Using connection As New OleDbConnection(connectionstring)
connection.Open()
Dim Command As New OleDbCommand("SELECT SUM(Price) FROM ItemsSold", connection)
Dim command2 As New OleDbCommand("SELECT SUM(TotalCost) FROM Inventory", connection)
Dim Turnover As Double = Convert.ToDouble(Command.ExecuteScalar())
Dim Cost As Double = Convert.ToDouble(command2.ExecuteScalar())
Dim TotalProfit As Double = Turnover - Cost
profit = TotalProfit
connection.Close()
End Using
Catch ex As Exception
MsgBox(ex.Message)
End Try
' Return the result
return profit
End Sub
And for update
Public Sub SetProfit(ByVal newProfit As Double)
Try
Using connection As New OleDbConnection(connectionstring)
connection.Open()
' Commands for updating data (just for example)
Dim Command As New OleDbCommand("UPDATE ItemsSold SET Price = " & newProfit)
connection.Close()
End Using
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
And then you when you dealing with your form you just do like this
Private Sub Form1_Load()
Label1.Text = GetProfit()
Label2.Text = GetProfit()
End Sub
When you need to update
Private Sub Button1_Click()
SetProfile(GetProfit() + 5)
End
It is not exactly production code, just for an example
this my database table
id name
1 abc
2 xyz
it i enter 1 then respective value "abc" display in different text box???
Private Sub butsea_Click(sender As Object, e As EventArgs) Handles butsea.Click
Dim dset As New DataSet
Dim da As SqlDataAdapter
Dim myCmd As New SqlCommand
Try
myConn.ConnectionString = "Data Source=THEONE\PARTH;Initial Catalog=testdatabase;Integrated Security=True;"
myConn.Open()
Dim avalue As String = (InputBox("Input Student Id", "Search Student")).ToString
txt_id.Text = avalue
da = New SqlDataAdapter("SELECT * FROM studentdetails where student_id= '" & txt_id.Text & "", myConn)
If dset.Tables(0).Rows.Count > 0 Then
'what should i write here
Else
MsgBox("No Record Found")
End If
Catch ex As Exception
MsgBox(ex.Message)
Finally
myConn.Close()
End Try
End Sub
If you need to fetch just a single value - using DataAdapter and DataSet is overkill. Use SqlCommand.ExecuteScalar method and in your query instead of "SELECT * ..." do a "SELECT YOURFIELD ... ".
this way you don't have to jump thru hoops building a dataset, checking number of rows etc. and just check returned value for Nothing instead.
UPDATE Here is your code modified to use ExecuteScalar
Private Sub butsea_Click(sender As Object, e As EventArgs) Handles butsea.Click
Dim myCmd As SqlCommand
Dim myConn As New SqlConnection
Dim oResult As Object
Try
myConn.ConnectionString = "Data Source=THEONE\PARTH;Initial Catalog=testdatabase;Integrated Security=True;"
myConn.Open()
Dim avalue As String = (InputBox("Input Student Id", "Search Student")).ToString
txt_id.Text = avalue
myCmd = New SqlCommand("SELECT student_name FROM studentdetails where student_id= '" & txt_id.Text & "'", myConn)
oResult = myCmd.ExecuteScalar()
If oResult IsNot Nothing Then
txt_name.text = oResult.ToString
Else
MsgBox("No Record Found")
End If
Catch ex As Exception
MsgBox(ex.Message)
Finally
myConn.Close()
End Try
End Sub
This code assumes that database field that u need to display is called student_name and that you added TextBox called txt_name to your form.
You need to add other textboxes for every field you want to show.
(For example a textbox called txtStudentName could be used for the name, and so on for other fields present in the table studentdetails).
The correct way to query your database (leaving out other methods like using a SqlDataReader) should be the following
Dim dset As New DataSet
Dim da As SqlDataAdapter
Try
myConn.ConnectionString = "Data Source=THEONE\PARTH;Initial Catalog=testdatabase;Integrated Security=True;"
myConn.Open()
Dim avalue As String = (InputBox("Input Student Id", "Search Student")).ToString
txt_id.Text = avalue
' prepare the adapter with a commandtext. Do not use string concatenation from user input'
da = New SqlDataAdapter("SELECT * FROM studentdetails where student_id=#id", myConn)
da.SelectCommand.Parameters.AddWithValue("#id", txt_id.Text)
' Fill the dataset'
da.Fill(dset)
If dset.Tables(0).Rows.Count > 0 Then
' Supposing you have a field for the studentname in the first column of the returned
' datatable rows(rowindex)(columnindex)
txtStudentName.Txt = dset.Tables(0).Rows(0)(0).ToString()
.....
' Set the text property of other textboxes for other fields to show'
Else
MsgBox("No Record Found")
End If