From 61c0f25a88f717fbd5b1f61b0862adb71a7d5683 Mon Sep 17 00:00:00 2001 From: Everton Barbosa Date: Mon, 25 Nov 2024 14:00:25 -0300 Subject: [PATCH] Escale any dollar signs when formatting cell data When a cell is formatted as text and contains a number prefixed with dollar sign, this number is getting replaced with 0. The replacement happens due to the preg_replace function. This commit escapes any sollar signs on the cell data, so those are not replaced. --- .../Style/NumberFormat/Formatter.php | 5 ++++- .../Worksheet/ToArrayTest.php | 16 ++++++++++++++++ tests/data/Reader/XLSX/issue.4242.xlsx | Bin 0 -> 9720 bytes 3 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 tests/data/Reader/XLSX/issue.4242.xlsx diff --git a/src/PhpSpreadsheet/Style/NumberFormat/Formatter.php b/src/PhpSpreadsheet/Style/NumberFormat/Formatter.php index 8ae33354ae..f11d84ec59 100644 --- a/src/PhpSpreadsheet/Style/NumberFormat/Formatter.php +++ b/src/PhpSpreadsheet/Style/NumberFormat/Formatter.php @@ -126,7 +126,10 @@ public static function toFormattedString($value, string $format, ?array $callBac // For now we do not treat strings in sections, although section 4 of a format code affects strings // Process a single block format code containing @ for text substitution if (preg_match(self::SECTION_SPLIT, $format) === 0 && preg_match(self::SYMBOL_AT, $format) === 1) { - return str_replace('"', '', preg_replace(self::SYMBOL_AT, (string) $value, $format) ?? ''); + //escape any dollar signs on the string, so they are not replaced with an empty value + $value = str_replace('$', '\\$', (string) $value); + + return str_replace('"', '', preg_replace(self::SYMBOL_AT, $value, $format) ?? ''); } // If we have a text value, return it "as is" diff --git a/tests/PhpSpreadsheetTests/Worksheet/ToArrayTest.php b/tests/PhpSpreadsheetTests/Worksheet/ToArrayTest.php index 75002bbf95..38b7e52ea6 100644 --- a/tests/PhpSpreadsheetTests/Worksheet/ToArrayTest.php +++ b/tests/PhpSpreadsheetTests/Worksheet/ToArrayTest.php @@ -4,6 +4,7 @@ namespace PhpOffice\PhpSpreadsheetTests\Worksheet; +use PhpOffice\PhpSpreadsheet\Reader\Xlsx; use PhpOffice\PhpSpreadsheet\Spreadsheet; use PHPUnit\Framework\TestCase; @@ -76,4 +77,19 @@ public static function testMaxCol(): void self::assertSame('start', $array[0][0]); self::assertSame('end', $array[0][16383]); } + + public static function testDollarSign(): void + { + $filename = 'tests/data/Reader/XLSX/issue.4242.xlsx'; + $reader = new Xlsx(); + $spreadsheet = $reader->load($filename); + $sheet = $spreadsheet->getActiveSheet(); + + $expected = [ + ['General', '$0', 'Value is $100', '200 number - $200 value', null], + ['Text', '$0', 'Value is $100', '200 number - $200 value', null], + ]; + $result = $sheet->toArray(); + self::assertSame($expected, $result); + } } diff --git a/tests/data/Reader/XLSX/issue.4242.xlsx b/tests/data/Reader/XLSX/issue.4242.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..e07592d7cb8a7d2a458f94afe1bccc81b5ada09d GIT binary patch literal 9720 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 oA4$M{@xPzYe-%fh{EPUX=e6n+B$y2X0GO~JJ