Skip to content

Commit

Permalink
Merge pull request #3373 from PHPOffice/CalcEngine_Formatted-Currency…
Browse files Browse the repository at this point in the history
…-Expand-Currency-Range

Allow a range of different potential currency codes in the currency matcher regexp
  • Loading branch information
MarkBaker authored Feb 17, 2023
2 parents 9e1378d + 3dd4862 commit d029042
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 4 deletions.
16 changes: 12 additions & 4 deletions src/PhpSpreadsheet/Calculation/Engine/FormattedNumber.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ class FormattedNumber

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';

// preg_quoted string for major currency symbols, with a %s for locale currency
private const CURRENCY_CONVERSION_LIST = '\$€£¥%s';

private const STRING_CONVERSION_LIST = [
[self::class, 'convertToNumberIfNumeric'],
[self::class, 'convertToNumberIfFraction'],
Expand Down Expand Up @@ -106,13 +109,11 @@ public static function convertToNumberIfPercent(string &$operand): bool
*/
public static function convertToNumberIfCurrency(string &$operand): bool
{
$quotedCurrencyCode = preg_quote(StringHelper::getCurrencyCode());

$currencyRegexp = self::currencyMatcherRegexp();
$value = preg_replace('/(\d),(\d)/u', '$1$2', $operand);
$regExp = '~^(?:(?: *(?<PrefixedSign>[-+])? *' . $quotedCurrencyCode . ' *(?<PrefixedSign2>[-+])? *(?<PrefixedValue>[0-9]+\.?[0-9*]*(?:E[-+]?[0-9]*)?) *)|(?: *(?<PostfixedSign>[-+])? *(?<PostfixedValue>[0-9]+\.?[0-9]*(?:E[-+]?[0-9]*)?) *' . $quotedCurrencyCode . ' *))$~ui';

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

return false;
}

public static function currencyMatcherRegexp(): string
{
$quotedCurrencyCode = sprintf(self::CURRENCY_CONVERSION_LIST, preg_quote(StringHelper::getCurrencyCode()));

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';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,11 @@ public function providerCurrencies(): array
'basic_postfix_scientific_currency_with_spaces' => ['2000000', "2E6 {$currencyCode}"],

'high_value_currency_with_thousands_separator' => ['2750000', "+{$currencyCode} 2,750,000"],

'explicit dollar' => ['2.75', '$2.75'],
'explicit euro' => ['2.75', '2.75€'],
'explicit pound sterling' => ['2.75', '£2.75'],
'explicit yen' => ['275', '¥275'],
];
}
}

0 comments on commit d029042

Please sign in to comment.