Fix #2966: convert formula result to Date when numFmt is date-like#55
Open
senoff wants to merge 1 commit intoprotobi:masterfrom
Open
Fix #2966: convert formula result to Date when numFmt is date-like#55senoff wants to merge 1 commit intoprotobi:masterfrom
senoff wants to merge 1 commit intoprotobi:masterfrom
Conversation
…like When a cell's formula result is cached as t="str" with a numeric Excel date serial in <v> (some non-Excel writers do this), the reader left the result as a string instead of converting it to a JS Date the way it does for plain numeric formula results. After PR exceljs#2956's guard, this no longer produced an Invalid Date, but the value was still wrong for downstream consumers that expect a Date. The standard (non-streaming) reconcile path and the streaming reader both now coerce string-typed formula results that look like a finite number before passing through excelToDate. Genuine non-numeric display strings (e.g., "27/08/2025 19:33:34") fall through unchanged so we never fabricate an Invalid Date. Adds spec/integration/issues/issue-2966-formula-result-date-numfmt covering: numeric serial with no t, numeric serial with t="str", a non-numeric display string, and the streaming reader. Two unrelated multi-line function calls in the touched files were collapsed to single-line form to satisfy the prettier+eslint hook (prettier wants a trailing comma, eslint forbids it on functions). Behavior is unchanged. Refs: exceljs#2966 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
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.
Bug
Tracked at exceljs#2966.
When a cell holds a formula whose cached result is a numeric Excel date
serial and the cell's
numFmtis a date format (e.g.m/d/yyyy), thereader is supposed to materialize
cell.value.resultas a JSDate.It does in the common case (
<v>46143</v>with notattribute), butnot when an off-spec writer marks the formula cell with
t=\"str\"and still puts a numeric serial inside
<v>. After PR exceljs#2956's guardin
excelToDate, the reader stopped throwingInvalid Datefor thatshape, but the value was left as the raw string "46143.20833333333"
The streaming
WorkbookReaderhad the same gap and never applieddate conversion to formula results at all.
Fix
lib/xlsx/xform/sheet/cell-xform.js(reconcile, Formula branch) andlib/stream/xlsx/worksheet-reader.js(formula cell handling) both now:numFmtis date-like (utils.isDateFmt).resultis a string but parses as a finite number that round-tripsexactly, coerce to that number first.
utils.excelToDate, which already handles plain numbersand (post-Fix the return value from dateToExcel() when it's passed a non-numeric value. exceljs/exceljs#2956) returns non-numeric input unchanged.
Genuine display strings like
\"27/08/2025 19:33:34\"cannot bereliably parsed as an Excel serial, so they fall through unchanged - we
never fabricate an Invalid Date.
Tests
spec/integration/issues/issue-2966-formula-result-date-numfmt.spec.jscovers four shapes:
<v>, notattribute (regression baseline)<v>witht=\"str\"(the actual bug)t=\"str\"(must not become Invalid Date)t=\"str\"becomes aDateFixtures are built programmatically: a workbook is written with the
real
m/d/yyyystyle, then the<c>element is rewritten in-place viaJSZip so the malformed shapes can be exercised without checking binary
fixtures into the repo.
npm run test:unit,npm run test:integration, andnpm run test:end-to-endall pass.Notes
Two unrelated multi-line function calls in the touched files were
collapsed to single-line form to satisfy the prettier+eslint hook
(prettier wants
trailingComma: \"all\", eslint enforcescomma-dangle.functions: \"never\"). Behavior is unchanged.