: The Integer.TryParse block ensures typing mistakes (like scanning an invalid alphanumeric string into the quantity text box) are caught gracefully before sending errors to the database tier. 7. Adding Advanced Features (Optional Roadmap)
Here are the most valuable VB.NET billing source code repositories available for learning and customization:
: A ComboBox ( cmbCustomer ) to select the customer. Product Selection Section : vb.net billing software source code
End Sub
Developing a billing system is one of the most common projects for VB.NET developers, and with good reason—it's the perfect way to master database integration, user interface design, and business logic implementation. : The Integer
Add items to a data grid with real-time calculation of subtotals, tax, discounts, and grand totals.
Imports System.Data.SqlClient Imports System.Drawing.Printing Public Class FormBilling ' Define your SQL Server database connection string Dim connString As String = "Server=(localdb)\MSSQLLocalDB;Database=BillingDB;Trusted_Connection=True;" Dim conn As New SqlConnection(connString) ' Structure to hold temporary printing data Private invoiceIdToPrint As Integer = 0 Private Sub FormBilling_Load(sender As Object, e As EventArgs) Handles MyBase.Load LoadProducts() ResetForm() End Sub ''' ''' Fetches active items from the database and binds them to the product selection ComboBox. ''' Private Sub LoadProducts() Try Dim query As String = "SELECT ProductID, ProductName, Price FROM Products ORDER BY ProductName ASC" Dim adapter As New SqlDataAdapter(query, conn) Dim dt As New DataTable() adapter.Fill(dt) cmbProducts.DataSource = dt cmbProducts.DisplayMember = "ProductName" cmbProducts.ValueMember = "ProductID" cmbProducts.SelectedIndex = -1 txtPrice.Clear() Catch ex As Exception MessageBox.Show("Error loading products: " & ex.Message, "Database Error", MessageBoxButtons.OK, MessageBoxIcon.Error) End Try End Sub ' Update the price field automatically when a product is selected Private Sub cmbProducts_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cmbProducts.SelectedIndexChanged If cmbProducts.SelectedIndex <> -1 AndAlso TypeOf cmbProducts.SelectedValue Is DataRowView = False Then Dim drv As DataRowView = CType(cmbProducts.SelectedItem, DataRowView) txtPrice.Text = Convert.ToDecimal(drv("Price")).ToString("F2") txtQuantity.Text = "1" End If End Sub ''' ''' Adds the selected product and quantity into the DataGridView cart. ''' Private Sub btnAddItem_Click(sender As Object, e As EventArgs) Handles btnAddItem.Click If cmbProducts.SelectedIndex = -1 Then MessageBox.Show("Please select a product first.", "Input Validation", MessageBoxButtons.OK, MessageBoxIcon.Warning) Exit Sub End If Dim qty As Integer If Not Integer.TryParse(txtQuantity.Text, qty) OrElse qty <= 0 Then MessageBox.Show("Please enter a valid quantity greater than zero.", "Input Validation", MessageBoxButtons.OK, MessageBoxIcon.Warning) Exit Sub End If Dim prodId As Integer = Convert.ToInt32(cmbProducts.SelectedValue) Dim prodName As String = cmbProducts.Text Dim price As Decimal = Convert.ToDecimal(txtPrice.Text) Dim total As Decimal = price * qty ' Check if product already exists in the cart grid; if so, update quantity Dim itemExists As Boolean = False For Each row As DataGridViewRow In dgvInvoice.Rows If Convert.ToInt32(row.Cells("ProdID").Value) = prodId Then Dim currentQty As Integer = Convert.ToInt32(row.Cells("Qty").Value) row.Cells("Qty").Value = currentQty + qty row.Cells("Total").Value = (currentQty + qty) * price itemExists = True Exit For End If Next ' If item is unique to the current session, add it as a new row If Not itemExists Then dgvInvoice.Rows.Add(prodId, prodName, price.ToString("F2"), qty, total.ToString("F2")) End If CalculateInvoiceTotals() txtQuantity.Text = "1" cmbProducts.SelectedIndex = -1 txtPrice.Clear() End Sub ''' ''' Calculates Subtotal, Taxes, Discounts, and the final Grand Total in real-time. ''' Private Sub CalculateInvoiceTotals() Dim subTotal As Decimal = 0 For Each row As DataGridViewRow In dgvInvoice.Rows subTotal += Convert.ToDecimal(row.Cells("Total").Value) Next Dim taxPercent As Decimal = 0 Decimal.TryParse(txtTax.Text, taxPercent) Dim discountAmt As Decimal = 0 Decimal.TryParse(txtDiscount.Text, discountAmt) Dim taxAmount As Decimal = subTotal * (taxPercent / 100) Dim grandTotal As Decimal = (subTotal + taxAmount) - discountAmt txtSubTotal.Text = subTotal.ToString("F2") txtGrandTotal.Text = grandTotal.ToString("F2") End Sub ' Live calculation events when dynamic variables change Private Sub txtTax_TextChanged(sender As Object, e As EventArgs) Handles txtTax.TextChanged, txtDiscount.TextChanged CalculateInvoiceTotals() End Sub ''' ''' Validates UI input, saves transactions safely to database tables, updates stock, and prints. ''' Private Sub btnSavePrint_Click(sender As Object, e As EventArgs) Handles btnSavePrint.Click If String.IsNullOrWhiteSpace(txtCustomerName.Text) Then MessageBox.Show("Customer Name is required.", "Validation Error", MessageBoxButtons.OK, MessageBoxIcon.Warning) Exit Sub End If If dgvInvoice.Rows.Count = 0 Then MessageBox.Show("Cart is empty. Please add items to process the invoice.", "Validation Error", MessageBoxButtons.OK, MessageBoxIcon.Warning) Exit Sub End If Dim insertedInvoiceId As Integer = 0 ' Initialize SQL transaction logic for accurate state commitment Using connection As New SqlConnection(connString) connection.Open() Using transaction As SqlTransaction = connection.BeginTransaction() Try ' Insert Master Invoice Records Dim queryInvoice As String = "INSERT INTO Invoices (CustomerName, SubTotal, TaxAmount, Discount, GrandTotal) " & "OUTPUT INSERTED.InvoiceID " & "VALUES (@Customer, @Sub, @Tax, @Disc, @Grand);" Using cmdInv As New SqlCommand(queryInvoice, connection, transaction) cmdInv.Parameters.AddWithValue("@Customer", txtCustomerName.Text.Trim()) cmdInv.Parameters.AddWithValue("@Sub", Convert.ToDecimal(txtSubTotal.Text)) Dim taxPercent As Decimal = 0 Decimal.TryParse(txtTax.Text, taxPercent) Dim calculatedTaxObj As Decimal = Convert.ToDecimal(txtSubTotal.Text) * (taxPercent / 100) cmdInv.Parameters.AddWithValue("@Tax", calculatedTaxObj) cmdInv.Parameters.AddWithValue("@Disc", Convert.ToDecimal(txtDiscount.Text)) cmdInv.Parameters.AddWithValue("@Grand", Convert.ToDecimal(txtGrandTotal.Text)) insertedInvoiceId = CInt(cmdInv.ExecuteScalar()) End Using ' Insert Item Details & Update Live Inventory Counts For Each row As DataGridViewRow In dgvInvoice.Rows Dim pid As Integer = Convert.ToInt32(row.Cells("ProdID").Value) Dim prc As Decimal = Convert.ToDecimal(row.Cells("Price").Value) Dim qty As Integer = Convert.ToInt32(row.Cells("Qty").Value) Dim tot As Decimal = Convert.ToDecimal(row.Cells("Total").Value) ' 1. Write transactional line item records Dim queryDetails As String = "INSERT INTO InvoiceDetails (InvoiceID, ProductID, Price, Quantity, Total) " & "VALUES (@InvID, @ProdID, @Price, @Qty, @Tot);" Using cmdDet As New SqlCommand(queryDetails, connection, transaction) cmdDet.Parameters.AddWithValue("@InvID", insertedInvoiceId) cmdDet.Parameters.AddWithValue("@ProdID", pid) cmdDet.Parameters.AddWithValue("@Price", prc) cmdDet.Parameters.AddWithValue("@Qty", qty) cmdDet.Parameters.AddWithValue("@Tot", tot) cmdDet.ExecuteNonQuery() End Using ' 2. Deduct active stock levels safely Dim queryStock As String = "UPDATE Products SET StockQty = StockQty - @Qty WHERE ProductID = @ProdID" Using cmdStock As New SqlCommand(queryStock, connection, transaction) cmdStock.Parameters.AddWithValue("@Qty", qty) cmdStock.Parameters.AddWithValue("@ProdID", pid) cmdStock.ExecuteNonQuery() End Using Next ' Commit structural items if both operations pass successfully transaction.Commit() invoiceIdToPrint = insertedInvoiceId MessageBox.Show("Invoice saved successfully with ID: " & invoiceIdToPrint, "Success", MessageBoxButtons.OK, MessageBoxIcon.Information) ' Trigger Printing Routine TriggerReceiptPrinting() ResetForm() Catch ex As Exception transaction.Rollback() MessageBox.Show("Transaction failed and was rolled back: " & ex.Message, "System Error", MessageBoxButtons.OK, MessageBoxIcon.Error) End Try End Using End Using End Sub ''' ''' Configures standard .NET printing subroutines. ''' Private Sub TriggerReceiptPrinting() Try Use code with caution. Product Selection Section : End Sub Developing a
'Assuming GST is calculated on SubTotal (simplified) Dim gstAmount As Decimal = (subTotal * 18) / 100 '18% GST Dim grandTotal As Decimal = subTotal + gstAmount
Once your core engine functions correctly, consider expanding your application with these valuable additions:
This specialized billing system, featured in academic research, was developed for bar owners to automatically calculate customer bills after sales. It was originally coded using VB.NET 2012 with MS Access 2003 as the database. Key characteristics include sign-in/sign-out, product inventory management, point-of-sale transactions, sales receipt generation, sales records listing, and user management.
: Design print layouts to stream hardcopy billing receipts instantly through commercial thermal POS systems.