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 d6f373d079..165779ba18 100644 --- a/src/PhpSpreadsheet/Style/NumberFormat/BaseFormatter.php +++ b/src/PhpSpreadsheet/Style/NumberFormat/BaseFormatter.php @@ -17,7 +17,7 @@ protected static function adjustSeparators(string $value): string $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 03a4403d1a..8cddd5fede 100644 --- a/tests/PhpSpreadsheetTests/Shared/StringHelperTest.php +++ b/tests/PhpSpreadsheetTests/Shared/StringHelperTest.php @@ -5,6 +5,8 @@ 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 @@ public function testSYLKtoUTF8(): void 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); + } }