Skip to content

fix(sheet): skip hidden and very-hidden worksheets - #39

Open
nitishagar wants to merge 1 commit into
firecrawl:mainfrom
nitishagar:fix/issue-9-hidden-sheets
Open

fix(sheet): skip hidden and very-hidden worksheets#39
nitishagar wants to merge 1 commit into
firecrawl:mainfrom
nitishagar:fix/issue-9-hidden-sheets

Conversation

@nitishagar

@nitishagar nitishagar commented Aug 6, 2026

Copy link
Copy Markdown

Closes #9 (sheet-level half).

Summary

anydoc rendered entire hidden / veryHidden worksheets as visible content — indistinguishable from visible sheets in both to_markdown() and to_document(). This adds a pure filter at the sheet frontend: sheets whose state is hidden or veryHidden contribute no heading and no table.

calamine 0.36.1 exposes each sheet's visibility via sheets_metadata() (SheetVisible::{Visible,Hidden,VeryHidden}), which shares one backing Vec<Sheet> with sheet_names() — so the Nth metadata entry describes the Nth name. Positional zip (never name lookup) is used so re-ordering cannot reintroduce the bug.

The change is one file, src/formats/sheet/mod.rs:

  • the skip runs before worksheet_range(), so a hidden sheet never counts as "unreadable";
  • the multi-sheet heading decision now counts visible sheets, so a single visible sheet among hidden ones keeps (or avoids) its heading correctly;
  • an all-hidden workbook degrades to an empty Document (Ok), not a misleading "no sheet could be read" error (hidden is a valid state, not unreadable).

Scope

This addresses the sheet-level half of #9. The row/column visibility half genuinely needs reading xl/worksheets/sheetN.xml <row hidden> / <col hidden> attributes that calamine's xlsx reader does not expose — it depends on the in-house parser and is explicitly out of scope.

ODS hidden-sheet filtering is also out of scope here: .ods routes through odf::parse (a different frontend reading content.xml directly), not sheet::parse, so calamine's SheetVisible is irrelevant to that path. Tracked as a follow-up in src/formats/odf/table.rs.

Verification

  • cargo fmt --all --check
  • cargo clippy --workspace --all-targets --all-features -- -D warnings
  • cargo test --locked ✅ (185 lib + 10 snapshot; existing snapshots byte-for-byte unchanged)
  • New tests: hidden_worksheets_do_not_render (visible+hidden+veryHidden fixture → only visible renders), all_hidden_workbook_yields_empty_document (all-hidden → empty Document, not Err/panic), veryHidden covered by the same fixture.
  • Branch rebased on current main.

Manual note (from the plan)

On the issue's openpyxl repro (visible row + hidden row + hidden column + hidden sheet), the hidden sheet disappears while the hidden row/column still render — confirming this does not accidentally touch the out-of-scope row/column half.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

calamine 0.36.1 exposes each sheet's visibility via sheets_metadata()
(SheetVisible::{Visible,Hidden,VeryHidden}), index-aligned with
sheet_names() through one backing Vec<Sheet>. The sheet frontend iterated
sheet_names() alone and rendered every sheet as visible content, so a
hidden or veryHidden worksheet was indistinguishable from a visible one
in both to_markdown() and to_document() (firecrawl#9, sheet-level
half).

Filter non-Visible sheets out before any heading or table is emitted:
- the multi-sheet heading decision now counts visible sheets, so a single
  visible sheet among hidden ones keeps (or avoids) its heading correctly;
- the skip runs before worksheet_range(), so a hidden sheet never counts
  as "unreadable" and an all-hidden workbook degrades to an empty Document
  rather than a misleading "no sheet could be read" error.

Row/column visibility (firecrawl#9's other half) needs the in-house parser and is
out of scope; ODS hidden tables route through odf::parse, a separate
frontend, and are tracked as a follow-up.

Adds a handmade-hidden.xlsx fixture (visible + hidden + veryHidden sheet)
and its visible-only snapshot; existing snapshots are byte-for-byte
unchanged.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

XLSX conversion silently treats hidden rows and columns as visible

1 participant