Skip to content

Commit d029042

Browse files
authored
Merge pull request #3373 from PHPOffice/CalcEngine_Formatted-Currency-Expand-Currency-Range
Allow a range of different potential currency codes in the currency matcher regexp
2 parents 9e1378d + 3dd4862 commit d029042

File tree

2 files changed

+17
-4
lines changed

2 files changed

+17
-4
lines changed

src/PhpSpreadsheet/Calculation/Engine/FormattedNumber.php

+12-4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ class FormattedNumber
1313

1414
private const STRING_REGEXP_PERCENT = '~^(?:(?: *(?<PrefixedSign>[-+])? *\% *(?<PrefixedSign2>[-+])? *(?<PrefixedValue>[0-9]+\.?[0-9*]*(?:E[-+]?[0-9]*)?) *)|(?: *(?<PostfixedSign>[-+])? *(?<PostfixedValue>[0-9]+\.?[0-9]*(?:E[-+]?[0-9]*)?) *\% *))$~i';
1515

16+
// preg_quoted string for major currency symbols, with a %s for locale currency
17+
private const CURRENCY_CONVERSION_LIST = '\$€£¥%s';
18+
1619
private const STRING_CONVERSION_LIST = [
1720
[self::class, 'convertToNumberIfNumeric'],
1821
[self::class, 'convertToNumberIfFraction'],
@@ -106,13 +109,11 @@ public static function convertToNumberIfPercent(string &$operand): bool
106109
*/
107110
public static function convertToNumberIfCurrency(string &$operand): bool
108111
{
109-
$quotedCurrencyCode = preg_quote(StringHelper::getCurrencyCode());
110-
112+
$currencyRegexp = self::currencyMatcherRegexp();
111113
$value = preg_replace('/(\d),(\d)/u', '$1$2', $operand);
112-
$regExp = '~^(?:(?: *(?<PrefixedSign>[-+])? *' . $quotedCurrencyCode . ' *(?<PrefixedSign2>[-+])? *(?<PrefixedValue>[0-9]+\.?[0-9*]*(?:E[-+]?[0-9]*)?) *)|(?: *(?<PostfixedSign>[-+])? *(?<PostfixedValue>[0-9]+\.?[0-9]*(?:E[-+]?[0-9]*)?) *' . $quotedCurrencyCode . ' *))$~ui';
113114

114115
$match = [];
115-
if ($value !== null && preg_match($regExp, $value, $match, PREG_UNMATCHED_AS_NULL)) {
116+
if ($value !== null && preg_match($currencyRegexp, $value, $match, PREG_UNMATCHED_AS_NULL)) {
116117
//Determine the sign
117118
$sign = ($match['PrefixedSign'] ?? $match['PrefixedSign2'] ?? $match['PostfixedSign']) ?? '';
118119
//Cast to a float
@@ -123,4 +124,11 @@ public static function convertToNumberIfCurrency(string &$operand): bool
123124

124125
return false;
125126
}
127+
128+
public static function currencyMatcherRegexp(): string
129+
{
130+
$quotedCurrencyCode = sprintf(self::CURRENCY_CONVERSION_LIST, preg_quote(StringHelper::getCurrencyCode()));
131+
132+
return '~^(?:(?: *(?<PrefixedSign>[-+])? *(?<PrefixedCurrency>[' . $quotedCurrencyCode . ']) *(?<PrefixedSign2>[-+])? *(?<PrefixedValue>[0-9]+\.?[0-9*]*(?:E[-+]?[0-9]*)?) *)|(?: *(?<PostfixedSign>[-+])? *(?<PostfixedValue>[0-9]+\.?[0-9]*(?:E[-+]?[0-9]*)?) *(?<PostCurrency>[' . $quotedCurrencyCode . ']) *))$~ui';
133+
}
126134
}

tests/PhpSpreadsheetTests/Calculation/Engine/FormattedNumberTest.php

+5
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,11 @@ public function providerCurrencies(): array
233233
'basic_postfix_scientific_currency_with_spaces' => ['2000000', "2E6 {$currencyCode}"],
234234

235235
'high_value_currency_with_thousands_separator' => ['2750000', "+{$currencyCode} 2,750,000"],
236+
237+
'explicit dollar' => ['2.75', '$2.75'],
238+
'explicit euro' => ['2.75', '2.75€'],
239+
'explicit pound sterling' => ['2.75', '£2.75'],
240+
'explicit yen' => ['275', '¥275'],
236241
];
237242
}
238243
}

0 commit comments

Comments
 (0)