Conversation
xlrd hands back what Excel stores rather than what the cell says, so the
spreadsheet skill described the same sheet two different ways:
.xls .xlsx
date 45292.0 2024-01-01 00:00:00
bool 1 True
int 12.0 12
The date is the one that cannot be recovered afterwards: the sample the model
reads says 45292.0 and nothing marks it as a date.
Convert the date, the boolean and the whole number the way openpyxl already
delivers them, and report an error cell as the text Excel shows. A float that
is not whole and every string are untouched.
Contributor
There was a problem hiding this comment.
Hey - I've found 1 issue
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="astrbot/builtin_stars/astrbot/skills/spreadsheets/scripts/inspect_workbook.py" line_range="75" />
<code_context>
+ )
+ except (ValueError, xlrd.XLDateError):
+ return cell.value
+ return datetime(year, month, day, hour, minute, second)
+ if cell.ctype == xlrd.XL_CELL_BOOLEAN:
+ return bool(cell.value)
</code_context>
<issue_to_address>
**issue (bug_risk):** `datetime(year, month, day, hour, minute, second)` raises `ValueError` for valid Excel date-formatted cells representing a time-only value or serial zero, because `xldate_as_tuple` returns zero month/day components for those values. The inspector then exits with an error instead of returning the sample.
**Triggers:** When an XLS contains a date-formatted time-only cell, such as `0.5` for noon, or a date-formatted zero value.
**Suggested fix:** Handle zero month/day tuples as `datetime.time` or preserve the raw value, matching openpyxl's handling of time-only cells, and include the constructor in the conversion error handling.
</issue_to_address>Sourcery assessment
Approval pending. 1 finding to address first.
Blocking findings: astrbot/builtin_stars/astrbot/skills/spreadsheets/scripts/inspect_workbook.py:75
`xldate_as_tuple` reports a cell that carries only a time as `(0, 0, 0, hour, minute, second)`, so `datetime(...)` raised `ValueError: year 0 is out of range` and the inspector exited with an error instead of printing the sample. openpyxl reads the same cell in an .xlsx as a `datetime.time`, so return one here too.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this fixes
_inspect_xlsreads the sample withsheet.row_values(...), which hands back xlrd's raw storage rather than the cell's value._inspect_xlsxgoes through openpyxl and hands back the value. So the same sheet is described two different ways depending on which format it is saved in.Measured on
master(e0aa8d3), the same four cells written to both formats and run throughinspect_workbook.py:The date is the one that matters:
45292.0is Excel's serial number, and nothing in the JSON marks it as a date, so a model reading the inspection has no way to recover it.1for a boolean and12.0for a whole number are the same drift in smaller form.The change
_xls_cell_valueconverts each cell by its xlrd type, to match what_inspect_xlsxalready produces:XL_CELL_DATE→datetime, viaxldate_as_tuplewith the workbook'sdatemode(the 1900/1904 epoch matters and only the book knows which it is);XL_CELL_BOOLEAN→bool;XL_CELL_NUMBERthat is whole →int, since xlrd stores every number as a double;XL_CELL_ERROR→ the text Excel shows (#DIV/0!), which is what openpyxl reports.A float that is not whole, a string and an empty cell are untouched.
row_valuesbecomesrow_slice, because the conversion needs the cell type androw_valuesthrows it away; the column limit is unchanged.validate_workbook.pyonly counts sheets for.xlsand needs nothing.Tests
One case in
tests/test_builtin_office_skills.py, in the house style — it runs both scripts as subprocesses over a real.xls(written withxlwt) and the equivalent.xlsx:The second assertion is the property the first is really about: the two formats have to describe the same sheet the same way.
xlwtjoins thedevdependency group — it is the only way to write a legacy.xlsfixture — and the test alsoimportorskips it so the suite still runs without it.Measured:
ruff checkandruff formatclean with the pinned 0.15.22.Summary by Sourcery
Align legacy .xls inspection with .xlsx value semantics so equivalent workbooks produce consistent samples.
Bug Fixes:
Build:
Tests: