Proper Spreadsheets

Templates › Business

Job Quotes & Margin Tracker

Made for builders, electricians, plumbers and other trades.

A workbook for a tradesman: record every quote with its customer, labour hours and rate, materials and quoted price; see the margin made on each job and the win rate on quotes. The summary carries a chart that redraws itself as you type.

Of the 36 columns, you fill in 26 and the other 10 work themselves out, and all 18 figures on the summary do too. There is room for 1,450 rows of your own.

£4.99one payment, yours to keep

  • Opens in Excel, Google Sheets and Numbers
  • Delivered straight away
  • No macros, nothing to install
  • Change it free before you buy

Payment is handled by Stripe. Your card details go to them and never to us. Sales are final, which is why every tab, column and calculation is shown on this page first.

Already have a spreadsheet of your own? Check it for mistakes, free.

The workbook's summary and the table behind it
A row typed into the real file. Every figure that changes is the spreadsheet's own arithmetic. What the film shows, in order:
  1. A new row is typed into the Quotes tab, one cell at a time, in the white cells a person fills in.
  2. The shaded cells in that row fill themselves in.
  3. The figures on the Summary tab change to include the new row.
  4. The chart, Value quoted by job type, redraws with it.
The chart, drawn from the totals in the table beside it. See it full size
Where you type, and the shaded columns that work themselves out. See it full size

Everything inside, before you pay

This is the whole design: every tab, every column and how each calculated one is worked out. White cells are yours to fill in; the shaded ones work themselves out and are locked so a formula cannot be overwritten by accident. There is room for 1,450 rows. Open any tab to see its columns.

Customers

10 columns

Everyone you quote for. Add a customer here first so it appears in the dropdown on the Quotes tab. Ready for 150 rows, every one with its formulas in place.

ColumnWhat goes in itWorked out as
CustomerType any text.
ContactType any text.
PhoneType any text.
EmailType any text.
TypePick one: Domestic, Landlord, Letting Agent, Commercial or Builder / Trade.
Town / AreaType any text.
Quotes SentFills itself in.

The number of rows on Quotes where Customer matches this row's Customer.

The formulaIF(ISBLANK([customer_name]), "", COUNTIF([Quotes!customer], [customer_name]))
Jobs WonFills itself in.

The number of rows on Quotes where Customer matches this row's Customer and Status is “Won”.

The formulaIF(ISBLANK([customer_name]), "", COUNTIFS([Quotes!customer], [customer_name], [Quotes!status], "Won"))
Value WonFills itself in.

The total of Price Quoted on Quotes where Customer matches this row's Customer and Status is “Won”.

The formulaIF(ISBLANK([customer_name]), "", ROUND(SUMIFS([Quotes!quoted_price], [Quotes!customer], [customer_name], [Quotes!status], "Won"), 2))
NotesType any text.

Quotes

18 columns

One row per quote. Fill in the hours, your rate and the price you quoted. Materials pull through from the Materials tab, and the margin works itself out. Ready for 300 rows, every one with its formulas in place.

ColumnWhat goes in itWorked out as
Quote NoYour own reference, e.g. Q-1041. Materials lines are matched to this.Type any text.
Date QuotedType a date.
CustomerPick one of the Customer entries on Customers.
JobType any text.
Job TypePick one: Plumbing, Electrical, Carpentry, Tiling, Painting, Roofing, Bathroom Fit, Kitchen Fit, General Maintenance or Other.
StatusPick one: Quoted, Won, Lost or Cancelled.
Labour HoursType a number.
Hourly RateType an amount in £.
Labour CostFills itself in.

Worked out from this row's Quote No, Labour Hours and Hourly Rate.

The formulaIF(ISBLANK([quote_ref]), "", ROUND([labour_hours] * [hourly_rate], 2))
Materials CostFills itself in.

The total of Line Cost on Materials where Quote No matches this row's Quote No.

The formulaIF(ISBLANK([quote_ref]), "", ROUND(SUMIF([Materials!quote_ref], [quote_ref], [Materials!line_cost]), 2))
Other CostsType an amount in £.
Total CostFills itself in.

Worked out from this row's Quote No, Labour Cost, Materials Cost and Other Costs.

The formulaIF(ISBLANK([quote_ref]), "", ROUND([labour_cost] + [materials_cost] + [other_costs], 2))
Price QuotedType an amount in £.
MarginFills itself in.

Worked out from this row's Quote No, Price Quoted and Total Cost.

The formulaIF(ISBLANK([quote_ref]), "", ROUND([quoted_price] - [total_cost], 2))
Margin %Fills itself in.

Worked out from this row's Quote No, Margin and Price Quoted.

The formulaIF(ISBLANK([quote_ref]), "", IFERROR([margin_value] / [quoted_price], 0))
Effective £/HourFills itself in.

Worked out from this row's Quote No, Price Quoted, Materials Cost, Other Costs and Labour Hours.

The formulaIF(ISBLANK([quote_ref]), "", IFERROR(([quoted_price] - [materials_cost] - [other_costs]) / [labour_hours], 0))
Decided OnThe day the customer said yes or no.Type a date.
NotesType any text.

Materials

8 columns

Materials bought or priced in for each quote. Each line adds itself to that quote's materials cost. Ready for 1,000 rows, every one with its formulas in place.

ColumnWhat goes in itWorked out as
Quote NoPick one of the Quote No entries on Quotes.
DateType a date.
ItemType any text.
SupplierType any text.
QtyType a number.
Unit CostType an amount in £.
Line CostFills itself in.

Worked out from this row's Item, Qty and Unit Cost.

The formulaIF(ISBLANK([item]), "", ROUND([quantity] * [unit_cost], 2))
NotesType any text.

Summary

18 figures

Win rate and the money made, updating as you fill the Quotes tab in.

FigureWorked out as
Quotes recorded

The number of rows on Quotes with Quote No filled in.

The formulaCOUNTA([Quotes!quote_ref])
Quotes still awaiting a decision

The number of rows on Quotes where Status is “Quoted”.

The formulaCOUNTIF([Quotes!status], "Quoted")
Value out with customersPrice quoted on jobs not yet won or lost.

The total of Price Quoted on Quotes where Status is “Quoted”.

The formulaROUND(SUMIF([Quotes!status], "Quoted", [Quotes!quoted_price]), 2)
Jobs won

The number of rows on Quotes where Status is “Won”.

The formulaCOUNTIF([Quotes!status], "Won")
Jobs lost

The number of rows on Quotes where Status is “Lost”.

The formulaCOUNTIF([Quotes!status], "Lost")
Win rateWon as a share of everything decided; cancelled and pending quotes are left out.

Worked out from Status on Quotes.

The formulaIFERROR(COUNTIF([Quotes!status], "Won") / (COUNTIF([Quotes!status], "Won") + COUNTIF([Quotes!status], "Lost")), 0)
Total value quoted (all quotes)

The total of Price Quoted on Quotes.

The formulaROUND(SUM([Quotes!quoted_price]), 2)
Value of work won

The total of Price Quoted on Quotes where Status is “Won”.

The formulaROUND(SUMIF([Quotes!status], "Won", [Quotes!quoted_price]), 2)
Cost of work won

The total of Total Cost on Quotes where Status is “Won”.

The formulaROUND(SUMIF([Quotes!status], "Won", [Quotes!total_cost]), 2)
Profit on work won

Worked out from Status, Price Quoted and Total Cost on Quotes.

The formulaROUND(SUMIF([Quotes!status], "Won", [Quotes!quoted_price]) - SUMIF([Quotes!status], "Won", [Quotes!total_cost]), 2)
Average margin on work won

Worked out from Status, Price Quoted and Total Cost on Quotes.

The formulaIFERROR((SUMIF([Quotes!status], "Won", [Quotes!quoted_price]) - SUMIF([Quotes!status], "Won", [Quotes!total_cost])) / SUMIF([Quotes!status], "Won", [Quotes!quoted_price]), 0)
Average job value won

Worked out from Status and Price Quoted on Quotes.

The formulaIFERROR(SUMIF([Quotes!status], "Won", [Quotes!quoted_price]) / COUNTIF([Quotes!status], "Won"), 0)
Labour hours on work won

The total of Labour Hours on Quotes where Status is “Won”.

The formulaSUMIF([Quotes!status], "Won", [Quotes!labour_hours])
Profit per labour hour on work wonWhat each hour on site actually earned you after materials.

Worked out from Status, Price Quoted, Total Cost and Labour Hours on Quotes.

The formulaIFERROR((SUMIF([Quotes!status], "Won", [Quotes!quoted_price]) - SUMIF([Quotes!status], "Won", [Quotes!total_cost])) / SUMIF([Quotes!status], "Won", [Quotes!labour_hours]), 0)
Jobs won at under 10% marginPriced too keenly, worth a look before you quote the next one.

The number of rows on Quotes where Status is “Won” and Margin % is below 0.1.

The formulaCOUNTIFS([Quotes!status], "Won", [Quotes!margin_pct], "<0.1")
Quotes sent this year

Worked out from Date Quoted on Quotes.

The formulaCOUNTIFS([Quotes!date_quoted], ">=" & DATE(YEAR(TODAY()), 1, 1))
Quotes sent in the last 30 days

Worked out from Date Quoted on Quotes.

The formulaCOUNTIFS([Quotes!date_quoted], ">=" & TODAY() - 30)
Materials spend recorded

The total of Line Cost on Materials.

The formulaROUND(SUM([Materials!line_cost]), 2)