Why Project Timelines Slip: 7 Warning Signs in Your Spreadsheet
Almost no project fails on the day it is discovered. It fails weeks earlier, quietly, in a row nobody looked at.
The useful thing about running a project on a spreadsheet is that the early evidence is already sitting there in columns you filled in for other reasons. Seven checks pull it out. Each is one formula, and each has a threshold that means something.
The examples below run against a real twelve-task website relaunch: fifty-four calendar days, an $11,000 budget, five people, set out in full here. We are looking at it on day 31.
One layout note, so the seven formulas can coexist in a single sheet: C is the task name, D the owner, F the status, G the start date, H the due date, J the % complete, L the budget, M the actual and O the notes. Every check below uses those columns.
1. The Calendar Is Ahead of the Work
The blunt version, and the one to run first.
=(TODAY()-MIN($G$4:$G$200)+1)/(MAX($H$4:$H$200)-MIN($G$4:$G$200)+1)
That is the share of the project’s calendar you have consumed, counted inclusively — the same +1 convention the duration column uses, so the two agree. Compare it against your overall % complete.
| Day 31 of 54 | |
|---|---|
| Calendar elapsed | 57.4% |
| Work complete | 33.3% |
Threshold: a gap over about ten points, on a project past its first quarter, is real — that is my own working line, not a standard. Twenty-four points is not a wobble.
The trap is that this comparison feels fine right up until it doesn’t, because early projects are naturally front-loaded with quick tasks. Ignore the reading for the first 25% of the calendar; take it seriously after that.
2. Planned Percent Beats Actual Percent
Sharper than check 1, because it credits each task against its own window rather than the project’s.
Add a column beside % complete:
=IF($G3="","",MEDIAN(0,(TODAY()-$G3+1)/($H3-$G3+1),1))
MEDIAN of three values is a clamp: below zero returns zero, above one returns one, anything in between passes through. A task not yet started reads 0%. A task whose window has closed reads 100%, whatever actually happened.
The IF guard is not optional. On an empty row the arithmetic becomes (TODAY()-0+1)/(0-0+1) — a five-figure number — which clamps to 1 and reports every blank row as 100% planned. Leave it out and the average is meaningless the moment your list has spare rows.
Average that column against the real one:
| Value | |
|---|---|
| Planned by today | 54.6% |
| Actual | 33.3% |
| Schedule variance | −21.3 points |
Then read it task by task, because the average hides where the damage is:
| Task | Planned | Actual | Gap |
|---|---|---|---|
| CMS setup | 70% | 0% | −70 |
| Copywriting | 100% | 40% | −60 |
| Front-end build | 41% | 0% | −41 |
| Visual design | 100% | 60% | −40 |
| SEO redirect map | 38% | 0% | −38 |
| Content migration | 7% | 0% | −7 |
| Everything else | — | — | 0 |
Six tasks carry the entire variance, and the first five carry almost all of it. That is a short list of conversations, not a project-wide crisis.
3. A Window That Has Opened With Nothing In It
The single earliest signal there is, and nothing flags it.
=AND($G3<>"", $G3<=TODAY(), $J3=0, $H3>TODAY())
Started, zero progress, not yet overdue. No dashboard tile counts it, because overdue counts compare against the due date. Front-end build in the worked project is seven days into a seventeen-day window at 0% — and it is the $3,000 task the whole back half of the schedule sits on.
Threshold: any task more than 20% into its window at 0% needs an explanation today. Twenty percent is a rule of thumb, not a measured figure — pick a line and hold to it. Put this rule in conditional formatting and let it colour the row amber.
4. The Same Tasks Are Overdue Two Weeks Running
An overdue count is a snapshot. What matters is whether the same rows are in it.
A spreadsheet forgets last week unless you tell it to remember, so add one column per week — call it W — and paste the % complete column into it as values every Friday. Two snapshots is all you need:
=IF(AND($C3<>"",$H3<TODAY(),$F3<>"Done",$J3=$W3),"STALLED","")
Note which column each term reads: $F3 is the status, $J3 is this week’s percent and $W3 is last week’s pasted percent. Comparing the status against the snapshot — the easy slip here — gives a test that can never fire.
Threshold: a task that is overdue and whose percent has not moved in seven days is not late — it is stopped. Those are different problems with different fixes, and only the snapshot distinguishes them.
Visual design at 60% and Copywriting at 40% are both overdue in the worked project. Whether they are moving is the difference between a two-day slip and a dead task, and no single-snapshot dashboard can tell you which.
5. Percent Complete Only Ever Reads 0 or 100
=COUNTIFS($J$4:$J$200,">0",$J$4:$J$200,"<1")
That counts tasks in partial progress. On a live project of any size it should not be zero.
If it is, the % column is a duplicate of the status column and has no early-warning value — every task is fine until the moment it is finished or missed. Checks 2 and 3 both stop working, because both depend on partial numbers being real.
Threshold: at least one task in partial progress per person actively working. The fix is not more precision — nobody needs 63% — it is a habit of moving a number to 25, 50 or 75 when work is genuinely at those points.
6. Blocked Work With No Named Blocker
“Blocked” is the most useful status and the most abused. A blocked task with an empty notes cell is usually a task nobody wants to own.
=COUNTIFS($F$4:$F$200,"Blocked",$O$4:$O$200,"")
(Notes:Notes is not valid syntax outside an Excel Table — use the column letter, or Tasks[Notes] if your list really is a Table.)
Threshold: zero. Every blocked row should name what it is waiting for and, ideally, who owns the unblocking — which is frequently not the person who owns the task.
In the worked project, SEO redirect map is Blocked with an eight-day window that opened on Mar 30. Blocked is not a resting state. It is a queue with somebody else’s name on it, and if that name is not written down, the task will still be blocked next week.
7. Spend Is Running Ahead of Progress
The money check, and it is one line:
=SUM($M$4:$M$200)/SUM($L$4:$L$200)
Compare against your budget-weighted % complete — =SUMPRODUCT($J$4:$J$200,$L$4:$L$200)/SUM($L$4:$L$200).
| Value | |
|---|---|
| Budget consumed | 34.5% ($3,790 of $11,000) |
| Work complete (budget-weighted) | 35.1% |
Those tracking within a point of each other is the healthy pattern, and it is worth saying plainly that this project’s money is fine. The estimating was good: the three finished tasks came to $2,710 against a $2,600 budget, 4% over.
Threshold: spend more than 10 points ahead of progress — again, a working line rather than a measured one — means the work is costing more than planned. Spend well behind progress is not automatically good news — on this project it mostly reflects the $3,000 build that has not started, which is the problem from check 3 showing up in a second place.
The Weekly Ten Minutes
Run 1, 2 and 3 every week. Run 4 once you have two snapshots. Run 5, 6 and 7 monthly.
On this project, that ten minutes produces one sentence: the schedule is 21 points behind, six tasks account for all of it, and the largest task in the project has been open for seven days without starting. That sentence is available on day 31. The missed launch date is on day 54.
Nothing here needs a new tool. It needs a due date, a start date and a percent on every row — and someone reading the gap between two columns once a week. The task list those columns live on, and the Gantt view that makes signal 3 visible at a glance.
Featured on ReadySheetGo
Project Management & Gantt Chart Tracker — $14.99
Eight tabs, with the columns these checks depend on already in place. The Task List carries project, owner, priority, status, start and due dates, automatic duration, % complete, a Depends On (ID) column and budget, actual and variance per task — overdue rows turn red on their own. The Gantt Chart draws bars from those dates and shades completed against remaining, which is what makes an opened-but-empty window obvious. The Kanban Board re-sorts by status into To Do, In Progress and Done as work moves. Milestones counts down days left and flags at-risk dates. Projects rolls up task count, done, % complete, open items and budget versus actual across every project. The Dashboard returns total tasks, completed, in progress, overdue, overall % complete, budget versus actual and workload by owner.
Sample data pre-filled across four example projects. Works in Excel and Google Sheets, no macros and no add-ons.
Get the Project Management & Gantt Chart Tracker →
Frequently Asked Questions
How do you know if a project is going to be late?
Compare how much of the calendar you have used against how much of the work is finished. If 57% of the days have gone and 33% of the work is done, the project is behind by a margin that will not close on its own, and you can see it long before any due date is missed. The refinement is to calculate what should be complete by today given each task's own window — in the worked project here that is 54.6% planned against 33.3% actual, a 21.3 point gap on day 31 of 54.
What is the earliest sign that a project is slipping?
A task whose start date has passed and whose percent complete is still zero, while its due date is still in the future. Nothing flags it — it is not overdue, so no dashboard tile counts it and no cell turns red — but a seventeen-day task that is seven days into its window at zero percent has already lost seven days it will never get back. With start dates in G, due dates in H and % complete in J, the formula is =AND($G3<>"",$G3<=TODAY(),$J3=0,$H3>TODAY()).
How do you calculate planned percent complete in Excel?
For each task, work out what fraction of its own window has elapsed and clamp the result between 0 and 1: =IF($G3="","",MEDIAN(0,(TODAY()-$G3+1)/($H3-$G3+1),1)) with start in G and due in H. MEDIAN of three values is a neat clamp — anything below zero returns zero, anything above one returns one. The IF guard matters: without it an empty row divides by a denominator of 1 and reads as 100% planned, quietly inflating the average. Average that column and compare it against the average of actual percent complete. The gap between the two is your schedule variance.
Why does percent complete jump straight from 0 to 100?
Because nobody updates it in between, which means it is a status column wearing a number's clothes and it carries no early-warning value at all. A healthy list has some tasks sitting between the extremes at any given time — check with =COUNTIFS($J$4:$J$200,">0",$J$4:$J$200,"<1"). If that count is zero on a live project, you will find out about every slip on the day the task was due rather than a week before.