Vb.net Billing Software Source Code -

Search customers instantly during invoice creation. B. Product/Inventory Management Module This module tracks products or services. Fields: Product ID, Name, Description, Price, Stock Level.

A scalable billing system requires a relational database framework to maintain data integrity. For desktop deployments, Microsoft Access ( .accdb ) or SQL Server Express are optimal choices. This architecture utilizes a structured relational model consisting of four core tables: Products, Customers, Invoices, and InvoiceDetails.

InvoiceDetails : Stores the individual line items for each invoice (Product ID, Quantity, Unit Price, Subtotal). SQL Database Script

Imports System.Data.SqlClient Module dbConnectionModule ' Replace with your actual SQL Server connection string Public ReadOnly ConnectionString As String = "Data Source=.\SQLEXPRESS;Initial Catalog=BillingDB;Integrated Security=True" Public Function GetDatabaseConnection() As SqlConnection Dim conn As New SqlConnection(ConnectionString) Try If conn.State = ConnectionState.Closed Then conn.Open() End If Return conn Catch ex As Exception MsgBox("Database Connection Error: " & ex.Message, MsgBoxStyle.Critical, "Error") Return Nothing End Try End Function End Module Use code with caution. 3. UI Design and Form Configuration vb.net billing software source code

Your preferred (SQL Server, MySQL, or MS Access) If you need barcode scanner integration

This guide provides a comprehensive architectural breakdown and production-ready source code for a complete VB.NET billing software solution. It covers database design, user interface integration, transactional logic, and invoice printing. 1. Database Architecture & Schema Design

: lblSubTotal , txtTaxRate , txtDiscount , lblGrandTotal . Search customers instantly during invoice creation

Imports System.Data.SqlClient Imports System.Configuration Public Class frmBilling ' Define the connection string (Modify security parameters as needed for production) Private ReadOnly connString As String = "Server=(localdb)\MSSQLLocalDB;Database=BillingDB;Trusted_Connection=True;" ' Temporary runtime storage for the selected Product's ID Private currentProductID As Integer = 0 ''' ''' Form Load event. Initializes structural components. ''' Private Sub frmBilling_Load(sender As Object, e As EventArgs) Handles MyBase.Load InitializeInvoiceGrid() LoadCustomers() GenerateInvoiceNumber() ResetProductInputs() End Sub ''' ''' Explicitly creates columns for the DataGridView to avoid structural mismatch. ''' Private Sub InitializeInvoiceGrid() With dgvItems .Columns.Clear() .Columns.Add("ProductID", "Product ID") .Columns.Add("ProductCode", "Item Code") .Columns.Add("ProductName", "Item Description") .Columns.Add("UnitPrice", "Unit Price") .Columns.Add("Quantity", "Qty") .Columns.Add("LineTotal", "Total Amount") ' UI Optimization .Columns("ProductID").Visible = False .Columns("ProductName").AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill .SelectionMode = DataGridViewSelectionMode.FullRowSelect .AllowUserToAddRows = False End With End Sub ''' ''' Hydrates the Customer dropdown selection. ''' Private Sub LoadCustomers() Dim query As String = "SELECT CustomerID, CustomerName FROM Customers" Using conn As New SqlConnection(connString) Using cmd As New SqlCommand(query, conn) Dim dt As New DataTable() Try conn.Open() Using reader As SqlDataReader = cmd.ExecuteReader() dt.Load(reader) End Using cmbCustomer.DataSource = dt cmbCustomer.DisplayMember = "CustomerName" cmbCustomer.ValueMember = "CustomerID" Catch ex As Exception MessageBox.Show($"Database Error loading customers: ex.Message", "DAL Error", MessageBoxButtons.OK, MessageBoxIcon.Error) End Try End Using End Using End Sub ''' ''' Generates a unique, trackable string sequence for the current transaction instance. ''' Private Sub GenerateInvoiceNumber() Dim timestamp As String = DateTime.Now.ToString("yyyyMMddHHmmss") txtInvoiceNumber.Text = $"INV-timestamp" End Sub ''' ''' Fires when a product code is entered or scanned via barcode reader. ''' Private Sub txtProductCode_KeyDown(sender As Object, e As KeyEventArgs) Handles txtProductCode.KeyDown If e.KeyCode = Keys.Enter Then e.SuppressKeyPress = True ' Stop systemic beep sound on enter If String.IsNullOrWhiteSpace(txtProductCode.Text) Then Exit Sub Dim query As String = "SELECT ProductID, ProductName, UnitPrice FROM Products WHERE ProductCode = @ProductCode" Using conn As New SqlConnection(connString) Using cmd As New SqlCommand(query, conn) cmd.Parameters.AddWithValue("@ProductCode", txtProductCode.Text.Trim()) Try conn.Open() Using reader As SqlDataReader = cmd.ExecuteReader() If reader.Read() Then currentProductID = Convert.ToInt32(reader("ProductID")) txtProductName.Text = reader("ProductName").ToString() txtUnitPrice.Text = Convert.ToDecimal(reader("UnitPrice")).ToString("F2") txtQuantity.Focus() Else MessageBox.Show("Product not found in system storage.", "Inventory Check", MessageBoxButtons.OK, MessageBoxIcon.Warning) ResetProductInputs() End If End Using Catch ex As Exception MessageBox.Show($"Error pulling inventory details: ex.Message", "Query Error", MessageBoxButtons.OK, MessageBoxIcon.Error) End Try End Using End Using End If End Sub ''' ''' Validates UI input state and appends entry record to active item grid list. ''' Private Sub btnAddToGrid_Click(sender As Object, e As EventArgs) Handles btnAddToGrid.Click If currentProductID = 0 OrElse String.IsNullOrWhiteSpace(txtProductName.Text) Then MessageBox.Show("Please select or scan a valid product first.", "Input Missing", 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 input a valid positive integer quantity.", "Input Error", MessageBoxButtons.OK, MessageBoxIcon.Warning) Exit Sub End If Dim price As Decimal = Convert.ToDecimal(txtUnitPrice.Text) Dim total As Decimal = price * qty ' Append items directly to the UI Matrix dgvItems.Rows.Add(currentProductID, txtProductCode.Text, txtProductName.Text, price, qty, total) CalculateInvoiceTotals() ResetProductInputs() End Sub ''' ''' Iterates grid data records to maintain computational totals real-time. ''' Private Sub CalculateInvoiceTotals() Dim subTotal As Decimal = 0 For Each row As DataGridViewRow In dgvItems.Rows If Not row.IsNewRow Then subTotal += Convert.ToDecimal(row.Cells("LineTotal").Value) End If Next Dim taxRate As Decimal = 0 Decimal.TryParse(txtTaxRate.Text, taxRate) Dim taxAmount As Decimal = subTotal * (taxRate / 100) Dim grandTotal As Decimal = subTotal + taxAmount lblSubTotal.Text = subTotal.ToString("F2") lblTaxAmount.Text = taxAmount.ToString("F2") lblGrandTotal.Text = grandTotal.ToString("F2") End Sub Private Sub txtTaxRate_TextChanged(sender As Object, e As EventArgs) Handles txtTaxRate.TextChanged CalculateInvoiceTotals() End Sub Private Sub ResetProductInputs() currentProductID = 0 txtProductCode.Clear() txtProductName.Clear() txtUnitPrice.Clear() txtQuantity.Text = "1" txtProductCode.Focus() End Sub ''' ''' Implements an ACID-compliant transaction workflow to save both master and detail layers. ''' Private Sub btnSavePrint_Click(sender As Object, e As EventArgs) Handles btnSavePrint.Click If dgvItems.Rows.Count = 0 Then MessageBox.Show("Cannot process an empty billing statement.", "Validation Halt", MessageBoxButtons.OK, MessageBoxIcon.Warning) Exit Sub End If Using conn As New SqlConnection(connString) conn.Open() ' Initialize SQL transaction pipeline for reliable multi-table commitment Using sqlTran As SqlTransaction = conn.BeginTransaction() Dim masterQuery As String = "INSERT INTO Invoices (InvoiceNumber, CustomerID, SubTotal, TaxRate, TaxAmount, GrandTotal) " & "VALUES (@InvNum, @CustID, @Sub, @TaxR, @TaxA, @Grand); SELECT SCOPE_IDENTITY();" Dim detailQuery As String = "INSERT INTO InvoiceDetails (InvoiceID, ProductID, Quantity, UnitPrice) " & "VALUES (@InvID, @ProdID, @Qty, @Price);" Dim stockQuery As String = "UPDATE Products SET StockQuantity = StockQuantity - @Qty WHERE ProductID = @ProdID" Try Dim newInvoiceID As Integer = 0 ' 1. Persist Master Record Using cmdMaster As New SqlCommand(masterQuery, conn, sqlTran) cmdMaster.Parameters.AddWithValue("@InvNum", txtInvoiceNumber.Text.Trim()) cmdMaster.Parameters.AddWithValue("@CustID", cmbCustomer.SelectedValue) cmdMaster.Parameters.AddWithValue("@Sub", Convert.ToDecimal(lblSubTotal.Text)) cmdMaster.Parameters.AddWithValue("@TaxR", Convert.ToDecimal(If(String.IsNullOrEmpty(txtTaxRate.Text), "0", txtTaxRate.Text))) cmdMaster.Parameters.AddWithValue("@TaxA", Convert.ToDecimal(lblTaxAmount.Text)) cmdMaster.Parameters.AddWithValue("@Grand", Convert.ToDecimal(lblGrandTotal.Text)) newInvoiceID = Convert.ToInt32(cmdMaster.ExecuteScalar()) End Using ' 2. Loop & Persist Line Items + Adjust Inventory Stock levels For Each row As DataGridViewRow In dgvItems.Rows Dim pID As Integer = Convert.ToInt32(row.Cells("ProductID").Value) Dim qty As Integer = Convert.ToInt32(row.Cells("Quantity").Value) Dim uPrice As Decimal = Convert.ToDecimal(row.Cells("UnitPrice").Value) ' Insert details record Using cmdDetail As New SqlCommand(detailQuery, conn, sqlTran) cmdDetail.Parameters.AddWithValue("@InvID", newInvoiceID) cmdDetail.Parameters.AddWithValue("@ProdID", pID) cmdDetail.Parameters.AddWithValue("@Qty", qty) cmdDetail.Parameters.AddWithValue("@Price", uPrice) cmdDetail.ExecuteNonQuery() End Using ' Deduct Stock allocation Using cmdStock As New SqlCommand(stockQuery, conn, sqlTran) cmdStock.Parameters.AddWithValue("@Qty", qty) cmdStock.Parameters.AddWithValue("@ProdID", pID) cmdStock.ExecuteNonQuery() End Using Next ' All stages complete without failure flags sqlTran.Commit() MessageBox.Show($"Invoice txtInvoiceNumber.Text successfully committed to ledger.", "Transaction Success", MessageBoxButtons.OK, MessageBoxIcon.Information) ClearFormToDefault() Catch ex As Exception ' Error encountered, roll state back to prevent fragmented/orphaned logs sqlTran.Rollback() MessageBox.Show($"Critical Database Transaction Exception: ex.Message", "Transaction Rollback Executed", MessageBoxButtons.OK, MessageBoxIcon.Error) End Try End Using End Using End Sub Private Sub ClearFormToDefault() dgvItems.Rows.Clear() lblSubTotal.Text = "0.00" lblTaxAmount.Text = "0.00" lblGrandTotal.Text = "0.00" txtTaxRate.Text = "0" GenerateInvoiceNumber() ResetProductInputs() End Sub End Class Use code with caution. Technical Analysis of the Code 1. Database Transaction Security (ACID Principles)

End Class

Built-in tools like Crystal Reports or Microsoft Report Viewer make generating invoices straightforward. Fields: Product ID, Name, Description, Price, Stock Level

--- ## 5. Security and Operational Improvements To make this billing source code enterprise-grade, consider implementing the following production improvements: ### Database Transactions The `btnSavePrint_Click` routine leverages explicit `SqlTransaction` properties. This protects financial reporting tables from partial updates. If an item loop fails due to database lock issues or sudden hardware issues midway through execution, the tracking engine rolls back modifications completely to prevent data corruption. ### Input Constraints Always validate user entries before processing queries to avoid computational exceptions. * Override textbox keypress handlers to restrict character input: ```vb Private Sub txtQuantity_KeyPress(sender As Object, e As KeyPressEventArgs) Handles txtQuantity.KeyPress ' Allow numbers and backspace characters only If Not Char.IsDigit(e.KeyChar) AndAlso Not Char.IsControl(e.KeyChar) Then e.Handled = True End If End Sub Parameterized Query Design

"The lack of a layered architecture makes the application brittle. For example, if the database schema changes, modifications are required directly in the UI event handlers (e.g., BtnSave_Click ), violating the Open/Closed Principle."

Public Class Product Public Property ProductID As Integer Public Property ProductCode As String Public Property ProductName As String Public Property Category As String Public Property UnitPrice As Decimal Public Property StockQuantity As Integer Public Property GSTPercentage As Decimal Public Function AddProduct() As Boolean Try Dim query As String = "INSERT INTO Products (ProductCode, ProductName, Category, UnitPrice, StockQuantity, GSTPercentage) VALUES (@Code, @Name, @Category, @Price, @Stock, @GST)" DBConnection.OpenConnection() Using cmd As New SqlCommand(query, DBConnection.conn) cmd.Parameters.AddWithValue("@Code", ProductCode) cmd.Parameters.AddWithValue("@Name", ProductName) cmd.Parameters.AddWithValue("@Category", Category) cmd.Parameters.AddWithValue("@Price", UnitPrice) cmd.Parameters.AddWithValue("@Stock", StockQuantity) cmd.Parameters.AddWithValue("@GST", GSTPercentage) Return cmd.ExecuteNonQuery() > 0 End Using Catch ex As Exception MessageBox.Show("Error: " & ex.Message) Return False Finally DBConnection.CloseConnection() End Try End Function

SQL triggers or inline command batches update the inventory stock levels. 2. Database Schema Design (MS SQL Server / MS Access)

Try ' Calculate totals Dim subtotal As Decimal = 0 Dim totalGST As Decimal = 0 For Each row As DataRow In dtCart.Rows subtotal += CDec(row("Total")) Next