xlsxparser 0.11.0

A lightweight, high-performance .xlsx (OOXML) parser library
Documentation
# `model/workbook.rs` Design Doc

*[日本語](workbook.md)*

Design doc for `src/model/workbook.rs`. This is the final data model once resolution processing for all phases has completed, and is exactly what the public API in `lib.rs` (`parse_workbook(path) -> Result<Workbook>`) returns. It aggregates [`Sheet`](sheet.en.md) from model/sheet.md.

## Responsibility / Scope

- Holds multiple [`Sheet`](sheet.en.md) instances in source order (the order defined in `<sheets>` within `xl/workbook.xml`)
- Provides lookup by sheet name
- **Not responsible for**: parsing the `workbook.xml` XML (`parse/workbook.rs`), or resolving the routing between sheet IDs and their backing file paths (`parse/relationships.rs` — the routing map is discarded once Phase 1 completes, so it does not remain in this model)

## Key Types (draft)

```rust
use crate::model::sheet::Sheet;

/// The final resolved output model. The return value of `lib.rs::parse_workbook`.
#[derive(Debug, Clone)]
pub struct Workbook {
    sheets: Vec<Sheet>,
}

impl Workbook {
    /// Builds a `Workbook` from a list of already-resolved sheets.
    /// `pipeline.rs` calls this exactly once, after Phases 3 and 4 have
    /// completed for every sheet (see pipeline.md; added after discovering
    /// the gap while designing it).
    pub(crate) fn new(sheets: Vec<Sheet>) -> Self {
        Self { sheets }
    }

    /// The list of sheets, preserving the definition order from the source file.
    pub fn sheets(&self) -> &[Sheet] {
        &self.sheets
    }

    /// Looks up a sheet by name. Since the requirements spec does not prohibit linear search,
    /// and the number of sheets in practice is small (a few to a few dozen), a linear search
    /// over a Vec is assumed to be sufficient.
    pub fn sheet(&self, name: &str) -> Option<&Sheet> {
        self.sheets.iter().find(|s| s.name == name)
    }
}
```

## Dependencies

- Depends on: [`model/sheet.rs`](sheet.en.md)
- Depended on by: [`pipeline.rs`](../pipeline.en.md) (constructs via `Workbook::new` and returns it), `lib.rs` (the return type of the public API), [`json.rs`](../json.en.md) (the top-level serialization target)

## Error Handling Policy

- `Workbook` itself does not generate errors (it is a terminal model that only holds already-constructed, valid data). Errors during construction (missing required elements in `workbook.xml`, dangling references to sheet backing files, etc.) are the responsibility of `pipeline.rs` / `parse/workbook.rs`, propagated to the caller as `Result::Err` from `parse_workbook` via the common type in `error.rs`.
- `sheet(name)` returns `Option::None` when the sheet does not exist (not a `Result` — a name-lookup miss is a logic error on the caller's side, not an internal library anomaly).

## Testing Strategy

- Looking up `sheet(name)` on a `Workbook` with multiple sheets (both existing and non-existing names)
- Verifying that `sheets()` preserves the source definition order
- Verifying the behavior of `sheets()` / `sheet()` on a `Workbook` with zero sheets (an empty book, or all sheets hidden, etc.)

## Open Questions

1. ~~Handling of hidden sheets~~ → **Resolved**: `Workbook.sheets` includes all sheets regardless of visibility. Excluding hidden sheets could break formula resolution referencing them from other sheets, and would leave the parser incomplete for data-extraction use cases. Visibility is carried as [`Sheet::visibility`](sheet.en.md) (a `SheetVisibility` enum), with filtering left to the caller (or `json.rs`) as an opt-in choice (finalized following the [PR #5 review](https://github.com/MinamiyamaKotaro/xlsxparser/pull/5#pullrequestreview-4948235239)).
2. **Complexity of sheet lookup**: For books with an extremely large number of sheets (hundreds, say), a linear search may not scale and a change to something like `IndexMap` could be considered. For now, since the requirements spec's main focus is "grid-paper Excel" (many rows/columns within a single sheet) rather than a large sheet count, Vec + linear search is used as a tentative design.
3. **Book-level metadata**: Information such as author or creation date (the `docProps` family) is out of scope for the requirements spec, but if added in the future, whether to add fields directly to `Workbook` or split them into a separate `Metadata` type is undecided (currently out of scope and not included in the type).