Expert guide
Cleaning Business Job Scheduling in Excel
Every recurring clean on the schedule, the right cleaner on every job, and hours that match the price
Call us at +1 (385) 386-3860
Short answer: build a Sites table with frequency, days, time window, budgeted hours, team size and access notes; a Cleaners table with availability, max hours and the sites they know; generate weekly jobs from frequency; assign cleaners in a day-by-day grid with formulas that flag clashes and over-hours; then log actual hours to compare against budget per site. For invoicing and one-off jobs, add our work order management database.
Cleaning businesses run on hundreds of small recurring commitments: the dental office every weeknight after 7 pm, the home every second Thursday, the gym's deep clean on the first Sunday of the month. Each one has keys, alarm codes and preferences. When a cleaner calls in sick at 4 pm, the office needs to know in seconds who can cover. That is a data problem, and a well-structured workbook solves most of it.
The Tables
| Table | Key columns |
|---|---|
| tblSites | SiteID, Client, Address, Type (Residential/Commercial), Frequency, Days, TimeFrom, TimeTo, BudgetHours, TeamSize, PricePerVisit, AccessNotes |
| tblCleaners | CleanerID, Name, Phone, Mon–Sun availability, MaxWeeklyHours, PayRate, Skills |
| tblSiteKnowledge | CleanerID, SiteID, HasKey, Trained (Y/N) |
| tblJobs | JobID, SiteID, Date, CleanerID, Status, ActualStart, ActualEnd, Notes |
Generating Recurring Jobs
Each week, filter sites that are due (weekly, fortnightly by week number, monthly by week of month) and create one job row per required day. Store Days as text such as "Mon,Wed,Fri" and expand it with TEXTSPLIT. Keep generated jobs in tblJobs so one-off changes do not alter the site master.
Days this site needs this week (spills):
=IF([@DueThisWeek], TEXTSPLIT([@Days], ","), "")
Date for each day (week start Monday in Settings!WeekStart):
=Settings!WeekStart + MATCH(day, {"Mon","Tue","Wed","Thu","Fri","Sat","Sun"}, 0) - 1Assignment Checks
Cleaner's planned hours this week:
=SUMPRODUCT((tblJobs[CleanerID] = [@CleanerID]) *
(tblJobs[Date] >= Settings!WeekStart) * (tblJobs[Date] < Settings!WeekStart + 7),
XLOOKUP(tblJobs[SiteID], tblSites[SiteID], tblSites[BudgetHours]) /
XLOOKUP(tblJobs[SiteID], tblSites[SiteID], tblSites[TeamSize]))
Over max hours?
=[@PlannedHours] > [@MaxWeeklyHours]
Unassigned jobs this week:
=COUNTIFS(tblJobs[Date], ">=" & Settings!WeekStart,
tblJobs[Date], "<" & Settings!WeekStart + 7, tblJobs[CleanerID], "")Clash check: the same cleaner on two jobs whose time windows overlap on the same day.
Knowledge check: cleaner assigned to a site where tblSiteKnowledge has no record (no key, never trained).
Availability check: assignment on a day the cleaner marked unavailable.
Covering an Absence in Seconds
Available cover for a job (site in B1, date in B2):
=FILTER(tblCleaners[Name],
(INDEX(tblCleaners[[Mon]:[Sun]], 0, WEEKDAY(B2, 2)) = "Y") *
(COUNTIFS(tblSiteKnowledge[CleanerID], tblCleaners[CleanerID],
tblSiteKnowledge[SiteID], B1) > 0) *
(tblCleaners[PlannedHours] < tblCleaners[MaxWeeklyHours]),
"No trained cover available")The availability columns Mon to Sun hold Y or N; INDEX with WEEKDAY picks the right day's column. The result is one list of people who are free that day, know the site and have hours left. Training more than one cleaner per site is the real fix, and this list shows where that is missing.
Hours vs Budget and Site Profitability
Actual hours per job: =IF([@ActualEnd] = "", "", MOD([@ActualEnd] - [@ActualStart], 1) * 24) Per site, month to date: Budget hours: =COUNTIFS(tblJobs[SiteID], [@SiteID], tblJobs[Status], "Done") * [@BudgetHours] Actual hours: =SUMIFS(tblJobs[ActualHours], tblJobs[SiteID], [@SiteID]) Variance: =[@[Actual hours]] - [@[Budget hours]] Labour cost: =[@[Actual hours]] * Settings!LoadedRate Revenue: =COUNTIFS(tblJobs[SiteID], [@SiteID], tblJobs[Status], "Done") * [@PricePerVisit] Margin %: =IF([@Revenue] = 0, "", 1 - [@[Labour cost]] / [@Revenue])
Sites consistently over budget hours are either underpriced or have a scope that has crept. Both are conversations to have at contract renewal.
Proof of Service and Quality
Checklist per site type, ticked per visit on a phone form or paper sheet.
Photos for commercial clients who ask for them, linked to the job row.
Client complaints logged against the job and cleaner, reviewed monthly.
Periodic supervisor inspections scored and tracked per site.
Where AI Helps
Drafting quotes from a walk-through description and your production rates.
Summarising client emails into job notes or change requests.
Reading scanned checklists and timesheets into the job log.
Writing the weekly schedule message to each cleaner in plain language.
Hours from the schedule feed payroll; see the Excel payroll manager. Recurring route logic for outdoor services is in landscaping route scheduling, and scanned paperwork capture in scanning documents with AI.
FAQ
Cleaning business scheduling FAQ
Recurring jobs, staff cover and job costing