Skip to main content

Structural detection of table-like data regions, headers, and merged cells in Excel worksheets.

Project description

xldetect

CI

Structural detection of table-like data regions, headers, and merged cells in Excel worksheets. xldetect is the discovery step: it finds where the tables are so a processing step (like xlfilldown) can act on them.

Users say "grab the table", but a worksheet has no concept of one — just scattered cells, merged banners, decorative titles, summary rows, and sometimes several tables on one sheet. openpyxl tells you cell values; it does not tell you where the data starts. xldetect answers that question from structure alone.

  • Detect multiple rectangular data regions per sheet, across sheets
  • Detect header row(s) from content cues (text-over-data) and formatting (bold/fill/border)
  • Report and forward-fill merged cells
  • Skip decorative title/banner rows
  • Confidence score per region
  • Emit regions in a shape xlfilldown can consume

Install

pip install xldetect

Requires Python 3.11+. Runtime dependency: openpyxl.

Quickstart (CLI)

xldetect inspect messy.xlsx
File: messy.xlsx
Sheets: 1   Regions: 2

Sheet 'Data': 2 region(s), used range 8 rows x 3 cols, 1 merged range(s)
  Region 1: A2:C4  (confidence 0.933)
    header row 2: Name, Region, Sales
    data rows 3-4 (2 rows x 3 cols)
    decorative rows skipped: 1
  Region 2: A7:B8  (confidence 0.870)
    header row 7: Product, Qty
    data rows 8-8 (1 row x 2 cols)

Other output modes:

xldetect inspect messy.xlsx --json          # full report as JSON
xldetect inspect messy.xlsx --xlfilldown    # one xlfilldown plan per region
xldetect inspect messy.xlsx --sheet Data --min-blank-rows 2 --header-threshold 0.6

Quickstart (Python)

from xldetect import inspect_path

report = inspect_path("messy.xlsx")
for region in report.iter_regions():
    print(region.range_a1, region.headers, region.confidence)
    # A2:C4 ['Name', 'Region', 'Sales'] 0.933

Every result is a typed dataclass with a JSON-safe to_dict(). A Region carries: sheet, min_row/max_row/min_col/max_col, range_a1, has_header, header_rows/header_row, headers, data_start_row, n_data_rows, n_cols, confidence, merged_ranges, decorative_rows, and notes.

Pairing with xlfilldown

xldetect finds the region; xlfilldown fills it down and ingests it.

from xldetect import inspect_path, to_xlfilldown_plan
import xlfilldown

report = inspect_path("messy.xlsx")
region = next(report.iter_regions())
plan = to_xlfilldown_plan(region, "messy.xlsx",
                          sheet_max_col=report.sheets[0].max_col)

if not plan["caveats"]:
    xlfilldown.ingest_excel_to_sqlite(
        file=plan["file"], sheet=plan["sheet"],
        header_row=plan["header_row"], fill_cols=plan["fill_cols"],
        db="out.db", table="data", if_exists="replace",
    )

xlfilldown reads one header_row to the end of the sheet across all headered columns. When a region does not span the full sheet (multiple regions, column offsets), the plan's caveats list says so — read it before ingesting. See LIMITATIONS.md.

Deliberate design tradeoffs

xldetect makes opinionated structural guesses. The behaviours most likely to look like bugs (single-blank-row splitting, all-text header detection, summary rows kept as data, formula caching) are documented with rationale and overrides in LIMITATIONS.md.

Using with AI assistants

SKILL.md is an LLM-consumable guide (decision tree, worked examples, anti-patterns) so coding agents call xldetect correctly instead of hand-rolling region detection.

Development

pip install -e .[dev]
pytest            # runs straight from a clean clone (pythonpath = src)

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

xldetect-1.0.1.tar.gz (37.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

xldetect-1.0.1-py3-none-any.whl (27.9 kB view details)

Uploaded Python 3

File details

Details for the file xldetect-1.0.1.tar.gz.

File metadata

  • Download URL: xldetect-1.0.1.tar.gz
  • Upload date:
  • Size: 37.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for xldetect-1.0.1.tar.gz
Algorithm Hash digest
SHA256 c02065073e8c4f1f5343990dbcb1b3f35c7c7e4f17081c901b72cd198e8333f4
MD5 0b0396d3a12cabd7fe4fb65bf654edca
BLAKE2b-256 b63f0db39635a79a5c3fa2b14aeb5f42741d4c1d374e98e040e59ca251a93b4d

See more details on using hashes here.

File details

Details for the file xldetect-1.0.1-py3-none-any.whl.

File metadata

  • Download URL: xldetect-1.0.1-py3-none-any.whl
  • Upload date:
  • Size: 27.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for xldetect-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 223da69cfbece732a77936e25da525a53eb838ff6626091cda119c7b7ee96180
MD5 559182c4f4f0beab60599f4535c49a2c
BLAKE2b-256 d98c3dcab2d060da7a541f9cae6fafd9e4fed1cfe6c619f045d856a8e09d9d47

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page