Skip to content

Commit

Permalink
More Apostrophe Fixes
Browse files Browse the repository at this point in the history
Fix PHPOffice#4362. A similar problem to 4360, Style not handling sheet name with embedded apostrophe properly. And, with two examples in hand, I was able to determine a pattern to find and fix other possible exposures.
  • Loading branch information
oleibman committed Feb 15, 2025
1 parent ac148c8 commit 7b60624
Show file tree
Hide file tree
Showing 18 changed files with 136 additions and 60 deletions.
14 changes: 8 additions & 6 deletions src/PhpSpreadsheet/Calculation/Calculation.php
Original file line number Diff line number Diff line change
Expand Up @@ -4408,7 +4408,9 @@ private function internalParseFormula(string $formula, ?Cell $cell = null): bool
if ($rangeWS1 !== '') {
$rangeWS1 .= '!';
}
$rangeSheetRef = trim($rangeSheetRef, "'");
if (str_starts_with($rangeSheetRef, "'")) {
$rangeSheetRef = Worksheet::unApostrophizeTitle($rangeSheetRef);
}
[$rangeWS2, $val] = Worksheet::extractSheetTitle($val, true);
if ($rangeWS2 !== '') {
$rangeWS2 .= '!';
Expand Down Expand Up @@ -4766,18 +4768,18 @@ private function processTokenStack(mixed $tokens, ?string $cellID = null, ?Cell
}
}
if (str_contains($operand1Data['reference'] ?? '', '!')) {
[$sheet1, $operand1Data['reference']] = Worksheet::extractSheetTitle($operand1Data['reference'], true);
[$sheet1, $operand1Data['reference']] = Worksheet::extractSheetTitle($operand1Data['reference'], true, true);
} else {
$sheet1 = ($pCellWorksheet !== null) ? $pCellWorksheet->getTitle() : '';
}
$sheet1 ??= '';

[$sheet2, $operand2Data['reference']] = Worksheet::extractSheetTitle($operand2Data['reference'], true);
[$sheet2, $operand2Data['reference']] = Worksheet::extractSheetTitle($operand2Data['reference'], true, true);
if (empty($sheet2)) {
$sheet2 = $sheet1;
}

if (trim($sheet1, "'") === trim($sheet2, "'")) {
if ($sheet1 === $sheet2) {
if ($operand1Data['reference'] === null && $cell !== null) {
if (is_array($operand1Data['value'])) {
$operand1Data['reference'] = $cell->getCoordinate();
Expand Down Expand Up @@ -5495,7 +5497,7 @@ public function extractCellRange(string &$range = 'A1', ?Worksheet $worksheet =
$worksheetName = $worksheet->getTitle();

if (str_contains($range, '!')) {
[$worksheetName, $range] = Worksheet::extractSheetTitle($range, true);
[$worksheetName, $range] = Worksheet::extractSheetTitle($range, true, true);
$worksheet = ($this->spreadsheet === null) ? null : $this->spreadsheet->getSheetByName($worksheetName);
}

Expand Down Expand Up @@ -5557,7 +5559,7 @@ public function extractNamedRange(string &$range = 'A1', ?Worksheet $worksheet =

if ($worksheet !== null) {
if (str_contains($range, '!')) {
[$worksheetName, $range] = Worksheet::extractSheetTitle($range, true);
[$worksheetName, $range] = Worksheet::extractSheetTitle($range, true, true);
$worksheet = ($this->spreadsheet === null) ? null : $this->spreadsheet->getSheetByName($worksheetName);
}

Expand Down
2 changes: 1 addition & 1 deletion src/PhpSpreadsheet/Calculation/Information/Value.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public static function isRef(mixed $value, ?Cell $cell = null): bool

$cellValue = Functions::trimTrailingRange($value);
if (preg_match('/^' . Calculation::CALCULATION_REGEXP_CELLREF . '$/ui', $cellValue) === 1) {
[$worksheet, $cellValue] = Worksheet::extractSheetTitle($cellValue, true);
[$worksheet, $cellValue] = Worksheet::extractSheetTitle($cellValue, true, true);
if (!empty($worksheet) && $cell->getWorksheet()->getParentOrThrow()->getSheetByName($worksheet) === null) {
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public static function single(string $cellReference, Cell $cell): mixed
{
$worksheet = $cell->getWorksheet();

[$referenceWorksheetName, $referenceCellCoordinate] = Worksheet::extractSheetTitle($cellReference, true);
[$referenceWorksheetName, $referenceCellCoordinate] = Worksheet::extractSheetTitle($cellReference, true, true);
if (preg_match('/^([$]?[a-z]{1,3})([$]?([0-9]{1,7})):([$]?[a-z]{1,3})([$]?([0-9]{1,7}))$/i', "$referenceCellCoordinate", $matches) === 1) {
$ourRow = $cell->getRow();
$firstRow = (int) $matches[3];
Expand Down Expand Up @@ -44,7 +44,7 @@ public static function anchorArray(string $cellReference, Cell $cell): array|str
//$coordinate = $cell->getCoordinate();
$worksheet = $cell->getWorksheet();

[$referenceWorksheetName, $referenceCellCoordinate] = Worksheet::extractSheetTitle($cellReference, true);
[$referenceWorksheetName, $referenceCellCoordinate] = Worksheet::extractSheetTitle($cellReference, true, true);
$referenceCell = ($referenceWorksheetName === '')
? $worksheet->getCell((string) $referenceCellCoordinate)
: $worksheet->getParentOrThrow()
Expand Down
3 changes: 1 addition & 2 deletions src/PhpSpreadsheet/Calculation/LookupRef/Helpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,7 @@ public static function extractWorksheet(string $cellAddress, Cell $cell): array
{
$sheetName = '';
if (str_contains($cellAddress, '!')) {
[$sheetName, $cellAddress] = Worksheet::extractSheetTitle($cellAddress, true);
$sheetName = trim($sheetName, "'");
[$sheetName, $cellAddress] = Worksheet::extractSheetTitle($cellAddress, true, true);
}

$worksheet = ($sheetName !== '')
Expand Down
3 changes: 1 addition & 2 deletions src/PhpSpreadsheet/Calculation/LookupRef/Offset.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,7 @@ private static function extractWorksheet(?string $cellAddress, Cell $cell): arra

$sheetName = '';
if (str_contains($cellAddress, '!')) {
[$sheetName, $cellAddress] = Worksheet::extractSheetTitle($cellAddress, true);
$sheetName = trim($sheetName, "'");
[$sheetName, $cellAddress] = Worksheet::extractSheetTitle($cellAddress, true, true);
}

$worksheet = ($sheetName !== '')
Expand Down
2 changes: 1 addition & 1 deletion src/PhpSpreadsheet/Chart/DataSeriesValues.php
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,7 @@ public function refresh(Worksheet $worksheet, bool $flatten = true): void
}
unset($dataValue);
} else {
[$worksheet, $cellRange] = Worksheet::extractSheetTitle($this->dataSource, true);
[, $cellRange] = Worksheet::extractSheetTitle($this->dataSource, true);
$dimensions = Coordinate::rangeDimension(str_replace('$', '', $cellRange ?? ''));
if (($dimensions[0] == 1) || ($dimensions[1] == 1)) {
$this->dataValues = Functions::flattenArray($newDataValues);
Expand Down
3 changes: 1 addition & 2 deletions src/PhpSpreadsheet/Reader/Gnumeric.php
Original file line number Diff line number Diff line change
Expand Up @@ -517,8 +517,7 @@ private function processDefinedNames(?SimpleXMLElement $gnmXML): void
continue;
}

[$worksheetName] = Worksheet::extractSheetTitle($value, true);
$worksheetName = trim($worksheetName, "'");
[$worksheetName] = Worksheet::extractSheetTitle($value, true, true);
$worksheet = $this->spreadsheet->getSheetByName($worksheetName);
// Worksheet might still be null if we're only loading selected sheets rather than the full spreadsheet
if ($worksheet !== null) {
Expand Down
2 changes: 1 addition & 1 deletion src/PhpSpreadsheet/Reader/Ods/DefinedNames.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ protected function readDefinedExpressions(DOMElement $workbookData): void
*/
private function addDefinedName(string $baseAddress, string $definedName, string $value): void
{
[$sheetReference] = Worksheet::extractSheetTitle($baseAddress, true);
[$sheetReference] = Worksheet::extractSheetTitle($baseAddress, true, true);
$worksheet = $this->spreadsheet->getSheetByName($sheetReference);
// Worksheet might still be null if we're only loading selected sheets rather than the full spreadsheet
if ($worksheet !== null) {
Expand Down
17 changes: 8 additions & 9 deletions src/PhpSpreadsheet/Reader/Xls/LoadSpreadsheet.php
Original file line number Diff line number Diff line change
Expand Up @@ -588,8 +588,8 @@ protected function loadSpreadsheetFromFile2(string $filename, Xls $xls): Spreads
// $range should look like one of these
// Foo!$C$7:$J$66
// Bar!$A$1:$IV$2
$explodes = Worksheet::extractSheetTitle($range, true);
$sheetName = trim($explodes[0], "'");
$explodes = Worksheet::extractSheetTitle($range, true, true);
$sheetName = (string) $explodes[0];
if (!str_contains($explodes[1], ':')) {
$explodes[1] = $explodes[1] . ':' . $explodes[1];
}
Expand Down Expand Up @@ -617,8 +617,9 @@ protected function loadSpreadsheetFromFile2(string $filename, Xls $xls): Spreads
// Sheet!$A$1:$B$65536
// Sheet!$A$1:$IV$2
if (str_contains($range, '!')) {
$explodes = Worksheet::extractSheetTitle($range, true);
if ($docSheet = $xls->spreadsheet->getSheetByName($explodes[0])) {
$explodes = Worksheet::extractSheetTitle($range, true, true);
$docSheet = $xls->spreadsheet->getSheetByName($explodes[0]);
if ($docSheet) {
$extractedRange = $explodes[1];
$extractedRange = str_replace('$', '', $extractedRange);

Expand Down Expand Up @@ -646,11 +647,9 @@ protected function loadSpreadsheetFromFile2(string $filename, Xls $xls): Spreads
/** @var non-empty-string $formula */
$formula = $definedName['formula'];
if (str_contains($formula, '!')) {
$explodes = Worksheet::extractSheetTitle($formula, true);
if (
($docSheet = $xls->spreadsheet->getSheetByName($explodes[0]))
|| ($docSheet = $xls->spreadsheet->getSheetByName(trim($explodes[0], "'")))
) {
$explodes = Worksheet::extractSheetTitle($formula, true, true);
$docSheet = $xls->spreadsheet->getSheetByName($explodes[0]);
if ($docSheet) {
$extractedRange = $explodes[1];

$localOnly = ($definedName['scope'] === 0) ? false : true;
Expand Down
8 changes: 2 additions & 6 deletions src/PhpSpreadsheet/Reader/Xlsx.php
Original file line number Diff line number Diff line change
Expand Up @@ -1819,14 +1819,10 @@ protected function loadSpreadsheetFromFile(string $filename): Spreadsheet
$definedNameValueParts = preg_split("/[ ,](?=([^']*'[^']*')*[^']*$)/miuU", $extractedRange);
if (is_array($definedNameValueParts)) {
// Extract sheet name
[$extractedSheetName] = Worksheet::extractSheetTitle((string) $definedNameValueParts[0], true);
$extractedSheetName ??= '';
if ($extractedSheetName[0] === "'" && substr($extractedSheetName, -1) === "'") {
$extractedSheetName = str_replace("''", "'", substr($extractedSheetName, 1, -1));
}
[$extractedSheetName] = Worksheet::extractSheetTitle((string) $definedNameValueParts[0], true, true);

// Locate sheet
$locatedSheet = $excel->getSheetByName($extractedSheetName);
$locatedSheet = $excel->getSheetByName("$extractedSheetName");
}
}

Expand Down
4 changes: 3 additions & 1 deletion src/PhpSpreadsheet/Style/Style.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use PhpOffice\PhpSpreadsheet\Exception;
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;

class Style extends Supervisor
{
Expand Down Expand Up @@ -189,7 +190,8 @@ public function applyFromArray(array $styleArray, bool $advancedBorders = true):
// Uppercase coordinate and strip any Worksheet reference from the selected range
$pRange = strtoupper($pRange);
if (str_contains($pRange, '!')) {
$pRangeWorksheet = StringHelper::strToUpper(trim(substr($pRange, 0, (int) strrpos($pRange, '!')), "'"));
$pRangeWorksheet = StringHelper::strToUpper(substr($pRange, 0, (int) strrpos($pRange, '!')));
$pRangeWorksheet = Worksheet::unApostrophizeTitle($pRangeWorksheet);
if ($pRangeWorksheet !== '' && StringHelper::strToUpper($this->getActiveSheet()->getTitle()) !== $pRangeWorksheet) {
throw new Exception('Invalid Worksheet for specified Range');
}
Expand Down
Loading

0 comments on commit 7b60624

Please sign in to comment.