mirror of
https://github.com/PHPOffice/PhpSpreadsheet.git
synced 2026-09-18 22:16:46 +00:00
Merge pull request #3189 from fdjohnston/currencies_stored_as_strings
Handle Currencies Stored as Strings in Formulas
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
namespace PhpOffice\PhpSpreadsheet\Calculation\Engine;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
|
||||
|
||||
class FormattedNumber
|
||||
{
|
||||
@@ -17,6 +18,7 @@ class FormattedNumber
|
||||
[self::class, 'convertToNumberIfNumeric'],
|
||||
[self::class, 'convertToNumberIfFraction'],
|
||||
[self::class, 'convertToNumberIfPercent'],
|
||||
[self::class, 'convertToNumberIfCurrency'],
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -92,4 +94,30 @@ class FormattedNumber
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Identify whether a string contains a currency value, and if so,
|
||||
* convert it to a numeric.
|
||||
*
|
||||
* @param string $operand string value to test
|
||||
*/
|
||||
public static function convertToNumberIfCurrency(string &$operand): bool
|
||||
{
|
||||
$quotedCurrencyCode = preg_quote(StringHelper::getCurrencyCode());
|
||||
|
||||
$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)) {
|
||||
//Determine the sign
|
||||
$sign = ($match['PrefixedSign'] ?? $match['PrefixedSign2'] ?? $match['PostfixedSign']) ?? '';
|
||||
//Cast to a float
|
||||
$operand = (float) ($sign . ($match['PostfixedValue'] ?? $match['PrefixedValue']));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace PhpOffice\PhpSpreadsheetTests\Calculation;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||
use PhpOffice\PhpSpreadsheet\Cell\DataType;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
@@ -216,6 +217,20 @@ class CalculationTest extends TestCase
|
||||
self::assertSame(2.0, $cell2->getCalculatedValue());
|
||||
}
|
||||
|
||||
public function testCellWithStringCurrency(): void
|
||||
{
|
||||
$currencyCode = StringHelper::getCurrencyCode();
|
||||
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$workSheet = $spreadsheet->getActiveSheet();
|
||||
$cell1 = $workSheet->getCell('A1');
|
||||
$cell1->setValue($currencyCode . '2');
|
||||
$cell2 = $workSheet->getCell('B1');
|
||||
$cell2->setValue('=100*A1');
|
||||
|
||||
self::assertSame(200.0, $cell2->getCalculatedValue());
|
||||
}
|
||||
|
||||
public function testBranchPruningFormulaParsingSimpleCase(): void
|
||||
{
|
||||
$calculation = Calculation::getInstance();
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Engine;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Engine\FormattedNumber;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class FormattedNumberTest extends TestCase
|
||||
@@ -183,4 +184,51 @@ class FormattedNumberTest extends TestCase
|
||||
'permutation_88' => [' - % 2.50e - 06 ', ' - % 2.50e - 06 '],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerCurrencies
|
||||
*/
|
||||
public function testCurrencies(string $expected, string $value): void
|
||||
{
|
||||
$originalValue = $value;
|
||||
$result = FormattedNumber::convertToNumberIfCurrency($value);
|
||||
if ($result === false) {
|
||||
self::assertSame($expected, $originalValue);
|
||||
self::assertSame($expected, $value);
|
||||
} else {
|
||||
self::assertSame($expected, (string) $value);
|
||||
self::assertNotEquals($value, $originalValue);
|
||||
}
|
||||
}
|
||||
|
||||
public function providerCurrencies(): array
|
||||
{
|
||||
$currencyCode = StringHelper::getCurrencyCode();
|
||||
|
||||
return [
|
||||
'basic_prefix_currency' => ['2.75', "{$currencyCode}2.75"],
|
||||
'basic_postfix_currency' => ['2.75', "2.75{$currencyCode}"],
|
||||
|
||||
'basic_prefix_currency_with_spaces' => ['2.75', "{$currencyCode} 2.75"],
|
||||
'basic_postfix_currency_with_spaces' => ['2.75', "2.75 {$currencyCode}"],
|
||||
|
||||
'negative_basic_prefix_currency' => ['-2.75', "-{$currencyCode}2.75"],
|
||||
'negative_basic_postfix_currency' => ['-2.75', "-2.75{$currencyCode}"],
|
||||
|
||||
'negative_basic_prefix_currency_with_spaces' => ['-2.75', "-{$currencyCode} 2.75"],
|
||||
'negative_basic_postfix_currency_with_spaces' => ['-2.75', "-2.75 {$currencyCode}"],
|
||||
|
||||
'positive_signed_prefix_currency_with_spaces' => ['2.75', "+{$currencyCode} 2.75"],
|
||||
'positive_signed_prefix_currency_with_spaces-2' => ['2.75', "{$currencyCode} +2.75"],
|
||||
'positive_signed_postfix_currency_with_spaces' => ['2.75', "+2.75 {$currencyCode}"],
|
||||
|
||||
'basic_prefix_scientific_currency' => ['2000000', "{$currencyCode}2E6"],
|
||||
'basic_postfix_scientific_currency' => ['2000000', "2E6{$currencyCode}"],
|
||||
|
||||
'basic_prefix_scientific_currency_with_spaces' => ['2000000', "{$currencyCode} 2E6"],
|
||||
'basic_postfix_scientific_currency_with_spaces' => ['2000000', "2E6 {$currencyCode}"],
|
||||
|
||||
'high_value_currency_with_thousands_separator' => ['2750000', "+{$currencyCode} 2,750,000"],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user