Skip to content

Commit de01e59

Browse files
authored
Merge pull request #3384 from PHPOffice/NumberFormat-Wizards_Currency-Accounting-zero-decimals
Explicit 0 for a decimals value when using Currency and Accounting NumberFormat Wizards with a locale
2 parents 33eefe7 + 207d029 commit de01e59

File tree

4 files changed

+76
-4
lines changed

4 files changed

+76
-4
lines changed

src/PhpSpreadsheet/Style/NumberFormat/Wizard/Accounting.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class Accounting extends Currency
1818
* @param ?string $locale Set the locale for the currency format; or leave as the default null.
1919
* If provided, Locale values must be a valid formatted locale string (e.g. 'en-GB', 'fr', uz-Arab-AF).
2020
* Note that setting a locale will override any other settings defined in this class
21-
* other than the currency code.
21+
* other than the currency code; or decimals (unless the decimals value is set to 0).
2222
*
2323
* @throws Exception If a provided locale code is not a valid format
2424
*/
@@ -53,8 +53,12 @@ protected function getLocaleFormat(): string
5353

5454
// Scrutinizer does not recognize CURRENCY_ACCOUNTING
5555
$formatter = new Locale($this->fullLocale, NumberFormatter::CURRENCY_ACCOUNTING);
56+
$mask = $formatter->format();
57+
if ($this->decimals === 0) {
58+
$mask = (string) preg_replace('/\.0*/', '', $mask);
59+
}
5660

57-
return str_replace('¤', $this->formatCurrencyCode(), $formatter->format());
61+
return str_replace('¤', $this->formatCurrencyCode(), $mask);
5862
}
5963

6064
private function icuVersion(): float

src/PhpSpreadsheet/Style/NumberFormat/Wizard/Currency.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class Currency extends Number
3232
* @param ?string $locale Set the locale for the currency format; or leave as the default null.
3333
* If provided, Locale values must be a valid formatted locale string (e.g. 'en-GB', 'fr', uz-Arab-AF).
3434
* Note that setting a locale will override any other settings defined in this class
35-
* other than the currency code.
35+
* other than the currency code; or decimals (unless the decimals value is set to 0).
3636
*
3737
* @throws Exception If a provided locale code is not a valid format
3838
*/
@@ -70,8 +70,12 @@ public function setCurrencySymbolSpacing(bool $currencySymbolSpacing = self::SYM
7070
protected function getLocaleFormat(): string
7171
{
7272
$formatter = new Locale($this->fullLocale, NumberFormatter::CURRENCY);
73+
$mask = $formatter->format();
74+
if ($this->decimals === 0) {
75+
$mask = (string) preg_replace('/\.0*/', '', $mask);
76+
}
7377

74-
return str_replace('¤', $this->formatCurrencyCode(), $formatter->format());
78+
return str_replace('¤', $this->formatCurrencyCode(), $mask);
7579
}
7680

7781
private function formatCurrencyCode(): string

tests/PhpSpreadsheetTests/Style/NumberFormat/Wizard/AccountingTest.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,38 @@ public function providerAccountingLocale(): array
7070
];
7171
}
7272

73+
/**
74+
* @dataProvider providerAccountingLocaleNoDecimals
75+
*/
76+
public function testAccountingLocaleNoDecimals(
77+
string $expectedResult,
78+
string $currencyCode,
79+
string $locale
80+
): void {
81+
if (class_exists(NumberFormatter::class) === false) {
82+
self::markTestSkipped('Intl extension is not available');
83+
}
84+
85+
$wizard = new Accounting($currencyCode, 0);
86+
$wizard->setLocale($locale);
87+
self::assertSame($expectedResult, (string) $wizard);
88+
}
89+
90+
public function providerAccountingLocaleNoDecimals(): array
91+
{
92+
return [
93+
["[\$€-fy-NL]\u{a0}#,##0;([\$€-fy-NL]\u{a0}#,##0)", '', 'fy-NL'],
94+
["[\$€-nl-NL]\u{a0}#,##0;([\$€-nl-NL]\u{a0}#,##0)", '', 'nl-NL'],
95+
["[\$€-nl-BE]\u{a0}#,##0;([\$€-nl-BE]\u{a0}#,##0)", '', 'NL-BE'],
96+
["#,##0\u{a0}[\$€-fr-BE];(#,##0\u{a0}[\$€-fr-BE])", '', 'fr-be'],
97+
["#,##0\u{a0}[\$€-el-GR]", '', 'el-gr'],
98+
['[$$-en-CA]#,##0;([$$-en-CA]#,##0)', '$', 'en-ca'],
99+
["#,##0\u{a0}[\$\$-fr-CA];(#,##0\u{a0}[\$\$-fr-CA])", '$', 'fr-ca'],
100+
['[$¥-ja-JP]#,##0;([$¥-ja-JP]#,##0)', '¥', 'ja-JP'], // No decimals to truncate
101+
["#,##0\u{a0}[\$د.ب‎-ar-BH]", 'د.ب‎', 'ar-BH'], // 3 decimals truncated to none
102+
];
103+
}
104+
73105
public function testAccountingLocaleInvalidFormat(): void
74106
{
75107
if (class_exists(NumberFormatter::class) === false) {

tests/PhpSpreadsheetTests/Style/NumberFormat/Wizard/CurrencyTest.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,38 @@ public function providerCurrencyLocale(): array
6969
];
7070
}
7171

72+
/**
73+
* @dataProvider providerCurrencyLocaleNoDecimals
74+
*/
75+
public function testCurrencyLocaleNoDecimals(
76+
string $expectedResult,
77+
string $currencyCode,
78+
string $locale
79+
): void {
80+
if (class_exists(NumberFormatter::class) === false) {
81+
self::markTestSkipped('Intl extension is not available');
82+
}
83+
84+
$wizard = new Currency($currencyCode, 0);
85+
$wizard->setLocale($locale);
86+
self::assertSame($expectedResult, (string) $wizard);
87+
}
88+
89+
public function providerCurrencyLocaleNoDecimals(): array
90+
{
91+
return [
92+
["[\$€-fy-NL]\u{a0}#,##0;[\$€-fy-NL]\u{a0}#,##0-", '', 'fy-NL'], // Trailing negative
93+
["[\$€-nl-NL]\u{a0}#,##0;[\$€-nl-NL]\u{a0}-#,##0", '', 'nl-NL'], // Sign between currency and value
94+
["[\$€-nl-BE]\u{a0}#,##0;[\$€-nl-BE]\u{a0}-#,##0", '', 'NL-BE'], // Sign between currency and value
95+
["#,##0\u{a0}[\$€-fr-BE]", '', 'fr-be'], // Trailing currency code
96+
["#,##0\u{a0}[\$€-el-GR]", '', 'el-gr'], // Trailing currency code
97+
['[$$-en-CA]#,##0', '$', 'en-ca'],
98+
["#,##0\u{a0}[\$\$-fr-CA]", '$', 'fr-ca'], // Trailing currency code
99+
['[$¥-ja-JP]#,##0', '¥', 'ja-JP'], // No decimals to truncate
100+
["#,##0\u{a0}[\$د.ب‎-ar-BH]", 'د.ب‎', 'ar-BH'], // 3 decimals truncated to none
101+
];
102+
}
103+
72104
public function testCurrencyLocaleInvalidFormat(): void
73105
{
74106
if (class_exists(NumberFormatter::class) === false) {

0 commit comments

Comments
 (0)