{"record":{"id":"9c1968aad0f3859b","repo":"pola-rs/polars","slug":"empty-excel-sheet-if-you-want-to-read-this-as-an","errorCode":null,"errorMessage":"empty Excel sheet\n\nIf you want to read this as an empty DataFrame, set `raise_if_empty=False`.","messagePattern":"empty Excel sheet\n\nIf you want to read this as an empty DataFrame, set `raise_if_empty=False`\\.","errorType":"exception","errorClass":"NoDataError","httpStatus":null,"severity":"error","filePath":"py-polars/src/polars/io/spreadsheet/functions.py","lineNumber":1010,"sourceCode":"                ):\n                    null_cols.append(col_name)\n        if null_cols:\n            df = df.drop(*null_cols)\n\n    if df.height == df.width == 0:\n        return _empty_frame(raise_if_empty)\n    if drop_empty_rows:\n        return df.filter(~F.all_horizontal(F.all().is_null()))\n    return df\n\n\ndef _empty_frame(raise_if_empty: bool) -> pl.DataFrame:  # noqa: FBT001\n    if raise_if_empty:\n        msg = (\n            \"empty Excel sheet\"\n            \"\\n\\nIf you want to read this as an empty DataFrame, set `raise_if_empty=False`.\"\n        )\n        raise NoDataError(msg)\n    return pl.DataFrame()\n\n\ndef _reorder_columns(\n    df: pl.DataFrame, columns: Sequence[int] | Sequence[str] | None\n) -> pl.DataFrame:\n    if columns:\n        from polars.selectors import by_index, by_name\n\n        cols = (\n            by_index(*columns)\n            if is_non_empty_sequence_of(columns, int)\n            else by_name(*columns)\n        )\n        df = df.select(cols)\n    return df\n\n","sourceCodeStart":992,"sourceCodeEnd":1028,"githubUrl":"https://github.com/pola-rs/polars/blob/df599052daf96e7a9cc30a3b0c6bd25d6947e3c0/py-polars/src/polars/io/spreadsheet/functions.py#L992-L1028","documentation":"Raised as polars.exceptions.NoDataError by _empty_frame whenever the selected sheet turns out to contain no data and raise_if_empty is True (the default). It is reached from all three engines: a zero-byte CSV buffer in the xlsx2csv path, an empty used-range in openpyxl, or an all-null frame in calamine after _drop_null_data. The message itself tells you the escape hatch: pass raise_if_empty=False to get an empty DataFrame instead.","triggerScenarios":"pl.read_excel(src, sheet_name='Notes') on a blank-but-present sheet; reading with sheet_id=0 where some tabs are empty (first empty tab aborts everything); header-only sheets that drop_empty_rows filters to zero rows; formatted-but-dataless sheets.","commonSituations":"Heterogeneous workbooks where documentation/template tabs are empty; scheduled jobs over user-supplied files where a blank tab is normal; sheets whose only content is styling or a pivot cache.","solutions":["Pass raise_if_empty=False and branch on the result: df = pl.read_excel(..., raise_if_empty=False); if df.is_empty(): ...","When iterating all sheets (sheet_id=0), wrap per-sheet reads or skip known-empty tabs","Verify you selected the intended sheet — an empty result often means the wrong tab was addressed"],"exampleFix":"# before\ndf = pl.read_excel(src, sheet_name='Notes')  # blank sheet -> NoDataError\n\n# after\ndf = pl.read_excel(src, sheet_name='Notes', raise_if_empty=False)\nif df.is_empty():\n    df = pl.DataFrame()  # or skip / log this sheet","handlingStrategy":"try-catch","validationCode":"# cheapest pre-check without a full parse: use raise_if_empty=False and inspect\nframe = pl.read_excel(src, sheet_name='Notes', raise_if_empty=False)\nif frame.is_empty():\n    handle_empty('Notes')  # skip / default frame / log","typeGuard":null,"tryCatchPattern":"from polars.exceptions import NoDataError\n\ntry:\n    df = pl.read_excel(src, sheet_name=name)\nexcept NoDataError:\n    df = pl.DataFrame()  # empty sheet is an expected domain state\n\n# or, when looping all sheets:\nframes = {}\nfor name in sheet_names(src):\n    try:\n        frames[name] = pl.read_excel(src, sheet_name=name)\n    except NoDataError:\n        continue","preventionTips":["When blank tabs are possible (templates, notes sheets), pass raise_if_empty=False and branch on df.is_empty()","For sheet_id=0 bulk reads, expect NoDataError per sheet instead of one monolithic call","Import NoDataError from polars.exceptions — it is a PolarsError, not a ValueError"],"tags":["polars","excel","empty-data","no-data-error","raise-if-empty"],"backgroundTag":null,"analyzedSha":"df599052daf96e7a9cc30a3b0c6bd25d6947e3c0","analyzedAt":"2026-08-16T12:10:03.978Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}