BESS installation labour estimator
A takeoff and man-hour model for the electrical scope of a grid-scale battery site — DC and AC cable pulling, terminations, conduit, and the BESS-specific work that no general electrical labour book has a line for. It ships the structure. You bring the labour units.
- A cable schedule — one line per scope, and the runs and lengths are yours to measure.
- 28 labour units to start, more if you add scope. No tool ships these; the reason is below.
- One wage rate, and only if you want a cost. The hours stand without it.
What this is, and is not. An estimating aid, not a bid and not a compliance document. It computes man-hours from quantities and the labour units you supply; it does not tell you what those units should be. Check the result against your own history before it leaves your desk.
Fuller instructions — how the schedule behaves, the file round trip, what each step asks for — are in Getting to a number, below the tool.
01Block specification
Twenty 5 MWh enclosures on one conversion block. Row spacing assumed typical for a utility-scale site.
Cable schedule
Each line becomes a pull and, except where it is priced as MV, its terminations. Conductors per run is asked rather than assumed: a DC pull carrying + and − is ONE run with TWO conductors, and the units are per conductor-foot — getting it backwards doubles or halves the largest line on the sheet.
| Scope | Runs | Length (ft) | Conductors / run | Priced as | Size | Remove |
|---|---|---|---|---|---|---|
Enclosure internals — cabinets to a connection box (off)
For a block where the run from each cabinet to its connection box differs enough to be worth stating separately. Each cabinet adds its own pull and terminations to the takeoff.
Conversion scope, derived: 1 PCS skid · 1 transformer · 0 MV runs · 900 tray-ft. Change the enclosure count and these four follow it — the cable schedule above does not, because its runs and lengths are yours to state — these are the preset’s starting figures, not a measurement of your site. That is 50 MW per PCS skid — check it against your own conversion design and change enclosures per PCS skid in the fields above if it does not match.
MV collection and comms — the values the schedule does not carry
Polarity is a conductor, not a run. A DC pull carrying + and − is one pull with two conductors, and the cable rows are priced per conductor-foot. Getting this backwards doubles or halves the biggest line on the sheet.
02Labour units
This tool ships the structure of a BESS electrical takeoff — 316 unit records across 25 categories — and no labour values: you bring those, from your own licensed source or from what your own crews actually book. Why it ships without labour units is below the tool.
Licensed labour units. If you hold a licence to the source manual and this site has granted your address access, sign in and the units this takeoff needs load by themselves. Sessions are short, so if values you had stop appearing, sign in again. Most visitors do not need this: the tool works from your own values.
Values stay in this browser. Nothing you enter is transmitted or stored on a server. The blank template never contains a value. Your filled sheet and the estimate export do — they are your numbers, in a file only you have.
Enter them here — 0 of 28 doneman-hours per unit, at Normal · Enter moves to the next · 3 of these do not vary by condition and are stored once
Enter moves to the next unit value.
DC cable pulling0 / 2
- Battery Cabinet to combiner — 500 kcmilmh / 1,000 ft
- DC equipment grounding conductor — #4/0mh / 1,000 ft
Terminations0 / 2
- Battery Cabinet to combiner — lugs, Compression lug, two hole, 500 kcmilmh / each
- DC equipment grounding conductor — lugs, Compression lug, two hole, #4/0mh / each
Conduit0 / 5
- Underground DC duct — combiner to PCS — PVC Sch 40, 4"mh / 100 ft
- Underground DC duct — enclosures to combiner — PVC Sch 40, 3"mh / 100 ft
- BMS / comms raceway — EMT, 1"mh / 100 ft
- Stub-ups / risers at battery enclosures — GRC / RMC steel, 3"mh / 100 ft
- Stub-ups / risers at PCS skid — GRC / RMC steel, 4"mh / 100 ft
Conduit fittings0 / 6
- Comms raceway terminations — EMT set-screw box connector, 1"mh / each
- Comms raceway elbows — EMT factory elbow, 1"mh / each
- Underground duct bends — PVC Sch 40 elbow, 3"mh / each
- Riser elbows at battery enclosures — GRC factory elbow, 3"mh / each
- Enclosure conduit entries — GRC locknut and bushing set, 3"mh / each
- Riser elbows at PCS skid — GRC factory elbow, 4"mh / each
Equipment setting0 / 3
- Battery enclosure - hoist, set, level and shim, anchor with torque recordmh / each
- PCS skid - set, level, anchormh / each
- MV transformer - set, level, anchormh / each
BESS internal wiring0 / 2
- Maintenance service disconnect installmh / each
- OEM harness route, dress and landmh / each
Thermal management0 / 1
- Coolant loop connect, fill, bleedmh / each
Comms and controls0 / 1
- CAN / RS-485 daisy chain per rackmh / each
Test and turnover0 / 2
- Insulation resistance test per DC circuitmh / each
- Pack voltage and SoC balance verification before series connectionmh / each
Transformer connections0 / 3
- HV elbow or deadbreak landingmh / each
- LV bushing landingmh / each
- Ground-grid bondingmh / each
Tray and supports0 / 1
- Ladder tray, 18 inmh / 100 ft
Fill missing sizes from my own size step — 5 size families in this takeoff
Type your value for one size, then your own multiplier per size step. Larger sizes without a value follow upward from your nearest typed size; sizes below it stay open rather than dividing down. We ship no ladder — the anchor and the step are both yours, and a derived value always shows as a placeholder marked derived.
Bring them as a file instead — download the sheet, fill it, re-import
03Takeoff and hours
The takeoff below is every row your schedule and block produce — 28 of them — but nothing can be priced until you enter labour units in section 02 — Labour units. Every figure stays blank until then, because a zero would read as an answer.
Duct without conductors: the takeoff prices underground DC duct for Combiner to PCS, and no schedule line is named for it — so unless one of your own lines covers that run, no cable pull and no termination for it is in the hours below. Add a line in 01 if that scope is yours. Scope: this takeoff covers the DC block. It does not include AC LV collection, MV collection, MV terminations, enclosure bonding, station service, protection and relaying, fire and gas detection, SCADA checkout. The per-MWh and per-enclosure figures are therefore for the scope above, not for a whole site — add the rest before comparing them to a contractor’s number.
Skip the takeoff table| Scope | Quantity | Unit | Man-hours | Actions |
|---|---|---|---|---|
| Battery Cabinet to combiner — 500 kcmilDC cable pulling | runs22,680 conductor-ft (incl. 5% slack) | needs a value | ||
| Battery Cabinet to combiner — lugs, Compression lug, two hole, 500 kcmilTerminations | count480 each (120 runs × 4 lugs per run) | needs a value | ||
| DC equipment grounding conductor — #4/0DC cable pulling | runs1,890 conductor-ft (incl. 5% slack) | needs a value | ||
| DC equipment grounding conductor — lugs, Compression lug, two hole, #4/0Terminations | count40 each (20 runs × 2 lugs per run) | needs a value | ||
| Underground DC duct — enclosures to combiner — PVC Sch 40, 3"Conduit | ft2,400 raceway-ft (120 ft per enclosure × 20) | needs a value | ||
| Underground DC duct — combiner to PCS — PVC Sch 40, 4"Conduit | ft7,830 raceway-ft (87 ducts sized from the 260 DC conductors in the cable schedule (no line is named Combiner to PCS, so the schedule's DC cable is the proxy), at 3 singles per duct × 90 ft) | needs a value | ||
| Stub-ups / risers at battery enclosures — GRC / RMC steel, 3"Conduit | ft240 raceway-ft (12 ft per enclosure × 20) | needs a value | ||
| Stub-ups / risers at PCS skid — GRC / RMC steel, 4"Conduit | ft100 raceway-ft (5 ft per enclosure × 20) | needs a value | ||
| BMS / comms raceway — EMT, 1"Conduit | ft600 raceway-ft (30 ft per enclosure × 20) | needs a value | ||
| Riser elbows at battery enclosures — GRC factory elbow, 3"Conduit fittings | count160 each (8 fittings per enclosure × 20) | needs a value | ||
| Riser elbows at PCS skid — GRC factory elbow, 4"Conduit fittings | count80 each (4 fittings per enclosure × 20) | needs a value | ||
| Enclosure conduit entries — GRC locknut and bushing set, 3"Conduit fittings | count160 each (8 fittings per enclosure × 20) | needs a value | ||
| Underground duct bends — PVC Sch 40 elbow, 3"Conduit fittings | count240 each (12 fittings per enclosure × 20) | needs a value | ||
| Comms raceway elbows — EMT factory elbow, 1"Conduit fittings | count280 each (14 fittings per enclosure × 20) | needs a value | ||
| Comms raceway terminations — EMT set-screw box connector, 1"Conduit fittings | count400 each (20 fittings per enclosure × 20) | needs a value | ||
| Battery enclosure - hoist, set, level and shim, anchor with torque recordEquipment setting | count20 each (20 enclosures) | needs a value | ||
| PCS skid - set, level, anchorEquipment setting | count1 each (1 PCS skid, derived from 20 enclosures at 20 per skid) | needs a value | ||
| MV transformer - set, level, anchorEquipment setting | count1 each (1 transformer, one per PCS skid) | needs a value | ||
| Maintenance service disconnect installBESS internal wiring | count20 each (1 per enclosure × 20) | needs a value | ||
| OEM harness route, dress and landBESS internal wiring | count20 each (1 per enclosure × 20) | needs a value | ||
| Coolant loop connect, fill, bleedThermal management | count20 each (1 per enclosure × 20) | needs a value | ||
| CAN / RS-485 daisy chain per rackComms and controls | count40 each (2 links per enclosure × 20) | needs a value | ||
| Insulation resistance test per DC circuitTest and turnover | count120 each (120 DC circuits in the schedule — 20 single-conductor runs excluded, which are bonding or grounding rather than circuits to megger) | needs a value | ||
| Pack voltage and SoC balance verification before series connectionTest and turnover | count20 each (1 per enclosure × 20) | needs a value | ||
| HV elbow or deadbreak landingTransformer connections | count3 each (3 per transformer × 1) | needs a value | ||
| LV bushing landingTransformer connections | count3 each (3 per transformer × 1) | needs a value | ||
| Ground-grid bondingTransformer connections | count1 each (1 per transformer × 1) | needs a value | ||
| Ladder tray, 18 inTray and supports | ft900 raceway-ft (45 ft per enclosure × 20) | needs a value | ||
| Totalpartial | — |
Edit a quantity, remove a row, or add one from any of the 316 unit records — including the scopes this preset does not generate. Changing the block specification re-derives the generated rows and leaves your edits and additions alone.
04Site factors
Combined site efficiency, derived: 1 × 1 → ×1.000 on every direct hour. At 1.0 neither changes the hours.
Material and method — 7 factors, applied only where the unit allows
1.0 is no change. These material factors multiply hours on the units that declare them eligible and are ignored everywhere else — an aluminium deduct on a termination is not harmless, it is wrong in direction. (The two efficiency fields in 04 work the other way round: they divide, so a lower number means more hours.)
Crew size converts man-days into working days — days the crew is on site, not a calendar span; at the 4-day week set below, the calendar is about 75% longer. That is what equipment rental, temporary facilities and travel are charged against. Leave it blank and those three cannot be priced: man-days are working days multiplied by the crew, so charging a daily rate against them overstates it by the crew size.
Scheduled week, derived: 4 × 10 = 40 hours. Hours above the straight-time week set in 05 carry the overtime premium.
There is one clock. Attended hours per shift is the only divisor for duration and man-days, and site efficiency is applied once — as a divisor, so a lower number means more hours. Neither takes a second haircut off the same schedule.
05Rates and cost
Back to the running summaryNo wage rates ship. Inventing a metro number is the same mistake as inventing a labour unit — it reads as authoritative and nobody can tell where it came from. Enter the rates from your own agreement or determination, and — once every row is priced — cost appears.
Rate fields appear here for each craft the takeoff uses — they follow from the hours, and no row carries hours yet. Enter unit values in 02 — Labour units and the wage fields arrive with the crafts.
Three cost rules have no control and are applied as stated: workers’ comp is rated on the overtime premium as well as straight time, payroll tax is always rated on the overtime premium — fixed arithmetic, not a setting — and margin is not taken on contingency. All three are in the estimate export’s assumptions block.
Cost details — overtime split, prevailing wage, travel and site costs
Payroll tax and workers’ compensation ride the base wage, not the wage-plus-fringe package. Bona fide fringe paid into a plan is not taxable wages and is not payroll for comp rating, and burdening it overstates the largest number here by roughly 4% on a typical rate — more on a determination carrying a large fringe. Overtime premium rides the base wage only.
Small tools is also inside the Labour line rather than beside it: it is a percentage of the base wage carried in each craft’s hourly rate, so it moves Labour without appearing as a row of its own. At 2% it is that share of every base-wage hour.
Straight-time week never binds. The scheduled week is 40 hours and the straight-time threshold is 40, so no hour can reach the overtime premium. Lower the threshold below, or add days or hours in 04, if overtime is intended.
The estimate is partial, so a cost would be computed over an incomplete scope. Hours above are unaffected.
| Craft | Man-hours | From |
|---|---|---|
| Total | — |
Getting to a number
- Pick a block and write the cable schedule. Enclosure count and power, then a line per scope: how many runs, how far, how many conductors, what size. The takeoff follows the schedule, so every cable row on the sheet is one you wrote and can correct — and the per-enclosure scopes (equipment setting, comms, conduit, tray) re-derive from the enclosure count.
- The schedule does not multiply itself. Runs and lengths are yours to state — a preset arrives with starting figures, not a measurement of your site — so changing the enclosure count leaves them alone. If a bigger block means more cable, that is a number only you can state.
- Type the unit values, in the panel under “Labour units”. The default block needs 28 of the 316 records — not all 316, and more once you add scope — and they are grouped by trade in the takeoff’s order, each showing the basis, the assumed crew and whether the value is man-hours or crew-elapsed hours. Values come from a source you are entitled to use: your licensed manual, your estimating database, or the hours your own crews book against these tasks. The last of those is the best input anyone has.
- Or bring them as a file. Download exactly the units your takeoff needs (or all 316), fill the sheet, and paste or upload it back — the download follows the live takeoff, not the 28 the default block starts with. The values you enter stay in your browser and are remembered between visits. They are not transmitted to us, and clearing them is one button.
- Enter one wage rate. Cost needs a base and a fringe for each craft the takeoff uses; one composite rate can fill them all, and each field it fills says so. Until a rate exists the ledger returns nothing rather than guessing.
The sheet records each unit’s basis and crew. If a unit’s definition changes after you exported the sheet, the import refuses that value rather than applying it — the same number under a different basis is a different number.
Why it ships without labour units
The obvious way to build this is to load a published labour manual into the page. That is not available to us, and the reason is worth stating plainly rather than hiding behind a disclaimer.
Manuals like NECA’s are commercial publications, and their labour-unit tables are the product being sold. Owning a copy licenses you to use it — including in your own estimating, on your own machine. It does not license anyone to republish the tables on a free web page. And the numbers are not raw facts that copyright leaves alone: they are predicted values reflecting editorial judgement, which courts have treated as protectable in exactly this shape.
The alternative — inventing plausible-looking units so the tool shows a total on landing — is worse. The stated use of this page is checking a contractor’s number. A confident total built on made-up productivity would be the most damaging thing it could do.
So the page ships 316 unit records with their structure fully defined — category, size, install method, unit basis, assumed crew, whether condition changes them, whether the termination already includes torque — and no values. An unpriced row says not priced. It never contributes a zero.
The four things this gets right that spreadsheets usually do not
- Polarity is a conductor, not a runA DC pull carrying + and − is one pull with two conductors. Cable units are per conductor-foot, so treating the pair as two runs doubles the largest line on the sheet. The generator decides this once and the row echoes the basis it resolved.
- Condition selects a column, it does not multiplyNormal, Difficult and Very difficult are three independent values. Nothing here derives the harder tiers from the easy one by a fixed ladder. If you only have a Normal value, you can apply your own step — and it is labelled as yours.
- Torque is a property of the termination, not a separate multiplierIf a termination unit already contains torque-to-spec and witness marking, no separate torque row is generated for those joints. Add one by hand and the takeoff flags the possible double count — it cannot refuse it, because your torque row may cover joints made up outside this takeoff.
- One clockAttended hours per shift is the only divisor for duration and man-days. Site efficiency is applied once, and it divides: at 0.8 the crew gets 80% of the work done per paid hour, so the job needs 1/0.8 as many hours. Dividing paid hours by a net-of-breaks figure and then also applying an efficiency factor takes the same haircut twice, and it is a common way per-diem estimates come out 50% high.
Limits worth knowing before you rely on it
It prices direct installation man-hours first, then adds indirect supervision — foreman by ratio with a minimum-foreman floor, and general foreman by percentage. Those ride in cost and in the total and never in crew-days, because supervision does not shorten a job. The ledger also carries a safety attendant on any row marked as an energised work front, but nothing on this page can mark one yet — no shipped record is flagged and the unit sheet has no column for it — so that term is always zero today.
Cost is optional, and it is withheld rather than guessed. No wage rates ship, for the same reason no labour units ship: you enter your own, and until every craft carrying hours has one the ledger returns nothing. It is withheld while any row is unpriced, and while prevailing wage is switched on without a multiplier — there is no safe default for that number, so the ledger refuses rather than assuming one. The switch lives under “Cost details” in the rates section.
What it still does not model: escalation to a construction midpoint, shift differential, a detailed equipment schedule, per-craft workers’-comp rates, cash-in-lieu fringe, or anything below the line — bonding, insurance, permits, sales tax on materials. Per diem, mobilisation and demobilisation, travel, temporary facilities, the overtime and double-time split and the OEM field-service day rate have inputs in the rates section, most under “Cost details”; anything left at zero is listed as zero rather than hidden.
Per-MWh and per-enclosure figures are withheld whenever any row is unpriced. A normalised number computed over an incomplete scope is precise, quotable and wrong, and it is the failure mode most likely to end up in somebody’s board pack.
The learning curve is implemented and structurally gated: it applies only to units that are first-unit values, and no record in this dataset is one — so it could take no repetition saving even if it were switched on, and no control offers it. That is the safe direction to be wrong in: applying a cumulative-average curve to a unit that is already an average takes roughly 28% off at a hundred repetitions, which is a large and entirely fictional saving.