Vb.net Billing Software Source Code Link
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.
The source code functions as a prototype but is currently in its present state due to security vulnerabilities (SQL Injection) and maintainability risks. A refactoring sprint is highly advised before adding new features.
: A ComboBox ( cmbCustomer ) to select the customer. Product Selection Section :
Using document As New Document(Of InvoiceData)(...) document.GeneratePdfAndShow() End Using
To build the user interface, create a new in Visual Studio. Designer-heavy point-of-sale screens run efficiently when split into clean modular layout panels. UI Component Requirements vb.net billing software source code
: 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)
: "Save & Print" ( btnPrint ) and "Clear Cart" ( btnClear ). 3. The Core VB.NET Source Code
Public Function SaveBill(customerID As Integer, dtCart As DataTable, paymentMode As String) As Boolean Using transaction As SqlTransaction = con.BeginTransaction() Try ' 1. Insert into tbl_Invoice Dim cmdHeader As New SqlCommand("INSERT INTO tbl_Invoice (InvoiceDate, CustomerID, SubTotal, GST_Amount, GrandTotal, PaymentMode) OUTPUT INSERTED.InvoiceNo VALUES (@date, @cust, @sub, @gst, @grand, @mode)", con, transaction) ' ... add parameters from calculated totals ... Dim newInvoiceNo As Integer = Convert.ToInt32(cmdHeader.ExecuteScalar()) ' 2. Insert each row into tbl_InvoiceDetails & reduce stock For Each row As DataGridViewRow In dtCart.Rows ' Insert details Dim cmdDetail As New SqlCommand("INSERT INTO tbl_InvoiceDetails (InvoiceNo, ProductID, Quantity, Price, GST_Percent, LineTotal) VALUES (@invNo, @pid, @qty, @price, @gst, @lineTotal)", con, transaction) ' ... add parameters ...
If dt.Rows.Count = 0 Then MessageBox.Show("Product not found") Return End If Imports System
Private Sub cmbProductName_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cmbProductName.SelectedIndexChanged If cmbProductName.SelectedValue IsNot Nothing Then Try Dim productID As Integer = Convert.ToInt32(cmbProductName.SelectedValue) Dim query As String = "SELECT ProductCode, UnitPrice, GSTPercentage FROM Products WHERE ProductID = @ProductID" DBConnection.OpenConnection() Using cmd As New SqlCommand(query, DBConnection.conn) cmd.Parameters.AddWithValue("@ProductID", productID) Using reader As SqlDataReader = cmd.ExecuteReader() If reader.Read() Then txtProductCode.Text = reader("ProductCode").ToString() txtPrice.Text = reader("UnitPrice").ToString() txtGST.Text = reader("GSTPercentage").ToString() txtQuantity.Text = "1" CalculateTotal() End If End Using End Using DBConnection.CloseConnection() Catch ex As Exception MessageBox.Show("Error: " & ex.Message) End Try End If End Sub
Using standard VB.NET arithmetic functions to eliminate manual calculation errors.
(Visual Basic .NET), combined with the robust .NET Framework, remains a powerful, underrated tool for building exactly this type of software. If you have searched for "VB.NET billing software source code," you are likely looking for a foundation to build, customize, or deploy a complete billing system.
| Module | Description | |--------|-------------| | | Product, Customer, User, Tax (GST/VAT), Company Profile | | Transaction (Billing) | Create/Edit/Print Invoice, Add/Remove Items, Auto-calc totals | | Inventory | Stock-in, Stock-out, Low stock alerts | | Reports | Daily Sales, GST Summary, Customer Ledger, Profit/Loss | | Backup & Security | Database backup, User login, Role-based access | A refactoring sprint is highly advised before adding
This leaves the application wide open to SQL Injection attacks. A user could input malicious SQL into the text box to drop tables or access unauthorized data.
' Draw Grid Headerse.Graphics.DrawString("Item Description", fontHeader, Brushes.Black, startX, startY)e.Graphics.DrawString("Price", fontHeader, Brushes.Black, startX + 250, startY)e.Graphics.DrawString("Qty", fontHeader, Brushes.Black, startX + 350, startY)e.Graphics.DrawString("Total", fontHeader, Brushes.Black, startX + 430, startY)
End Function
Replace the code in your main form with the fully integrated backend implementation below. Make sure to adjust the connString variable to match your database server configuration.