Skip to content

Commit d4ffa3e

Browse files
authored
Merge pull request #4243 from sirbaconjr/fix-dollar-sign-issue-4242
Escape any dollar signs when formatting cell data
2 parents a70b335 + 690cb21 commit d4ffa3e

File tree

3 files changed

+64
-3
lines changed

3 files changed

+64
-3
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
2525

2626
### Fixed
2727

28-
- Nothing yet.
28+
- Ignore cell formatting when the format is a single @. [Issue #4242](https://github.com/PHPOffice/PhpSpreadsheet/issues/4242) [PR #4243](https://github.com/PHPOffice/PhpSpreadsheet/pull/4243)
2929

3030
## 2024-11-22 - 3.5.0
3131

src/PhpSpreadsheet/Style/NumberFormat/Formatter.php

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ class Formatter extends BaseFormatter
1414
* Matches any @ symbol that isn't enclosed in quotes.
1515
*/
1616
private const SYMBOL_AT = '/@(?=(?:[^"]*"[^"]*")*[^"]*\Z)/miu';
17+
private const QUOTE_REPLACEMENT = "\u{fffe}"; // invalid Unicode character
1718

1819
/**
1920
* Matches any ; symbol that isn't enclosed in quotes, for a "section" split.
@@ -125,8 +126,23 @@ public static function toFormattedString($value, string $format, ?array $callBac
125126
}
126127
// For now we do not treat strings in sections, although section 4 of a format code affects strings
127128
// Process a single block format code containing @ for text substitution
128-
if (preg_match(self::SECTION_SPLIT, $format) === 0 && preg_match(self::SYMBOL_AT, $format) === 1) {
129-
return str_replace('"', '', preg_replace(self::SYMBOL_AT, (string) $value, $format) ?? '');
129+
$formatx = str_replace('\\"', self::QUOTE_REPLACEMENT, $format);
130+
if (preg_match(self::SECTION_SPLIT, $format) === 0 && preg_match(self::SYMBOL_AT, $formatx) === 1) {
131+
if (!str_contains($format, '"')) {
132+
return str_replace('@', $value, $format);
133+
}
134+
//escape any dollar signs on the string, so they are not replaced with an empty value
135+
$value = str_replace(
136+
['$', '"'],
137+
['\\$', self::QUOTE_REPLACEMENT],
138+
(string) $value
139+
);
140+
141+
return str_replace(
142+
['"', self::QUOTE_REPLACEMENT],
143+
['', '"'],
144+
preg_replace(self::SYMBOL_AT, $value, $formatx) ?? $value
145+
);
130146
}
131147

132148
// If we have a text value, return it "as is"

tests/data/Style/NumberFormat.php

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1682,4 +1682,49 @@
16821682
'#,##0.00;;"---"',
16831683
],
16841684
'issue 4124' => ['1 HUF', 1, '#,##0_-[$HUF]'],
1685+
'issue 4242 General with dollar sign' => [
1686+
'General $200 - 200', // expected result
1687+
'General $200 - 200', // cell contents
1688+
NumberFormat::FORMAT_GENERAL, // cell style
1689+
],
1690+
'issue 4242 Text with dollar sign' => [
1691+
'Text $200 - 200',
1692+
'Text $200 - 200',
1693+
NumberFormat::FORMAT_TEXT,
1694+
],
1695+
'issue 4242 Text with quotes, format without' => [
1696+
'"Hello" she said and "Hello" I replied',
1697+
'"Hello" she said and "Hello" I replied',
1698+
NumberFormat::FORMAT_TEXT,
1699+
],
1700+
'issue 4242 Format with quotes, text without' => [
1701+
'Text: $200 - 200',
1702+
'$200 - 200',
1703+
'"Text: "' . NumberFormat::FORMAT_TEXT,
1704+
],
1705+
'issue 4242 single quote mark' => [
1706+
'"',
1707+
'"',
1708+
'@',
1709+
],
1710+
'issue 4242 dollar sign' => [
1711+
'$100',
1712+
'$100',
1713+
'@',
1714+
],
1715+
'issue 4242 repeat unquoted at signs' => [
1716+
'xy xy xy',
1717+
'xy',
1718+
'@ @ @',
1719+
],
1720+
'issue 4242 quotes in format and text' => [
1721+
'Text: "Hooray" for me',
1722+
'"Hooray" for me',
1723+
'"Text: "' . NumberFormat::FORMAT_TEXT,
1724+
],
1725+
'issue 4242 escaped quote in format' => [
1726+
'"Hello"',
1727+
'Hello',
1728+
'\\"@\\"',
1729+
],
16851730
];

0 commit comments

Comments
 (0)