Expert guide
Equipment Rental Tracking in Microsoft Access
What is out, what is free next Tuesday, what to bill, and which units earn their keep
Call us at +1 (385) 386-3860
Short answer: track each unit as an asset linked to a product type and rate card; record rentals as contracts with lines per unit, start, expected return and actual return; test availability with the overlap rule (existing start < requested end AND existing end > requested start); calculate charges as the cheapest mix of day, week and month rates; and inspect on return. Utilisation by product shows what to buy or sell. We build rental systems as custom Access databases.
Rental businesses, whether tools, party equipment, scaffolding, AV gear or medical devices, lose money in three ways: double-booking units that are not really available, units coming back late without being charged, and buying more of something that sits on the shelf. A whiteboard and a spreadsheet cannot track individual serial numbers across overlapping bookings. A relational database can.
The Tables
| Table | Key fields |
|---|---|
| tblProducts | ProductID, Name, Category, DayRate, WeekRate, MonthRate, Deposit, ReplacementCost |
| tblAssets | AssetID, ProductID, SerialNo, PurchaseDate, Cost, Status (Available/Maintenance/Retired), HoursMeter |
| tblCustomers | CustomerID, Name, Account terms, ID verified |
| tblContracts | ContractID, CustomerID, Type (Reservation/Rental), CreatedOn, DeliveryAddress, Status |
| tblContractLines | LineID, ContractID, AssetID, StartDate, DueBack, ReturnedOn, Charge, Condition |
| tblInspections | AssetID, Date, Result, Notes, WorkOrderID |
Availability: The Overlap Rule
qryAvailableAssets (parameters: ProductID, ReqStart, ReqEnd):
SELECT a.AssetID, a.SerialNo
FROM tblAssets AS a
WHERE a.ProductID = [ReqProduct]
AND a.Status = "Available"
AND NOT EXISTS (
SELECT 1 FROM tblContractLines AS l
WHERE l.AssetID = a.AssetID
AND l.ReturnedOn Is Null
AND l.StartDate < [ReqEnd]
AND l.DueBack > [ReqStart]);That single NOT EXISTS clause is the heart of the system. It catches every overlap, including bookings that start inside, end inside, or completely contain the requested period. Overdue rentals (DueBack in the past, not returned) should be treated as still out; extend their effective end date to today in the query if your process allows overdue items.
Calculating the Charge
Public Function RentalCharge(ByVal productID As Long, _
ByVal startDate As Date, ByVal endDate As Date) As Currency
Dim dayR As Currency, weekR As Currency, monthR As Currency
Dim days As Long, months As Long, weeks As Long, rest As Long
Dim rs As DAO.Recordset
Set rs = CurrentDb.OpenRecordset("SELECT DayRate, WeekRate, MonthRate " & _
"FROM tblProducts WHERE ProductID = " & productID)
dayR = rs!DayRate: weekR = rs!WeekRate: monthR = rs!MonthRate
rs.Close
days = DateDiff("d", startDate, endDate)
If days < 1 Then days = 1
months = days \ 28: rest = days Mod 28
weeks = rest \ 7: rest = rest Mod 7
' Each partial block is charged at the cheaper of its day total or the next block up
RentalCharge = months * monthR _
+ Min3(weeks * weekR + rest * dayR, (weeks + 1) * weekR, monthR)
End Function
Private Function Min3(ByVal a As Currency, ByVal b As Currency, ByVal c As Currency) As Currency
Min3 = a
If b < Min3 Then Min3 = b
If c < Min3 Then Min3 = c
End FunctionThe logic, cheapest of the day, week and month combinations for the remainder, matches how most rental counters quote. Encode your own rules, such as minimum charges, weekend specials and damage waivers, in the same function so every contract is priced identically.
Check-Out and Return
Check-out form: scan or select serial numbers, confirm ID and deposit, print the contract.
Return form: scan the unit, record condition and hours meter, calculate final charge from actual return date.
Late return: charge from the rate function automatically; flag on the contract.
Failed inspection: set asset status to Maintenance and create a work order.
Daily Operations Views
| View | Shows |
|---|---|
| Going out today | Reservations starting today, with delivery or pickup details |
| Due back today | Lines with DueBack today, customer phone |
| Overdue | Not returned, DueBack before today, days late and accruing charge |
| Maintenance queue | Assets in Maintenance with open work orders |
| Availability calendar | Per product: units free each day for the next 14 days |
Utilisation and Fleet Decisions
qryUtilisationByProduct (last 365 days):
SELECT p.Name, Count(a.AssetID) AS Units,
Sum(Nz(DSum("DateDiff('d', [StartDate], Nz([ReturnedOn], Date()))",
"tblContractLines",
"AssetID=" & a.AssetID & " AND StartDate >= Date()-365"), 0)) AS DaysOnRent,
Sum(Nz(DSum("Charge", "tblContractLines",
"AssetID=" & a.AssetID & " AND StartDate >= Date()-365"), 0)) AS Revenue,
Sum(a.Cost) AS FleetCost
FROM tblProducts AS p INNER JOIN tblAssets AS a ON p.ProductID = a.ProductID
WHERE a.Status <> "Retired"
GROUP BY p.Name;
Time utilisation = DaysOnRent / (Units * 365)
Financial utilisation = Revenue / FleetCostDomain functions keep the example short; for a large fleet, replace them with grouped subqueries for speed, as explained in faster alternatives to DLookup. Products with low time utilisation and many units are candidates to sell; products that are frequently unavailable when customers ask are candidates to buy.
Where AI Helps
Summarising return inspection notes into damage descriptions for the customer.
Drafting overdue reminders with the contract details.
Reading photographed delivery and collection notes into the contract.
Suggesting fleet changes from utilisation and lost-booking data for the owner to review.
Maintenance work orders use the same pattern as our work order management database, and receivables can be followed up with the invoice and payment tracker. Barcode scanning at check-out and return is a common addition.
FAQ
Equipment rental database FAQ
Availability, charges and utilisation