How to track subcontractor bids in Excel (free template layout)
A bid tracking spreadsheet layout for general contractors: one row per invitation, sixteen columns, six status values, the filters you'll use daily, and a twenty-minute build guide.
You don't need software to track who's bidding. You need one sheet, one row per invitation, and the discipline to update it every day. That last part is harder than the first two, but the layout helps. Here's one that works, where it breaks, and how to build it in about twenty minutes.
The principle: one row per invitation
Not one row per company. Not one row per scope with the bidders spread across columns. One row for each person you invited on each scope. If you invite the same electrical contact on electrical and again on fire alarm, that's two rows.
It feels like more work. It's less, because every filter and every count falls out automatically once the data is shaped this way.
The sixteen columns
The bold ones can't be skipped.
| Column | Contents |
|---|---|
| Project | Same spelling every time; use a dropdown |
| Scope | Cost code plus name, "26 00 00 Electrical," from a dropdown |
| Company | Exactly as on the trade list |
| Contact | First and last name |
| For copying into a merge later | |
| Phone | Mobile, for bid day |
| Sent | Date the invitation went out |
| Status | Dropdown, six values below |
| Status date | When it last changed |
| Follow-up 1 | Date sent, blank if not yet |
| Follow-up 2 | Date sent |
| Add 1 / Add 2 / Add 3 | Date sent, then "conf" on confirmation |
| Bid amount | Filled on bid day |
| Notes | "Wants a walkthrough." "Excludes ceilings." "Left message." |
The six status values
Define them, and use data validation so nobody can type "probably."
Not sent: row created, invitation not out yet. Useful for planning a scope before you send. Sent: out, no reply. Bidding: they've said they will. Maybe: treat it as a conversation, not a final answer. Not bidding: declined, and keep the row, because you want to know they were asked. Bid received: number in, so fill in Bid amount.
The five views you'll use every day
Who hasn't responded on electrical? Filter Scope = Electrical, Status = Sent. That's your follow-up list.
How many bids per scope? A pivot: rows = Scope, columns = Status, values = count. Check it on day 8. Fewer than three Bidding on a major scope means act now, not next week.
Who needs Addendum 2? Filter Status ≠ Not bidding, Add 2 = blank. Copy the Email column straight into the merge.
Who said bidding and hasn't sent a number? Bid day morning: Status = Bidding, Bid amount = blank. That's the phone list.
Response rate: (Bidding + Maybe + Not bidding + Bid received) ÷ (everything except Not sent), on a summary tab.
Three conditional formatting rules, and no more
Status = Sent and the Sent date is more than 3 days ago: yellow, follow up. Status = Sent and more than 8 days ago: orange, phone. Status = Bidding on bid day with Bid amount blank: red.
Add more than that and the sheet becomes a Christmas tree nobody reads.
The daily habit
Update the row before replying to any sub. Not after. Every morning, five minutes: filter to Sent, sort by date, handle the yellow and orange. Bid day morning: the Bidding-without-a-number filter, then the phone. After bid day: copy the final statuses back to the trade list ("last invited," "last bid," and a note on anyone who said Bidding and then went silent).
Sharing it
One estimator, one sheet: fine. Two estimators: the sheet has to live somewhere both people edit it live, meaning Excel on SharePoint or OneDrive, or Google Sheets. Not emailed around. Not copied to desktops. Two copies means the sheet is wrong, and a wrong tracking sheet is worse than no sheet at all, because you trust it.
Where it breaks
Three places, and they're all the same underlying problem: the sheet depends on a human noticing something and typing it in.
It can't see who opened the invitation. "Sent" is all it knows. A sub who never received the email and a sub who's ignoring you look identical in the sheet.
Status only changes when somebody changes it. A reply to the other estimator, a phone call, a word exchanged on site: if nobody types it in, the sheet lies.
Addenda are manual. Filter, copy, merge, then a column to fill in as confirmations trickle back. On a busy day it gets done "later."
Those three are what invitation software automates. Invite All records delivered, clicked, viewed and the Bidding / Maybe / Not bidding click per contact, so the status column fills itself in and "who hasn't looked" finally has an answer. If the daily habit is slipping, we think it's the natural upgrade, and it imports the same one-row-per-person trade list. But a one- or two-estimator shop with the discipline to update before replying can run on this sheet for years, and some do.
Build it in twenty minutes
New workbook. Tab 1 "Tracking," tab 2 "Lists." On Lists, type the six status values in one column and your cost codes in another (starter code list here). On Tracking, type the sixteen headers and freeze the top row. Data validation on Status and Scope, pointing at Lists. The three conditional formatting rules. Convert the range to a table so filters and the pivot are one click. Save it somewhere shared, and tell the other estimator where it is.