All articles
How-to

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.

Short answerOne row per invitation, a Status column limited to six values, one column per addendum, and a bid amount column. Keep it in one shared file and update the row before replying to any sub.

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.

ColumnContents
ProjectSame spelling every time; use a dropdown
ScopeCost code plus name, "26 00 00 Electrical," from a dropdown
CompanyExactly as on the trade list
ContactFirst and last name
EmailFor copying into a merge later
PhoneMobile, for bid day
SentDate the invitation went out
StatusDropdown, six values below
Status dateWhen it last changed
Follow-up 1Date sent, blank if not yet
Follow-up 2Date sent
Add 1 / Add 2 / Add 3Date sent, then "conf" on confirmation
Bid amountFilled 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.

Read next

Sending invitations by hand?

Invite All sends a tracked invitation to every trade on a scope from your own inbox. Four quick taps to see if it fits your team.