Heuristic header row range detection for Excel-like two-dimensional data.
Project description
guess-sheet-headers
guess-sheet-headers is a small heuristic Python package for guessing the header row range of Excel-like two-dimensional data. It is designed for practical automation, not perfect spreadsheet understanding.
The input is a two-dimensional list-like object. The output is a (start, end) tuple using zero-based, left-closed/right-open row indexes. (0, 0) means no reliable header was detected.
from datetime import date
from guess_sheet_headers import do_guess
rows = [
["姓名", "金额", "日期"],
["张三", 10, date(2026, 1, 1)],
["李四", 20, date(2026, 1, 2)],
]
assert do_guess(rows) == (0, 1)
Install
For local development:
python -m pip install -e .
The package has no runtime dependencies.
Algorithm
The default heuristic is intentionally simple and works in two stages: first find a suspected data region, then decide how many rows above it should be kept as the header range.
- Sample at most 200 rows.
- If total rows are at most 200, use all rows.
- Otherwise sample the first 100 rows, 50 middle rows, and 50 tail rows, then remove duplicate indexes.
- Before sampling, trim all-empty columns at the left and right edges and all-empty rows at the bottom. Top empty rows, middle empty rows, and middle empty columns are kept.
- Convert cells to integer types.
- For each column, count all types including
EMPTY. - Keep at most three types whose per-column ratio is greater than 30%; if none exceed 30%, the column profile is an empty set.
- All column type sets form the data-region profile.
- Scan top rows. The first row whose score is greater than 0.9 is treated as the suspected first data row.
- In the suspected header area before that row, find the row with the highest text density, where text density is
(PHRASE + SENTENCE) / column_countand empty cells stay in the denominator. - Return
(0, best_header_row + 1)so merged-cell titles and notes above the field row remain part of the header range. If the first row already matches data, return one default header row.
The match score is:
sum(column_weight) / column_count
Column weights:
type is in column profile: 1.0
otherwise: 0.0
empty profile set: skipped, not included in denominator
Cell Types
Cell types are plain integers:
EMPTY = 0
NUMBER = 1
DATETIME = 2
NUMERIC_STR = 3
PHRASE = 4
SENTENCE = 5
Notes:
DATETIME is used only when the parser has already returned a Python datetime, date, or time object.
NUMERIC_STR is used for strings that contain digits plus numeric separators or symbols, such as +25.3 or 2026/3/7.
PHRASE is short text. SENTENCE is longer natural-language text. For ASCII text, the rule splits by whitespace and punctuation except - and _; more than one segment is a sentence. For non-ASCII text, more than 8 non-space characters is a sentence.
Configuration
Use GuessOptions to tune thresholds and sample sizes:
from guess_sheet_headers import GuessOptions, do_guess
options = GuessOptions(
match_threshold=0.9,
col_type_threshold=0.3,
min_sample_rows=10,
)
result = do_guess(rows, options)
Limitations
This is a guessing algorithm for common structured tables, not a strict Excel understanding engine. It intentionally favors simple, predictable behavior over exhaustive edge-case handling.
Known weak cases include very small sheets, sparse data rows, heavily mixed column types, multiple unrelated tables in one sheet, long title/description blocks before the table, and sheets where group headers have many empty cells that match a sparse data profile.
Development
Run tests from this directory:
python -m unittest discover -s tests
License
MIT License. See LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file guess_sheet_headers-0.1.0.tar.gz.
File metadata
- Download URL: guess_sheet_headers-0.1.0.tar.gz
- Upload date:
- Size: 11.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9fedbeaca28a6feea450635dcbb1e01068dea3bb38134af600b432ed258e7489
|
|
| MD5 |
1938baff6af8a84d16979d85442c48ba
|
|
| BLAKE2b-256 |
4435813d29fc779271bb9cfe134c97c683ca12f966c3b6e1b1ecaf9751df6ed5
|
File details
Details for the file guess_sheet_headers-0.1.0-py3-none-any.whl.
File metadata
- Download URL: guess_sheet_headers-0.1.0-py3-none-any.whl
- Upload date:
- Size: 6.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9ab80a0375b5eaec7037d740979462f66c503b4d6711b9d65259abaa325fef11
|
|
| MD5 |
6c9a2cfb4d1c96e4479182c52de8cb9d
|
|
| BLAKE2b-256 |
ef6505081a4826b494635f2ad3b707dd1180ac0a4072057ebd7ab9b46d432cd9
|