Skip to content

ExcelReader

Paulo Gomes da Cruz Junior edited this page Jun 17, 2026 · 5 revisions

ExcelReader Service

Type: Component (Service) Domain: District Volume Import / Spreadsheet Processing Status: Complete (Issue #905) Last updated: 2026-06-17

Overview

ExcelReader is a pure file-reading service that forms the file-I/O layer of the spreadsheet import pipeline. It wraps the exceljs library to load .xlsx workbooks from browser File objects, providing typed worksheet access and sheet-name introspection.

Migrated from SheetJS (xlsx) to exceljs for better merged-cell support, streaming, and an actively maintained codebase (see MatrixParser for merged-cell resolution).

Public Interface

Class: ExcelReader

Stateless service. No constructor parameters.

loadWorkbook(file: File): Promise<ExcelJS.Workbook>

Loads the file into an exceljs Workbook object.

Parameter Type Required Description
file File yes Browser File from <input type="file" />

Throws: ExcelReadError — on corrupt file, arrayBuffer failure, or unsupported format.

read(file: File, sheetName?: string): Promise<ExcelJS.Worksheet>

Returns a specific worksheet by name, or the first worksheet if no name given.

Parameter Type Required Description
file File yes Browser File
sheetName string no Worksheet name (default: first sheet)

Returns: ExcelJS.Worksheet — provides row/column/cell access including merge info.

Throws: ExcelReadError — on missing sheet, empty workbook, or file load failure.

listSheets(file: File): Promise<string[]>

Returns all worksheet names in the workbook.

Parameter Type Required Description
file File yes Browser File

Returns: string[] — worksheet names in document order.

Class: ExcelReadError extends Error

Typed error for file-level failures.

export class ExcelReadError extends Error {
  name = 'ExcelReadError';
  constructor(message: string);
}

Design Principles

Pure Service — No UI Dependencies

  • Does NOT import Zod, React, or Carbon UI libraries
  • Only reads and selects worksheets
  • Reusable in non-React contexts

exceljs over SheetJS

  • exceljs is actively maintained; xlsx (SheetJS) is unmaintained
  • exceljs provides native merged-cell resolution via worksheet.mergeCells and worksheet.getCell().type
  • ExcelFile API: file.arrayBuffer() → workbook.xlsx.load(buffer)

Private Error Wrapping

// arrayBuffer failure → ExcelReadError
// workbook.xlsx.load failure → ExcelReadError
// Missing sheet → ExcelReadError

Dependencies

Dependency Version Purpose License
exceljs ^4.4+ Read .xlsx into typed workbook/worksheet objects MIT

Constraints

Constraint Detail
Supported formats .xlsx only (CSV not supported by exceljs in browser)
File size limit 2 MB (enforced by UI layer via maxFileSizeBytes)
Error type Always ExcelReadError for file-level failures
No Zod/React Must never import zod, react, or @carbon/*

Code Location

Artifact Path
Service frontend/src/services/spreadsheet/excelReader.ts
Types frontend/src/services/spreadsheet/types.ts
Tests frontend/src/services/spreadsheet/excelReader.unit.test.ts

Test Coverage

6 tests covering: read (first sheet, named sheet, missing sheet, corrupt file, arrayBuffer failure) and listSheets.

Edge Cases Covered

  • Named sheet not found → ExcelReadError
  • Corrupt file data → ExcelReadError from workbook.xlsx.load()
  • arrayBuffer rejection → ExcelReadError
  • Empty workbook → ExcelReadError

Architecture

Pipeline Role

Layer 1 — ExcelReader           file → ExcelJS.Worksheet
Layer 2 — MatrixParser          Worksheet → flat Record[] (via MatrixConfig)
Layer 3 — SpreadsheetValidator  Worksheet headers → ValidationResult
Layer 4 — DistrictVolumeProcessor  orchestrates 1-3 → ProcessorResult<TableData>

Consumers

Consumer Location Usage
MatrixParser src/services/spreadsheet/matrixParser.ts Receives Worksheet for row iteration
SpreadsheetValidator src/services/spreadsheet/spreadsheetValidator.ts Receives Worksheet for header validation
DistrictVolumeProcessor src/services/districtvolumes/processors/ Creates ExcelReader, calls read + listSheets
Interior Validator src/services/districtvolumes/validators/ Creates ExcelReader for pre-upload validation
Coast Validator src/services/districtvolumes/validators/ Creates ExcelReader for pre-upload validation

Usage Examples

Basic read

import { ExcelReader } from '@/services/spreadsheet/excelReader';

const reader = new ExcelReader();
const worksheet = await reader.read(file, 'Interior');

List sheets (auto-detection)

const sheets = await reader.listSheets(file);
// ['Interior', 'Coast', 'Data', ...]

References

Reference Link
GitHub Issue #905
Epic District Average Waste Volume Tables
Related page MatrixParser
Related page SpreadsheetValidator
Related page DistrictVolumeProcessor

Waste Plus Wiki

Home

Architecture

Codes

Decisions

Knowledge Base

Development

Changes

Clone this wiki locally