The exposure workbook is the hardest document in a casualty submission — and the most valuable. Payroll by class, vehicle schedules, SOVs, subcontractor lists, contractor work-in-progress by region: hundreds of rows across many sheets, in a layout every broker builds differently. This is exactly where template OCR and “LLM, read this spreadsheet” both fall over. Here’s how InsightXtract reads it — deterministically, every sheet, nothing dropped.
Why workbooks break naive extractors
- A metadata block above a table — Insured / Policy Period / Total Payroll sitting one blank row above a wide exposure grid. Zone-splitters collapse the two into a single 2-column mess.
- Stacked group headers — a row of merged group labels (“Current Estimate”, “Inception-to-Date”, “Backlog”) over a row of sub-columns. The sub-header row gets mistaken for data.
- Multiple tables per sheet, sub-tables (vehicle-type counts, rented-auto counts), and per-region sheets (MIQ / WEST / SOUTH…).
- Broker-specific wording — “Total Payroll” vs “Payroll”, “GL Exposure” vs “General Liability”.
Step 1 — Classify every sheet, every region
InsightXtract loads every sheet, splits it into regions on blank rows, and classifies each region as a key-value metadata block or a table (single- or stacked-header). Each detected table is mapped to a typed schedule by header name. A real operations workbook maps like this:
Every sheet is surfaced — even a sub-table the base schema didn’t anticipate is emitted under its sheet name, so no data is silently lost.
Step 2 — Flatten stacked group headers
The contractor WIP workbook has 400 project rows per region under grouped headers. InsightXtract detects the two-row header, forward-fills the merged group labels, and flattens each leaf column to group — sub — turning an unreadable grid into clean, typed columns:
[ Current Project Estimate ][ Backlog ] Revenue | Cost | GP (Loss) | ... | Revenue | ... 17,451,000 | 14,497,639 | ...
current_project_estimate_revenue current_project_estimate_cost_of_revenues current_project_estimate_gross_profit_loss backlog_revenue ...
This is a heuristic, not a per-file rule — any grouped-header workbook flattens the same way, whatever the groups are named.
Step 3 — Type & normalize the columns
Each schedule column is bound to a governed vocabulary, so raw broker wording lands as canonical codes and out-of-vocabulary values are flagged:
| Division | State | WC Code | Description | Revenue | Payroll |
|---|---|---|---|---|---|
| MIQ | LA us_state_codes | 91583 ncci_wc_class_codes | Masonry | $31,131,000 | $5,345,945 |
| WEST | CA | 95410 | Plumbing – Commercial | $18,470,000 | $3,112,600 |
Bindings: state → us_state_codes, class → ncci_wc_class_codes, vehicle type → vehicle_body_types, occupancy → occupancy_types, construction → construction_types. And because column resolution is fuzzy, a rule written for payroll still binds a broker’s “Total Payroll” column.
Step 4 — Derive header exposures
Rating happens on totals, not rows. The document type declares deterministic sum / count / group_by rules that compute over the extracted rows — exact, reproducible, and traceable. From this workbook:
The last is a cross-region wildcard sum — across all seven WIP sheets (1,330 projects) — so it stays right no matter how many regions the workbook holds. No LLM arithmetic anywhere.
Any workbook, any broker template
The extractor is structural, not per-file: read all sheets, classify regions, flatten grouped headers, map to typed schedules, normalize, derive. See the full submission walkthrough →