Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tests Involving Decimal and Currency Separators #3815

Merged
merged 7 commits into from
Dec 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions src/PhpSpreadsheet/Shared/StringHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class StringHelper
/**
* Currency code.
*
* @var string
* @var ?string
*/
private static $currencyCode;

Expand Down Expand Up @@ -551,9 +551,9 @@ public static function getDecimalSeparator(): string
* Set the decimal separator. Only used by NumberFormat::toFormattedString()
* to format output by \PhpOffice\PhpSpreadsheet\Writer\Html and \PhpOffice\PhpSpreadsheet\Writer\Pdf.
*
* @param string $separator Character for decimal separator
* @param ?string $separator Character for decimal separator
*/
public static function setDecimalSeparator(string $separator): void
public static function setDecimalSeparator(?string $separator): void
{
self::$decimalSeparator = $separator;
}
Expand Down Expand Up @@ -582,9 +582,9 @@ public static function getThousandsSeparator(): string
* Set the thousands separator. Only used by NumberFormat::toFormattedString()
* to format output by \PhpOffice\PhpSpreadsheet\Writer\Html and \PhpOffice\PhpSpreadsheet\Writer\Pdf.
*
* @param string $separator Character for thousands separator
* @param ?string $separator Character for thousands separator
*/
public static function setThousandsSeparator(string $separator): void
public static function setThousandsSeparator(?string $separator): void
{
self::$thousandsSeparator = $separator;
}
Expand Down Expand Up @@ -618,9 +618,9 @@ public static function getCurrencyCode(): string
* Set the currency code. Only used by NumberFormat::toFormattedString()
* to format output by \PhpOffice\PhpSpreadsheet\Writer\Html and \PhpOffice\PhpSpreadsheet\Writer\Pdf.
*
* @param string $currencyCode Character for currency code
* @param ?string $currencyCode Character for currency code
*/
public static function setCurrencyCode(string $currencyCode): void
public static function setCurrencyCode(?string $currencyCode): void
{
self::$currencyCode = $currencyCode;
}
Expand Down
13 changes: 13 additions & 0 deletions src/PhpSpreadsheet/Style/NumberFormat/BaseFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,24 @@

namespace PhpOffice\PhpSpreadsheet\Style\NumberFormat;

use PhpOffice\PhpSpreadsheet\Shared\StringHelper;

abstract class BaseFormatter
{
protected static function stripQuotes(string $format): string
{
// Some non-number strings are quoted, so we'll get rid of the quotes, likewise any positional * symbols
return str_replace(['"', '*'], '', $format);
}

protected static function adjustSeparators(string $value): string
{
$thousandsSeparator = StringHelper::getThousandsSeparator();
$decimalSeparator = StringHelper::getDecimalSeparator();
if ($thousandsSeparator !== ',' || $decimalSeparator !== '.') {
$value = str_replace(['.', ',', "\u{fffd}"], ["\u{fffd}", '.', ','], $value);
}

return $value;
}
}
4 changes: 2 additions & 2 deletions src/PhpSpreadsheet/Style/NumberFormat/Formatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
use PhpOffice\PhpSpreadsheet\Style\Color;
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;

class Formatter
class Formatter extends BaseFormatter
{
/**
* Matches any @ symbol that isn't enclosed in quotes.
Expand Down Expand Up @@ -133,7 +133,7 @@ public static function toFormattedString($value, $format, $callBack = null)
// For 'General' format code, we just pass the value although this is not entirely the way Excel does it,
// it seems to round numbers to a total of 10 digits.
if (($format === NumberFormat::FORMAT_GENERAL) || ($format === NumberFormat::FORMAT_TEXT)) {
return (string) $value;
return self::adjustSeparators((string) $value);
}

// Ignore square-$-brackets prefix in format string, like "[$-411]ge.m.d", "[$-010419]0%", etc
Expand Down
6 changes: 3 additions & 3 deletions src/PhpSpreadsheet/Style/NumberFormat/NumberFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;

class NumberFormatter
class NumberFormatter extends BaseFormatter
{
private const NUMBER_REGEX = '/(0+)(\\.?)(0*)/';

Expand Down Expand Up @@ -176,11 +176,11 @@ private static function formatStraightNumericValue(mixed $value, string $format,
return $result;
}

$sprintf_pattern = "%0$minWidth." . strlen($right) . 'f';
$sprintf_pattern = "%0$minWidth." . strlen($right) . 'F';

/** @var float */
$valueFloat = $value;
$value = sprintf($sprintf_pattern, round($valueFloat, strlen($right)));
$value = self::adjustSeparators(sprintf($sprintf_pattern, round($valueFloat, strlen($right))));

return self::pregReplace(self::NUMBER_REGEX, $value, $format);
}
Expand Down
4 changes: 2 additions & 2 deletions src/PhpSpreadsheet/Style/NumberFormat/PercentageFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@ public static function format($value, string $format): string

$wholePartSize += $decimalPartSize + (int) ($decimalPartSize > 0);
$replacement = "0{$wholePartSize}.{$decimalPartSize}";
$mask = (string) preg_replace('/[#0,]+\.?[?#0,]*/ui', "%{$replacement}f{$placeHolders}", $format);
$mask = (string) preg_replace('/[#0,]+\.?[?#0,]*/ui', "%{$replacement}F{$placeHolders}", $format);

/** @var float */
$valueFloat = $value;

return sprintf($mask, round($valueFloat, $decimalPartSize));
return self::adjustSeparators(sprintf($mask, round($valueFloat, $decimalPartSize)));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,11 @@

class FormattedNumberSlashTest extends TestCase
{
private string $originalCurrencyCode;

private string $originalDecimalSeparator;

private string $originalThousandsSeparator;

protected function setUp(): void
{
$this->originalCurrencyCode = StringHelper::getCurrencyCode();
$this->originalDecimalSeparator = StringHelper::getDecimalSeparator();
$this->originalThousandsSeparator = StringHelper::getThousandsSeparator();
}

protected function tearDown(): void
{
StringHelper::setCurrencyCode($this->originalCurrencyCode);
StringHelper::setDecimalSeparator($this->originalDecimalSeparator);
StringHelper::setThousandsSeparator($this->originalThousandsSeparator);
StringHelper::setCurrencyCode(null);
StringHelper::setDecimalSeparator(null);
StringHelper::setThousandsSeparator(null);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,12 @@

class ValueTest extends AllSetupTeardown
{
private string $currencyCode;

private string $decimalSeparator;

private string $thousandsSeparator;

protected function setUp(): void
{
parent::setUp();
$this->currencyCode = StringHelper::getCurrencyCode();
$this->decimalSeparator = StringHelper::getDecimalSeparator();
$this->thousandsSeparator = StringHelper::getThousandsSeparator();
}

protected function tearDown(): void
{
parent::tearDown();
StringHelper::setCurrencyCode($this->currencyCode);
StringHelper::setDecimalSeparator($this->decimalSeparator);
StringHelper::setThousandsSeparator($this->thousandsSeparator);
StringHelper::setCurrencyCode(null);
StringHelper::setDecimalSeparator(null);
StringHelper::setThousandsSeparator(null);
}

/**
Expand Down
15 changes: 3 additions & 12 deletions tests/PhpSpreadsheetTests/Cell/AdvancedValueBinderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,30 +18,21 @@ class AdvancedValueBinderTest extends TestCase

private string $originalLocale;

private string $originalCurrencyCode;

private string $originalDecimalSeparator;

private string $originalThousandsSeparator;

private IValueBinder $valueBinder;

protected function setUp(): void
{
$this->originalLocale = Settings::getLocale();
$this->originalCurrencyCode = StringHelper::getCurrencyCode();
$this->originalDecimalSeparator = StringHelper::getDecimalSeparator();
$this->originalThousandsSeparator = StringHelper::getThousandsSeparator();

$this->valueBinder = Cell::getValueBinder();
Cell::setValueBinder(new AdvancedValueBinder());
}

protected function tearDown(): void
{
StringHelper::setCurrencyCode($this->originalCurrencyCode);
StringHelper::setDecimalSeparator($this->originalDecimalSeparator);
StringHelper::setThousandsSeparator($this->originalThousandsSeparator);
StringHelper::setCurrencyCode(null);
StringHelper::setDecimalSeparator(null);
StringHelper::setThousandsSeparator(null);
Settings::setLocale($this->originalLocale);
Cell::setValueBinder($this->valueBinder);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ protected function setUp(): void
{
$this->currentLocale = setlocale(LC_ALL, '0');

if (!setlocale(LC_ALL, 'de_DE.UTF-8', 'deu_deu')) {
if (!setlocale(LC_ALL, 'de_DE.UTF-8', 'deu_deu.utf8')) {
$this->localeAdjusted = false;

return;
Expand All @@ -52,12 +52,17 @@ protected function tearDown(): void

/**
* @dataProvider providerNumberFormatNoConversionTest
*
* @runInSeparateProcess
*/
public function testNumberFormatNoConversion(mixed $expectedValue, string $expectedFormat, string $cellAddress): void
{
if (!$this->localeAdjusted) {
self::markTestSkipped('Unable to set locale for testing.');
}
$localeconv = localeconv();
self::assertSame(',', $localeconv['decimal_point'], 'unexpected change to German decimal separator');
self::assertSame('.', $localeconv['thousands_sep'], 'unexpected change to German thousands separator');

$spreadsheet = $this->csvReader->load($this->filename);
$worksheet = $spreadsheet->getActiveSheet();
Expand Down Expand Up @@ -99,6 +104,9 @@ public function testNumberValueConversion(mixed $expectedValue, string $cellAddr
if (!$this->localeAdjusted) {
self::markTestSkipped('Unable to set locale for testing.');
}
$localeconv = localeconv();
self::assertSame(',', $localeconv['decimal_point'], 'unexpected change to German decimal separator');
self::assertSame('.', $localeconv['thousands_sep'], 'unexpected change to German thousands separator');

$this->csvReader->castFormattedNumberToNumeric(true);
$spreadsheet = $this->csvReader->load($this->filename);
Expand Down
20 changes: 3 additions & 17 deletions tests/PhpSpreadsheetTests/Shared/StringHelperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,11 @@

class StringHelperTest extends TestCase
{
private string $currencyCode;

private string $decimalSeparator;

private string $thousandsSeparator;

protected function setUp(): void
{
parent::setUp();
$this->currencyCode = StringHelper::getCurrencyCode();
$this->decimalSeparator = StringHelper::getDecimalSeparator();
$this->thousandsSeparator = StringHelper::getThousandsSeparator();
}

protected function tearDown(): void
{
StringHelper::setCurrencyCode($this->currencyCode);
StringHelper::setDecimalSeparator($this->decimalSeparator);
StringHelper::setThousandsSeparator($this->thousandsSeparator);
StringHelper::setCurrencyCode(null);
StringHelper::setDecimalSeparator(null);
StringHelper::setThousandsSeparator(null);
}

public function testGetIsIconvEnabled(): void
Expand Down
15 changes: 3 additions & 12 deletions tests/PhpSpreadsheetTests/Style/NumberFormatTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,17 @@

class NumberFormatTest extends TestCase
{
private string $currencyCode;

private string $decimalSeparator;

private string $thousandsSeparator;

protected function setUp(): void
{
$this->currencyCode = StringHelper::getCurrencyCode();
$this->decimalSeparator = StringHelper::getDecimalSeparator();
$this->thousandsSeparator = StringHelper::getThousandsSeparator();
StringHelper::setDecimalSeparator('.');
StringHelper::setThousandsSeparator(',');
}

protected function tearDown(): void
{
StringHelper::setCurrencyCode($this->currencyCode);
StringHelper::setDecimalSeparator($this->decimalSeparator);
StringHelper::setThousandsSeparator($this->thousandsSeparator);
StringHelper::setCurrencyCode(null);
StringHelper::setDecimalSeparator(null);
StringHelper::setThousandsSeparator(null);
}

/**
Expand Down
15 changes: 3 additions & 12 deletions tests/PhpSpreadsheetTests/Writer/Html/HtmlNumberFormatTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,18 @@

class HtmlNumberFormatTest extends Functional\AbstractFunctional
{
private string $currency;

private string $decsep;

private string $thosep;

protected function setUp(): void
{
$this->currency = StringHelper::getCurrencyCode();
StringHelper::setCurrencyCode('$');
$this->decsep = StringHelper::getDecimalSeparator();
StringHelper::setDecimalSeparator('.');
$this->thosep = StringHelper::getThousandsSeparator();
StringHelper::setThousandsSeparator(',');
}

protected function tearDown(): void
{
StringHelper::setCurrencyCode($this->currency);
StringHelper::setDecimalSeparator($this->decsep);
StringHelper::setThousandsSeparator($this->thosep);
StringHelper::setCurrencyCode(null);
StringHelper::setDecimalSeparator(null);
StringHelper::setThousandsSeparator(null);
}

public function testColorNumberFormat(): void
Expand Down
Loading