CREATE TABLE tbl_Users (
UserID INT PRIMARY KEY IDENTITY(1,1),
Username NVARCHAR(50) NOT NULL,
Password NVARCHAR(50) NOT NULL,
Role NVARCHAR(20) NOT NULL -- Admin / Cashier
);
Add a PrintDocument and PrintPreviewDialog control to the form. Then handle the PrintPage event.
Private Sub btnPrint_Click(sender As Object, e As EventArgs) Handles btnPrint.Click PrintPreviewDialog1.Document = PrintDocument1 PrintPreviewDialog1.ShowDialog() End SubPrivate Sub PrintDocument1_PrintPage(sender As Object, e As Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage Dim fontTitle As New Font("Arial", 18, FontStyle.Bold) Dim fontBody As New Font("Arial", 10) Dim yPos As Single = e.MarginBounds.Top Dim leftMargin As Single = e.MarginBounds.Left
e.Graphics.DrawString("TAX INVOICE", fontTitle, Brushes.Black, leftMargin, yPos) yPos += 40 e.Graphics.DrawString("Invoice No: " & txtInvoiceNo.Text, fontBody, Brushes.Black, leftMargin, yPos) yPos += 20 e.Graphics.DrawString("Date: " & txtInvoiceDate.Text, fontBody, Brushes.Black, leftMargin, yPos) yPos += 30 ' Draw headers e.Graphics.DrawString("Item", fontBody, Brushes.Black, leftMargin, yPos) e.Graphics.DrawString("Qty", fontBody, Brushes.Black, leftMargin + 200, yPos) e.Graphics.DrawString("Rate", fontBody, Brushes.Black, leftMargin + 300, yPos) e.Graphics.DrawString("Amount", fontBody, Brushes.Black, leftMargin + 400, yPos) yPos += 20 For Each row As DataRow In dtDetails.Rows e.Graphics.DrawString(row("ProductName").ToString(), fontBody, Brushes.Black, leftMargin, yPos) e.Graphics.DrawString(row("Quantity").ToString(), fontBody, Brushes.Black, leftMargin + 200, yPos) e.Graphics.DrawString(row("Rate").ToString(), fontBody, Brushes.Black, leftMargin + 300, yPos) e.Graphics.DrawString(row("TaxableValue").ToString(), fontBody, Brushes.Black, leftMargin + 400, yPos) yPos += 20 Next yPos += 20 e.Graphics.DrawString("Total: " & lblGrandTotal.Text, New Font("Arial", 12, FontStyle.Bold), Brushes.Black, leftMargin + 350, yPos)
End Sub
Public Class frmBilling Dim cartTable As New DataTable() Dim currentGrandTotal As Decimal = 0Private Sub frmBilling_Load(sender As Object, e As EventArgs) Handles MyBase.Load ' Define cart table columns cartTable.Columns.Add("ProductID", GetType(Integer)) cartTable.Columns.Add("ProductName", GetType(String)) cartTable.Columns.Add("Quantity", GetType(Integer)) cartTable.Columns.Add("Price", GetType(Decimal)) cartTable.Columns.Add("GST_Percent", GetType(Integer)) cartTable.Columns.Add("GST_Amount", GetType(Decimal)) cartTable.Columns.Add("Total", GetType(Decimal)) dgvCart.DataSource = cartTable End Sub Private Sub txtProductCode_KeyDown(sender As Object, e As KeyEventArgs) Handles txtProductCode.KeyDown If e.KeyCode = Keys.Enter Then Dim productCode As String = txtProductCode.Text.Trim() Dim query As String = $"SELECT ProductID, ProductName, UnitPrice, StockQuantity, GST_Percent FROM tbl_Products WHERE ProductCode='productCode'" Dim dt As DataTable = ExecuteQuery(query) If dt.Rows.Count > 0 Then Dim productID As Integer = dt.Rows(0)("ProductID") Dim pName As String = dt.Rows(0)("ProductName") Dim price As Decimal = Convert.ToDecimal(dt.Rows(0)("UnitPrice")) Dim gstPercent As Integer = Convert.ToInt32(dt.Rows(0)("GST_Percent")) ' Check if already in cart Dim existingRow() As DataRow = cartTable.Select($"ProductID = productID") If existingRow.Length > 0 Then existingRow(0)("Quantity") += 1 Dim qty As Integer = Convert.ToInt32(existingRow(0)("Quantity")) Dim totalBeforeGST As Decimal = qty * price Dim gstAmt As Decimal = totalBeforeGST * (gstPercent / 100) existingRow(0)("GST_Amount") = gstAmt existingRow(0)("Total") = totalBeforeGST + gstAmt Else Dim gstAmt As Decimal = price * (gstPercent / 100) Dim totalWithGST As Decimal = price + gstAmt cartTable.Rows.Add(productID, pName, 1, price, gstPercent, gstAmt, totalWithGST) End If CalculateTotals() txtProductCode.Clear() txtProductCode.Focus() Else MessageBox.Show("Product not found!") End If End If End Sub Private Sub CalculateTotals() Dim subTotal As Decimal = 0 Dim totalGST As Decimal = 0 For Each row As DataRow In cartTable.Rows subTotal += Convert.ToDecimal(row("Price")) * Convert.ToInt32(row("Quantity")) totalGST += Convert.ToDecimal(row("GST_Amount")) Next Dim grandTotal As Decimal = subTotal + totalGST lblSubTotal.Text = subTotal.ToString("N2") lblGST.Text = totalGST.ToString("N2") lblGrandTotal.Text = grandTotal.ToString("N2") currentGrandTotal = grandTotal End Sub Private Sub btnGenerateInvoice_Click(sender As Object, e As EventArgs) Handles btnGenerateInvoice.Click If cartTable.Rows.Count = 0 Then MessageBox.Show("Cart is empty!") Return End If Dim invoiceNo As String = "INV-" & DateTime.Now.ToString("yyyyMMddHHmmss") Dim customerID As Integer = GetOrCreateCustomer(txtCustomerMobile.Text) ' Function to fetch/add customer Dim userId As Integer = CurrentUserID ' Assume global login user ID ' Insert into tbl_Invoices Dim insertInvoice As String = $"INSERT INTO tbl_Invoices (InvoiceNo, CustomerID, SubTotal, GST_Amount, GrandTotal, UserID) VALUES ('invoiceNo', customerID, lblSubTotal.Text, lblGST.Text, lblGrandTotal.Text, userId)" ExecuteNonQuery(insertInvoice) ' Insert into tbl_InvoiceDetails For Each row As DataRow In cartTable.Rows Dim productID As Integer = Convert.ToInt32(row("ProductID")) Dim qty As Integer = Convert.ToInt32(row("Quantity")) Dim price As Decimal = Convert.ToDecimal(row("Price")) Dim gstAmt As Decimal = Convert.ToDecimal(row("GST_Amount")) Dim total As Decimal = Convert.ToDecimal(row("Total")) Dim detailQuery As String = $"INSERT INTO tbl_InvoiceDetails (InvoiceNo, ProductID, Quantity, Price, GST_Amount, Total) VALUES ('invoiceNo', productID, qty, price, gstAmt, total)" ExecuteNonQuery(detailQuery) ' Reduce stock Dim updateStock As String = $"UPDATE tbl_Products SET StockQuantity = StockQuantity - qty WHERE ProductID = productID" ExecuteNonQuery(updateStock) Next MessageBox.Show($"Invoice Generated: invoiceNo") PrintInvoice(invoiceNo) ' Clear cart and reset cartTable.Clear() CalculateTotals() End Sub
End Class
Create a database named BillingDB and run the following scripts: vbnet+billing+software+source+code
The system uses a standard SQL Server connection.
Imports System.Data.SqlClient
Public Class DatabaseHelper
' Connection string should ideally be stored in a config file
Private connString As String = "Data Source=.;Initial Catalog=BillingDB;Integrated Security=True"
Public Function GetConnection() As SqlConnection
Return New SqlConnection(connString)
End Function
' Generic method to execute Non-Query (Insert, Update, Delete)
Public Function ExecuteNonQuery(query As String, parameters As List(Of SqlParameter)) As Boolean
Using conn As SqlConnection = GetConnection()
Using cmd As New SqlCommand(query, conn)
If parameters IsNot Nothing Then
cmd.Parameters.AddRange(parameters.ToArray())
End If
conn.Open()
Dim rowsAffected As Integer = cmd.ExecuteNonQuery()
Return rowsAffected > 0
End Using
End Using
End Function
End Class
Our billing software will include: