Inventory Management System
Manage stock levels with automatic reorder alerts, stock movement logging, valuation reports, and low-stock notifications. Supports multiple product categories and warehouse locations.
570 views
Featured
Perfect For:
- Warehouse stock control
- Retail inventory tracking
- Reorder management
- Stock valuation reporting
- Movement audit trails
VBA Code
' Inventory Management System
' Main sheet (Inventory): Product Code (A), Name (B), Category (C),
' Location (D), Qty in Stock (E), Reorder Level (F), Unit Cost (G),
' Stock Value (H), Status (I)
' Movements sheet: Date (A), Product Code (B), Type (C), Quantity (D),
' Reference (E), Notes (F)
Sub UpdateStockLevels()
' Recalculate stock values and check reorder levels
On Error GoTo ErrorHandler
Application.ScreenUpdating = False
Dim wsInv As Worksheet
Set wsInv = ThisWorkbook.Sheets("Inventory")
Dim lastRow As Long
lastRow = wsInv.Cells(wsInv.Rows.Count, "A").End(xlUp).Row
If lastRow < 2 Then
MsgBox "No inventory data found.", vbExclamation
Exit Sub
End If
Dim lowStockItems As String
Dim outOfStockItems As String
Dim lowCount As Long
Dim outCount As Long
Dim i As Long
For i = 2 To lastRow
Dim qty As Double
Dim reorderLevel As Double
Dim unitCost As Double
qty = Val(wsInv.Cells(i, 5).Value)
reorderLevel = Val(wsInv.Cells(i, 6).Value)
unitCost = Val(wsInv.Cells(i, 7).Value)
' Calculate stock value
wsInv.Cells(i, 8).Value = qty * unitCost
wsInv.Cells(i, 8).NumberFormat = "#,##0.00"
' Determine status
Dim status As String
If qty <= 0 Then
status = "Out of Stock"
outOfStockItems = outOfStockItems & wsInv.Cells(i, 2).Value & vbCrLf
outCount = outCount + 1
wsInv.Cells(i, 9).Interior.Color = RGB(255, 150, 150)
ElseIf qty <= reorderLevel Then
status = "Low Stock"
lowStockItems = lowStockItems & wsInv.Cells(i, 2).Value & _
" (Qty: " & qty & ", Reorder at: " & reorderLevel & ")" & vbCrLf
lowCount = lowCount + 1
wsInv.Cells(i, 9).Interior.Color = RGB(255, 230, 150)
ElseIf qty <= reorderLevel * 1.5 Then
status = "Adequate"
wsInv.Cells(i, 9).Interior.Color = RGB(200, 230, 255)
Else
status = "In Stock"
wsInv.Cells(i, 9).Interior.Color = RGB(200, 240, 200)
End If
wsInv.Cells(i, 9).Value = status
Next i
' Format currency column
wsInv.Range("G2:H" & lastRow).NumberFormat = "#,##0.00"
wsInv.Columns("A:I").AutoFit
Application.ScreenUpdating = True
' Show alerts
Dim alertMsg As String
If outCount > 0 Then
alertMsg = "OUT OF STOCK (" & outCount & " items):" & vbCrLf & outOfStockItems & vbCrLf
End If
If lowCount > 0 Then
alertMsg = alertMsg & "LOW STOCK (" & lowCount & " items):" & vbCrLf & lowStockItems
End If
If alertMsg <> "" Then
MsgBox alertMsg, vbExclamation, "Stock Alerts"
Else
MsgBox "All stock levels are healthy.", vbInformation
End If
Exit Sub
ErrorHandler:
Application.ScreenUpdating = True
MsgBox "Error updating stock: " & Err.Description, vbCritical
End Sub
Sub RecordStockMovement()
' Record incoming or outgoing stock
On Error GoTo ErrorHandler
Dim wsInv As Worksheet
Dim wsMov As Worksheet
Set wsInv = ThisWorkbook.Sheets("Inventory")
On Error Resume Next
Set wsMov = ThisWorkbook.Sheets("Movements")
On Error GoTo ErrorHandler
If wsMov Is Nothing Then
Set wsMov = ThisWorkbook.Sheets.Add(After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
wsMov.Name = "Movements"
wsMov.Cells(1, 1).Value = "Date"
wsMov.Cells(1, 2).Value = "Product Code"
wsMov.Cells(1, 3).Value = "Type"
wsMov.Cells(1, 4).Value = "Quantity"
wsMov.Cells(1, 5).Value = "Reference"
wsMov.Cells(1, 6).Value = "Notes"
With wsMov.Range("A1:F1")
.Font.Bold = True
.Interior.Color = RGB(0, 102, 204)
.Font.Color = RGB(255, 255, 255)
End With
End If
' Get movement details
Dim productCode As String
productCode = InputBox("Enter product code:", "Stock Movement")
If productCode = "" Then Exit Sub
' Find product in inventory
Dim lastInvRow As Long
lastInvRow = wsInv.Cells(wsInv.Rows.Count, "A").End(xlUp).Row
Dim productRow As Long
productRow = 0
Dim i As Long
For i = 2 To lastInvRow
If UCase(wsInv.Cells(i, 1).Value) = UCase(productCode) Then
productRow = i
Exit For
End If
Next i
If productRow = 0 Then
MsgBox "Product code '" & productCode & "' not found in inventory.", vbExclamation
Exit Sub
End If
Dim productName As String
productName = wsInv.Cells(productRow, 2).Value
Dim currentQty As Double
currentQty = Val(wsInv.Cells(productRow, 5).Value)
' Get movement type
Dim movType As String
Dim response As VbMsgBoxResult
response = MsgBox("Product: " & productName & " (Current stock: " & currentQty & ")" & vbCrLf & vbCrLf & _
"Yes = Stock IN (receiving)" & vbCrLf & _
"No = Stock OUT (dispatching)", vbYesNoCancel + vbQuestion, "Movement Type")
If response = vbCancel Then Exit Sub
movType = IIf(response = vbYes, "IN", "OUT")
' Get quantity
Dim movQty As Double
movQty = Val(InputBox("Enter quantity to " & IIf(movType = "IN", "receive", "dispatch") & ":", "Quantity"))
If movQty <= 0 Then
MsgBox "Invalid quantity.", vbExclamation
Exit Sub
End If
' Check if enough stock for OUT
If movType = "OUT" And movQty > currentQty Then
MsgBox "Insufficient stock. Current quantity: " & currentQty, vbExclamation
Exit Sub
End If
' Get reference
Dim reference As String
reference = InputBox("Enter reference (PO number, order number, etc.):", "Reference", "")
' Record movement
Dim lastMovRow As Long
lastMovRow = wsMov.Cells(wsMov.Rows.Count, "A").End(xlUp).Row + 1
wsMov.Cells(lastMovRow, 1).Value = Now
wsMov.Cells(lastMovRow, 1).NumberFormat = "dd/mm/yyyy hh:mm"
wsMov.Cells(lastMovRow, 2).Value = productCode
wsMov.Cells(lastMovRow, 3).Value = movType
wsMov.Cells(lastMovRow, 4).Value = movQty
wsMov.Cells(lastMovRow, 5).Value = reference
' Update inventory
If movType = "IN" Then
wsInv.Cells(productRow, 5).Value = currentQty + movQty
Else
wsInv.Cells(productRow, 5).Value = currentQty - movQty
End If
' Refresh stock levels
Call UpdateStockLevels
MsgBox movType & ": " & movQty & " x " & productName & vbCrLf & _
"New stock level: " & wsInv.Cells(productRow, 5).Value, vbInformation
Exit Sub
ErrorHandler:
MsgBox "Error recording movement: " & Err.Description, vbCritical
End Sub
Sub GenerateStockValuationReport()
' Create stock valuation summary by category
On Error GoTo ErrorHandler
Application.ScreenUpdating = False
Dim wsInv As Worksheet
Set wsInv = ThisWorkbook.Sheets("Inventory")
Dim lastRow As Long
lastRow = wsInv.Cells(wsInv.Rows.Count, "A").End(xlUp).Row
' Collect categories
Dim categories As Object
Set categories = CreateObject("Scripting.Dictionary")
Dim i As Long
For i = 2 To lastRow
Dim cat As String
cat = wsInv.Cells(i, 3).Value
If cat = "" Then cat = "Uncategorised"
If Not categories.Exists(cat) Then
categories.Add cat, Array(0, 0, 0) ' items, totalQty, totalValue
End If
Dim vals As Variant
vals = categories(cat)
vals(0) = vals(0) + 1
vals(1) = vals(1) + Val(wsInv.Cells(i, 5).Value)
vals(2) = vals(2) + Val(wsInv.Cells(i, 8).Value)
categories(cat) = vals
Next i
' Create report sheet
Dim wsReport As Worksheet
On Error Resume Next
Set wsReport = ThisWorkbook.Sheets("Stock Valuation")
On Error GoTo ErrorHandler
If wsReport Is Nothing Then
Set wsReport = ThisWorkbook.Sheets.Add(After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
wsReport.Name = "Stock Valuation"
Else
wsReport.Cells.Clear
End If
' Title
wsReport.Cells(1, 1).Value = "Stock Valuation Report"
wsReport.Cells(1, 1).Font.Size = 16
wsReport.Cells(1, 1).Font.Bold = True
wsReport.Cells(2, 1).Value = "Generated: " & Format(Now, "dd/mm/yyyy hh:mm")
' Headers
wsReport.Cells(4, 1).Value = "Category"
wsReport.Cells(4, 2).Value = "Items"
wsReport.Cells(4, 3).Value = "Total Quantity"
wsReport.Cells(4, 4).Value = "Total Value"
With wsReport.Range("A4:D4")
.Font.Bold = True
.Interior.Color = RGB(0, 102, 204)
.Font.Color = RGB(255, 255, 255)
End With
' Write data
Dim row As Long
row = 5
Dim grandTotal As Double
Dim key As Variant
For Each key In categories.Keys
vals = categories(key)
wsReport.Cells(row, 1).Value = key
wsReport.Cells(row, 2).Value = vals(0)
wsReport.Cells(row, 3).Value = vals(1)
wsReport.Cells(row, 4).Value = vals(2)
wsReport.Cells(row, 4).NumberFormat = "#,##0.00"
grandTotal = grandTotal + vals(2)
row = row + 1
Next key
' Grand total
wsReport.Cells(row + 1, 3).Value = "Grand Total:"
wsReport.Cells(row + 1, 3).Font.Bold = True
wsReport.Cells(row + 1, 4).Value = grandTotal
wsReport.Cells(row + 1, 4).NumberFormat = "#,##0.00"
wsReport.Cells(row + 1, 4).Font.Bold = True
wsReport.Columns("A:D").AutoFit
Application.ScreenUpdating = True
MsgBox "Stock valuation report generated!", vbInformation
Exit Sub
ErrorHandler:
Application.ScreenUpdating = True
MsgBox "Error generating report: " & Err.Description, vbCritical
End Sub
Related Topics
inventory
stock
warehouse
reorder
management
Need Custom VBA Solutions?
Our AI-powered VBA generator can create custom code tailored to your specific requirements in seconds.
Free AI generations every month — top up with credit packs anytime
Related Templates
More VBA templates in the same category
Beginner
Data Processing & Cleanup
Remove duplicates, clean data formats, and standardise entries
View Template
Intermediate
CSV Import with Data Types
Import CSV files with automatic data type detection and formatting
View Template
Intermediate
Timesheet & Attendance Tracker
Track employee working hours, overtime, absences, and holidays with automatic calculations, weekl...
View Template