fix(xlsx): keep whole numbers and booleans in a column with an empty cell
Summary
partition_xlsx() reads each worksheet with pd.read_excel() and its default dtype inference, then writes the frame with to_html(na_rep=""). Pandas gives a column that holds a missing value a float dtype. One empty cell therefore turns a column of whole numbers into floats, and a column of booleans into 1.0 / 0.0:
| cells | element text on 0.27.28 |
|---|---|
12, (empty), 7, 3 | 12.0, 7.0, 3.0 |
TRUE, FALSE, (empty) | 1.0, 0.0 |
A probe sheet ([12, "pen", True], [None, "ink", False], [7, "pad", None], [3, "007", 1.5]) comes out of main as 12.0 pen 1.0 ink 0.0 7.0 pad 3.0 007 1.5. With this PR it reads 12 pen True ink False 7 pad 3 007 1.5.
Change
Both read paths, the plain pd.read_excel() and the row-compacting reader used for subtable detection, now pass dtype=object (_CELLS_AS_WRITTEN). Each cell keeps the value openpyxl or xlrd gives for it. Empty cells are still missing, so subtable detection sees the same populated cells as before.
Related: #4505 reads cell text such as N/A, NULL or None as content (keep_default_na=False). I first had that here too, then left it out so the two PRs do not overlap. Each one only adds read options, so they combine without trouble.
Out of scope: a date cell still shows its time (2024-09-30 00:00:00).
Testing
- New
test_partition_xlsx_reads_each_cell_as_written, parametrized overfind_subtable, checks the text andtext_as_htmlof the probe sheet. Both cases fail onmain. - The other 142 tests in
test_xlsx.pypass unchanged, including the.xlsones. - ruff 0.15.10 check and format are clean, and
scripts/version-sync.sh -cpasses with0.27.34-dev7.