Repository navigation
SpreadsheetValidator
Type: Component (Service) Domain: Spreadsheet Processing / District Volume Import Status: Complete (Issue #905) Last updated: 2026-06-17
SpreadsheetValidator validates a worksheet's header structure against a MatrixConfig. It checks that group headers and sub-column headers are present at the expected rows and column positions, returning a ValidationResult with descriptive error messages.
Used both as a pre-upload validator (via interiorValidator and coastValidator) and inline during processor execution.
Stateless service. No constructor parameters.
Validates worksheet headers against a matrix configuration.
| Parameter | Type | Required | Description |
|---|---|---|---|
worksheet |
ExcelJS.Worksheet |
yes | Worksheet from ExcelReader.read()
|
config |
MatrixConfig |
yes | Expected matrix layout configuration |
Returns: ValidationResult — { valid: boolean, errors: string[] }. Errors contain human-readable messages identifying missing or mispositioned headers.
If worksheet.rowCount < config.dataStartRow, returns immediately with a single error: no data rows found.
For each group in config.groups, reads worksheet cell at (config.groupHeaderRow, group.colStart). If the cell is empty or whitespace-only, an error is added: Missing group header at column N, expected "label".
For each sub-column in each group, reads the cell at (config.columnHeaderRow, colIdx). If empty, an error is added: Missing column header at column N (row M), expected "header".
Whitespace normalization: all cell text is cleaned via replace(/\s+/g, ' ').trim() before comparison. This matches the cleaning applied by MatrixParser and the configs.
If the worksheet has no data rows, the validator returns immediately without checking headers. This avoids misleading "missing header" errors when the file is fundamentally empty.
Returns errors as a ValidationResult rather than throwing exceptions. Callers always receive a result object, never an unhandled rejection.
SpreadsheetValidator does NOT validate individual cell values or data types — that is the responsibility of downstream mappers and Zod schemas.
| Dependency | Purpose |
|---|---|
exceljs |
Worksheet row/cell access |
types.ts (local) |
MatrixConfig, ValidationResult
|
| Constraint | Detail |
|---|---|
| Headers only | Does not check data cell values, types, or ranges |
| Whitespace normalization | Header text is cleaned before checking |
| Case-sensitive | Compares cell text as-is (use interiorValidator/coastValidator for case-insensitive sheet names) |
| Artifact | Path |
|---|---|
| Service | frontend/src/services/spreadsheet/spreadsheetValidator.ts |
| Types | frontend/src/services/spreadsheet/types.ts |
| Tests | frontend/src/services/spreadsheet/spreadsheetValidator.unit.test.ts |
5 tests covering: valid worksheet, no data rows, missing group header, missing column header, and multiple simultaneous errors.
| Consumer | Location | Usage |
|---|---|---|
| interiorValidator | src/services/districtvolumes/validators/ |
Pre-upload validation for Interior files |
| coastValidator | src/services/districtvolumes/validators/ |
Pre-upload validation for Coast files |
| DistrictVolumeProcessor | src/services/districtvolumes/processors/ |
Internal validation during processing |
import { ExcelReader } from '@/services/spreadsheet/excelReader';
import { SpreadsheetValidator } from '@/services/spreadsheet/spreadsheetValidator';
import { interiorMatrixConfig } from '@/services/districtvolumes/config/interiorMatrixConfig';
const reader = new ExcelReader();
const worksheet = await reader.read(file, 'Interior');
const validator = new SpreadsheetValidator();
const result = validator.validateWorksheet(worksheet, interiorMatrixConfig);
if (!result.valid) {
console.error(result.errors); // ['Missing group header at column 2, expected "Dry Belt m3/ha"']
}| Reference | Link |
|---|---|
| GitHub Issue | #905 |
| Related page | ExcelReader |
| Related page | MatrixParser |
This wiki documents NR Waste Plus for users and developers. Verify security and deployment guidance against the current application configuration before applying it elsewhere.
- Report an issue or ask a question in the GitHub repository.
- Follow the Contributing Guidelines to propose an update.
- Read the Code of Conduct.
Collection indexes support human browsing and machine retrieval. Keep both current when adding or moving wiki pages.
NR Waste Plus Wiki | GitHub Repository