Creating receipt number in vb.net and save into mysql database - mysql

How to create receipt number like this "BSP000001" and in the next load of the receipt form, the receipt number will be "BSP000002" and save again to database..I'm using vb2010 and MySql database...It is just like auto increment receipt number in my database table.
And I really don't know how to make it.
It looks like this to my transaction table and I want show for Receipt_No column only, just to figure out..
Receipt_No
BSP000001
BSP000002
BSP000003
badly needed your help, to anyone who read this post...Big Please for Mr and Mrs Programmers outside the world..I Thankyou..

In a single user scenario, usually you could use the MAX function or order your receipts in DESCENDING order to find the last inserted one. Once you have this last record it is easy to extract the numeric part, increase the value by one and build the new receipt_no
Function GetNewReceiptNumber(prefix as string ) as String
using cn = new MySqlConnection(connectionstring)
using cmd = cn.CreateCommand()
cn.Open()
cmd.CommandText = "select receipt_no from receipts order by receipt_no DESC limit 1"
Dim result = cmd.ExecuteScalar
if result IsNot DbNull.Value AndAlso result IsNot Nothing Then
Dim number = Convert.ToInt32(result.ToString().SubString(prefix.Length))
return prefix & (number + 1).ToString("D6")
else
return prefix & "000001"
End If
End Using
End Using
End Function
or perhaps it is better to use MAX(receipt_no) for a slightly faster performance (but you really need to have an index of receipt_no)
cmd.CommandText = "select MAX(receipt_no) from receipts"
You could call this method from the code that tries to insert a new receipt in this way
Dim newReceiptNumber = GetNewReceiptNumber("BSP")
In this answer there are some assumptions:
You have a global variable that keeps the details of your connection
string to MySql called connectionstring
The name of the table where you store the receipts is called
receipts

Related

Comparing values in a DataGridView against MySQL if they share the same ID

I'm trying to compare a value in one column in a DataGridView against a column in a MySQL Table using an "ID". The way I'm approaching this as the program cycles through the DataGridView, it will pull up the amount of stock in MySQL, put it into a textbox and compare it to the amount in the DataGridView. If the number is bigger in the DataGridView, a text box will say: "Stock falls below 0". If the number is bigger in the MySQL table, the text box will say "Stock remains above or equals 0" instead.
I'll highlight the exact line below but when I try to run the code, this error pops up:
MySql.Data.MySqlClient.MySqlException: 'Invalid attempt to access a field before calling Read()'
I'm not sure why this error appearing. I use very similar code in other parts of my project with no complaints.
This is my attempt:
Dim cmd As MySqlCommand
Dim READER As MySqlDataReader
For i = 0 To DataGridView1.Rows.Count - 1
Dim Query As String
Query = "SELECT Quantity FROM `database`.`stockroom` WHERE `ID`='#Stock'"
COMMAND = New MySqlCommand(Query, MysqlConn)
READER = COMMAND.ExecuteReader
Sum_Quantity.Text = READER.GetString("Quantity") 'Error appears here
If Sum_Quantity.Text >= DataGridView1.Rows(i).Cells(4).Value.ToString() Then 'IF STOCK REMAINS ABOVE OR EQUAL TO 0
Sum_Outcome.Text = "Stock remains above or equals 0"
ElseIf Sum_Result.Text <= DataGridView1.Rows(i).Cells(4).Value.ToString() Then 'IF STOCK REACHES BELOW 0
Sum_Outcome.Text = "Stock falls below 0"
End If
Next
Open your connection.
Swap your ExecuteReader call for ExecuteScalar and capture it into an integer - Dim qty = Convert.ToInt32(COMMAND.ExecuteScalar())
Don't compare strings using >= and <= - it will go wrong because "10" is less than "2" - take the quantity from the grid as an integer, and compare it with the integer from the database
The code as you have it there is almost pointless because if will loop, say, 100 roows, change the textbox 100 times so fast that you'll only see the last change...
Were it my problem I'd maybe do it more like this:
'imagine your grid is based on a datatable with the order info in
dt.Rows.Add("Apples", 1)
dt.Rows.Add("Pears", 2)
dt.Rows.Add("Bananas", 4)
'show the order in the grid
datagridviewX.DataSource = dt
So imagine that's where you've got to now, above. It would help us if the DGV was looking at a table that had a couple more columns:
'add another columns to the table to hold the stock quantity and message
dt.Columns.Add("Stock", GetType(Integer))
dt.Columns.Add("Determination").Expression = "IIF([Quantity]>[Stock],'Not enough stock','Can fulfil this order')"
Then when we want to analyze the order for being able to supply it:
'loop over the table looking up the stock quants
Using cmd as New MySqlCommand("SELECT Quantity FROM Stock WHERE ID = #id", "conn str here")
cmd.Parameters.AddWithValue("#id", "dummy value")
cmd.Connection.Open()
For Each ro as DataRow in dt.Rows
cmd.Parameters("#id").Value = ro("Name").ToString()
ro("Stock") = Convert.ToInt32(cmd.ExecuteScalar())
Next ro
End Using
So that code will pull the stock amounts for all the items in the grid and stash it in the Stock column. Separately an Expression on a string column gives a commentary on if there is enough stock or not.

Checking if the fund is sufficient

I am currently doing an ATM Management System, I want my program to check if the amount entered does not exceed the account's balance on database. Here is my code:
Dim w As Double
w = Val(txtwithdraw.Text)
adapter = New MySql.Data.MySqlClient.MySqlDataAdapter("SELECT `balance` FROM `jaagbank` WHERE
acctnum = '" & Form1.namebox.Text & "'", con)
dtable.Clear()
adapter.Fill(dtable)
If w > dtable.Rows.Count Then
MsgBox("Insufficient Balance")
txtwithdraw.Clear()
Return
End If
Decimal is a good datatype to used for money. Don't use the vb6 Val(). You can get unexpected results. Put Option Strict and Option Infer on. I used .TryParse to test the input in txtwithdraw. If it returns True, it puts the converted decimal value in WithdrawalAmount.
Keep your data objects local to the method where they are used. Connections and commands need to be closed and disposed. Using...End Using blocks handle this for us even if there is an error.
Always use parameters to avoid sql injection. If the code is running in Form1, do not qualify namebox with Form1. It seems a bit strange that a field named acctnum is not a number but a String containing a name. You will need to check your database for the correct datatype and field size. I had to guess.
Since you are retrieving a single piece of data, you can use .ExecuteScalar which will give you the first column of the first row.
Private Sub OPCode()
Dim WithdrawalAmount As Decimal
If Not Decimal.TryParse(txtwithdraw.Text, WithdrawalAmount) Then
MessageBox.Show("Please enter a valid withdrawal amount.")
Return
End If
Dim Balance As Object
Using con As New MySqlConnection(ConStr),
cmd As New MySqlCommand("SELECT `balance` FROM `jaagbank` WHERE acctnum = #Name;", con)
cmd.Parameters.Add("#Name", MySqlDbType.VarChar, 100).Value = Form1.namebox.Text
con.Open()
Balance = cmd.ExecuteScalar
End Using
If Balance Is Nothing Then
MessageBox.Show("Account not recognized.")
Return
End If
If WithdrawalAmount > CDec(Balance) Then
MsgBox("Insufficient Balance")
txtwithdraw.Clear()
Return
End If
End Sub

Delete command using ID from DataGridView

I have data shown in DataGridView. I made a Button when selecting IDs in the grid the code below runs but I keep getting an error.
Dim cnx As New MySqlConnection("datasource=localhost;database=bdgeststock;username=root;password=")
Dim cmd As MySqlCommand = cnx.CreateCommand
Dim resultat As Integer
If ConnectionState.Open Then
cnx.Close()
End If
cnx.Open()
If grid.SelectedCells.Count = 0 Then
MessageBox.Show("please select the ids that u want to delete")
Else
cmd.CommandText = "delete from utilisateur where idu= #P1"
cmd.Parameters.AddWithValue("#P1", grid.SelectedCells)
resultat = cmd.ExecuteNonQuery
If (resultat = 0) Then
MessageBox.Show("error")
Else
MessageBox.Show("success")
End If
End If
cnx.Close()
cmd.Dispose()
How does this make sense?
cmd.Parameters.AddWithValue("#P1", grid.SelectedCells)
As you tagged this question WinForms, you are presumably using a DataGridView rather than a DataGrid (names matter so use the right ones). In that case, the SelectedCells property is type DataGridViewSelectedCellCollection. How does it make sense to set your parameter value to that? How is that going to get compared to an ID in the database?
If you expect to use the values in those cells then you have to actually get those values out. You also need to decide whether you're going to use a single value or multiple. You are using = in your SQL query so that means only a single value is supported. If you want to use multiple values then you would need to use IN and provide a list, but that also means using multiple parameters. I wrote an example of this type of thing using a ListBox some time ago. You can find that here. You could adapt that code to your scenario like so:
Dim connection As New SqlConnection("connection string here")
Dim command As New SqlCommand
Dim query As New StringBuilder("DELETE FROM utilisateur")
Select Case grid.SelectedCells.Count
Case 1
query.Append(" WHERE idu = #idu")
command.Parameters.AddWithValue("#idu", grid.SelectedCells(0).Value)
Case Is > 1
query.Append(" WHERE idu IN (")
Dim paramName As String
For index As Integer = 0 To grid.SelectedCells.Count - 1 Step 1
paramName = "#idu" & index
If index > 0 Then
query.Append(", ")
End If
query.Append(paramName)
command.Parameters.AddWithValue(paramName, grid.SelectedCells(index).Value)
Next index
query.Append(")")
End Select
command.CommandText = query.ToString()
command.Connection = connection
SelectedCells is a collection of cells
so it never can be only one id, so you have to guess which was you want or only allow one row to be selected
grid.SelectedCells(0).Value.ToString()
Or you have to program a loop to delete all selected rows

Populating ListBox More Quickly

Is there a way to make populating ListBox fast, because the UI is freezing on form load upon populating the ListBox?
This is my form load code:
Dim abc As String = itemCount()
Dim output = Account_Get(a)
For Each s In output
ListBox1.Items.Add(s)
count1 += 1
If count1 = abc Then
ListBox1.Visible = True
End If
Next
This is the query in module:
Public Function Account_Get(ByVal chk As String) As List(Of String)
Dim result = New List(Of String)()
Try
cn.Open()
sql = "select column_name as str from table where status = 'New' order by rand()"
cmd = New MySqlCommand(sql, cn)
dr = cmd.ExecuteReader
While dr.Read
result.Add(dr("str").ToString())
End While
Return result
Catch ex As Exception
MsgErr(ex.Message, "Error Encounter")
Return Nothing
Finally
cn.Close()
End Try
End Function
this is working fine. but the fact that it loads too many datas. the ui is freezing on load. hoping someone could help me with this. thanks!
Since you are incrementing count1 I assume it is some sort of number. However, you are then comparing it to a string in the If statement. Please use Option Strict.
Changed the Function to return an Array of String. Took the random sort form the sql statement and moved it to a little linq at the end or the function.
You could add a Stopwatch to the data retrieval and the display sections to see where your bottleneck is. BeginUpdate and EndUpdate on the listbox prevents repainting on every addition.
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim output = Account_Get()
ListBox2.BeginUpdate()
ListBox2.Items.AddRange(output)
ListBox2.EndUpdate()
End Sub
Private Rand As New Random
Public Function Account_Get() As String()
Dim dt As New DataTable
Dim result As String()
Using cn As New MySqlConnection("Your connection string")
Dim Sql = "select column_name as str from table where status = 'New'" 'order by rand()"
Using cmd = New MySqlCommand(Sql, cn)
Try
cn.Open()
dt.Load(cmd.ExecuteReader)
Catch ex As Exception
MessageBox.Show(ex.Message, "Error Encounter")
Return Nothing
End Try
End Using
End Using
result = (From dRow In dt.AsEnumerable()
Let field = dRow("str").ToString
Order By Rand.Next
Select field).ToArray
Return result
End Function
The query you are using contains a random order. Ordering records randomly can be a huge performance issue within MySQL as it has to go through all records in the table and then sort them randomly. The more records in the table, the bigger the performance penalty. There is also no limitation on the number of records in your query. So if there are thousands of items in your table the listbox will also be thousands of items in size, which could also take a long time.
If you really require the random ordering you could do something about it in your code. I'm now assuming here that you are: 1) using identifiers in your table, 2) you actually wish to limit the number of items in your listbox and not display all of them.
Get a grasp of the total number of records in the table by a query
Pick a random number from the range of items in your table
Fetch the nearest record
Hope this helps you to get going to find a solution

How can I query by an value which is segmented, as 123-456-789 in mysql in vb.net?

My problem is, when I query by a usual ID, like number with no segments = 1234567890, it works nicely.
But I need to query by some kind of segmented values or ID as = 123-4567-890, when I try by 123-4567-890 this id it does not query anything in mysql although in the database this 123-4567-890 ID is present.
So what is the possible solution to search by segmented value in mysql in VB.NET
Here is below, my trying codes in vb
Public Sub student()
textbox1.text= "123-4567-890"
Try
dbConn()
Dim myAdapter As New MySqlDataAdapter("Select studentID, batchID, studentStatus from student where studentID= " & textbox1.text, ServerString)
Dim myDataTable As New DataTable
myAdapter.Fill(myDataTable)
If myDataTable.Rows.Count > 0 Then
vrSID = myDataTable.Rows(0).Item("studentID")
vrRecBatchID = myDataTable.Rows(0).Item("batchID")
vrAttendanceStatus = myDataTable.Rows(0).Item("studentStatus")
If vrSID = vrIDD Then
If vrAttendanceStatus = "Active" Then
Console.Beep()
batchRoutine()
Else
led3()
Console.Beep()
End If
End If
Else
Console.Beep()
teacher()
End If
Catch ex As Exception
Console.Beep()
MsgBox ("Error")
End Try
End Sub
When you are running into problems, the easiest way to solve them is to break things down to the simplest scenario. So instead of complicating things with table adapters and data tables, see what happens when you just send MySQL the query you 'think' works correctly.
So start out by seeing if you can get this to work, then go from there:
Dim sql As String = "select id from mytable where id = '123-4567-890'"
Using cnx As New MySqlConnection("connection_string")
Using cmd As New MySqlCommand(sql, cnx)
cnx.Open()
Using reader As MySqlDataReader = cmd.ExecuteReader()
Debug.Assert(reader.Read(), "No results")
Trace.WriteLine(reader.GetValue(reader.Item(0)))
End Using
End Using
End Using
if the column is in-fact a sort of student ID column (not social security I would expect), and the table has it without special characters, I would pre-strip the extra formatting (hyphens) from the string and pass the CLEANED value to the query as a parameter to get results.
Also, by explicitly adding the query string Plus the text box value, you are leaving yourself WIDE OPEN to sql injection. Look into Parameterized queries (my guess is it would be an object something like MySqlDataParameter data type.)