Skip to content

Write Integers With a Fraction Format As Excel Does - #5060

Open
ybai08 wants to merge 2 commits into
PHPOffice:masterfrom
ybai08:fraction-format-integers
Open

ybai08 wants to merge 2 commits into
PHPOffice:masterfrom
ybai08:fraction-format-integers

Conversation

@ybai08

@ybai08 ybai08 commented Oct 18, 2026

Copy link
Copy Markdown

This is:

  • a bugfix
  • a new feature
  • refactoring
  • additional unit tests

Checklist:

  • Changes are covered by unit tests
    • Changes are covered by existing unit tests
    • New unit tests have been added
  • Code style is respected
  • Commit message explains why the change is made (see https://github.com/erlang/otp/wiki/Writing-good-commit-messages)
  • CHANGELOG.md contains a short summary of the change and a link to the pull request if applicable
  • Documentation is updated as necessary

Why is this change needed?

Fix #3625. With a fraction format, an integer was written as the integer alone. Excel writes a fraction in two cases, both noted in the issue:

Value Format Excel PhpSpreadsheet before
1 0/0 1/1 1
1 ??/??? 1/1 (padded) 1
1 0 0/0 1 0/1 1
1 ? ??/??? 1 (padded) 1

So a format with no integer part always shows a fraction (N/1, or N*d/d with a fixed denominator d), and a format with an integer part shows N 0/1 when the last numerator placeholder is 0. With a ? or # numerator placeholder the fraction is left out, as before.

NumberFormatter replaced the # and 0 placeholders with ? before FractionFormatter saw the format, which lost the 0. That replacement now happens inside FractionFormatter (its only caller), after it notes whether the numerator ends in 0.

The 1/1, 1 0/1 and 1 results come from the issue thread. The other new cases (12/1, -3/1, 0/1 for 0 with 0/0, 500/100 for 5 with ??/100, 5 0/4 for 5 with 0 0/4) follow the same rule but have not been checked in Excel; Excel's padding with spaces is still not reproduced, as in the existing tests.

The suite was run:

  • vendor/bin/phpunit tests/PhpSpreadsheetTests/Style/NumberFormatTest.php --filter testFormatValueWithMaskFraction: 8 of the 10 new cases fail without the change; all 37 pass with it.
  • Full phpunit: 22445 tests, the same 1 error and 8 failures as on master (Html reader/writer, CODE of ℅, and the it_CH locale test, which depend on the local libxml/ICU/iconv).
  • composer style (phpcs and php-cs-fixer), the PHPCompatibility check and bin/check-phpdoc-types.php: clean.
  • phpstan: the same 5 $argv might not be defined reports in samples/Chart as on master, nothing new.
  • Not run: composer versions on PHP versions other than 8.5, and Windows.

Fix PHPOffice#3625. With a fraction format, PhpSpreadsheet wrote an integer as
the integer alone, so 1 formatted with `0/0` was `1`. Excel writes
`1/1`: a format with no integer part always shows a fraction. Excel
also shows the fraction when the last numerator placeholder is 0, so 1
formatted with `0 0/0` is `1 0/1`; with a `?` or `#` numerator
placeholder the fraction is left out, as before.

The `#` and `0` placeholders were replaced by `?` before
FractionFormatter saw the format, so the replacement moves into
FractionFormatter, which first notes whether the numerator ends in 0.
@ybai08
ybai08 force-pushed the fraction-format-integers branch from 3ecbc50 to 086ee2c Compare October 18, 2026 01:21

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

getFormattedValue(): invalid format value in some cases

2 participants