From e1fb68efc176e38e7a36a90a9b6f37d5f15e92b7 Mon Sep 17 00:00:00 2001 From: oleibman <10341515+oleibman@users.noreply.github.com> Date: Wed, 14 Feb 2024 21:20:45 -0800 Subject: [PATCH] Handling of User-supplied Decimal and Thousands Separators Fix #3900. The code to adjust Decimal and Thousands separators to user-specified choices expects to convert periods to commas and vice versa - hard-coded without taking the user specification into account. This is likely to be the only significant use case, however, as the issue demonstrates, it is not the only possibility. In particular, it will mess up Csv output if decimal separator is kept as period, but thousands separator is set to null string. The code is altered to replace period with the user-selected decimal separator, and comma with the user-selected thousands separator. No existing tests broke as a result of this change in behavior. --- .../Style/NumberFormat/BaseFormatter.php | 2 +- .../Shared/StringHelperTest.php | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/PhpSpreadsheet/Style/NumberFormat/BaseFormatter.php b/src/PhpSpreadsheet/Style/NumberFormat/BaseFormatter.php index d6f373d07..165779ba1 100644 --- a/src/PhpSpreadsheet/Style/NumberFormat/BaseFormatter.php +++ b/src/PhpSpreadsheet/Style/NumberFormat/BaseFormatter.php @@ -17,7 +17,7 @@ abstract class BaseFormatter $thousandsSeparator = StringHelper::getThousandsSeparator(); $decimalSeparator = StringHelper::getDecimalSeparator(); if ($thousandsSeparator !== ',' || $decimalSeparator !== '.') { - $value = str_replace(['.', ',', "\u{fffd}"], ["\u{fffd}", '.', ','], $value); + $value = str_replace(['.', ',', "\u{fffd}"], ["\u{fffd}", $thousandsSeparator, $decimalSeparator], $value); } return $value; diff --git a/tests/PhpSpreadsheetTests/Shared/StringHelperTest.php b/tests/PhpSpreadsheetTests/Shared/StringHelperTest.php index 03a4403d1..8cddd5fed 100644 --- a/tests/PhpSpreadsheetTests/Shared/StringHelperTest.php +++ b/tests/PhpSpreadsheetTests/Shared/StringHelperTest.php @@ -5,6 +5,8 @@ declare(strict_types=1); namespace PhpOffice\PhpSpreadsheetTests\Shared; use PhpOffice\PhpSpreadsheet\Shared\StringHelper; +use PhpOffice\PhpSpreadsheet\Spreadsheet; +use PhpOffice\PhpSpreadsheet\Writer\Csv; use PHPUnit\Framework\TestCase; class StringHelperTest extends TestCase @@ -98,4 +100,24 @@ class StringHelperTest extends TestCase self::assertEquals($expectedResult, $result); } + + public function testIssue3900(): void + { + StringHelper::setDecimalSeparator('.'); + StringHelper::setThousandsSeparator(''); + + $spreadsheet = new Spreadsheet(); + $sheet = $spreadsheet->getActiveSheet(); + $sheet->setCellValue('A1', 1.4); + $sheet->setCellValue('B1', 1004.5); + $sheet->setCellValue('C1', 1000000.5); + + ob_start(); + $ioWriter = new Csv($spreadsheet); + $ioWriter->setDelimiter(';'); + $ioWriter->save('php://output'); + $output = ob_get_clean(); + $spreadsheet->disconnectWorksheets(); + self::assertSame('"1.4";"1004.5";"1000000.5"' . PHP_EOL, $output); + } }