Skip to content

Commit 8d7a854

Browse files
authored
Merge pull request #2771 from PHPOffice/Extract-Worksheet-Validations
Extract cell/range validations from Worksheet
2 parents 0d01482 + 69edf61 commit 8d7a854

File tree

4 files changed

+142
-131
lines changed

4 files changed

+142
-131
lines changed

src/PhpSpreadsheet/Calculation/Functions.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
use PhpOffice\PhpSpreadsheet\Cell\Cell;
66
use PhpOffice\PhpSpreadsheet\Shared\Date;
7-
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
87

98
class Functions
109
{
@@ -686,12 +685,13 @@ public static function expandDefinedName(string $coordinate, Cell $cell): string
686685
// Uppercase coordinate
687686
$pCoordinatex = strtoupper($coordinate);
688687
// Eliminate leading equal sign
689-
$pCoordinatex = Worksheet::pregReplace('/^=/', '', $pCoordinatex);
688+
$pCoordinatex = (string) preg_replace('/^=/', '', $pCoordinatex);
690689
$defined = $spreadsheet->getDefinedName($pCoordinatex, $worksheet);
691690
if ($defined !== null) {
692691
$worksheet2 = $defined->getWorkSheet();
693692
if (!$defined->isFormula() && $worksheet2 !== null) {
694-
$coordinate = "'" . $worksheet2->getTitle() . "'!" . Worksheet::pregReplace('/^=/', '', $defined->getValue());
693+
$coordinate = "'" . $worksheet2->getTitle() . "'!" .
694+
(string) preg_replace('/^=/', '', $defined->getValue());
695695
}
696696
}
697697

@@ -700,7 +700,7 @@ public static function expandDefinedName(string $coordinate, Cell $cell): string
700700

701701
public static function trimTrailingRange(string $coordinate): string
702702
{
703-
return Worksheet::pregReplace('/:[\\w\$]+$/', '', $coordinate);
703+
return (string) preg_replace('/:[\\w\$]+$/', '', $coordinate);
704704
}
705705

706706
public static function trimSheetFromCellReference(string $coordinate): string

src/PhpSpreadsheet/Worksheet/AutoFilter.php

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
88
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
99
use PhpOffice\PhpSpreadsheet\Calculation\Internal\WildcardMatch;
10+
use PhpOffice\PhpSpreadsheet\Cell\AddressRange;
1011
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
1112
use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException;
1213
use PhpOffice\PhpSpreadsheet\Shared\Date;
@@ -50,9 +51,18 @@ public function setEvaluated(bool $value): void
5051

5152
/**
5253
* Create a new AutoFilter.
54+
*
55+
* @param AddressRange|array<int>|string $range
56+
* A simple string containing a Cell range like 'A1:E10' is permitted
57+
* or passing in an array of [$fromColumnIndex, $fromRow, $toColumnIndex, $toRow] (e.g. [3, 5, 6, 8]),
58+
* or an AddressRange object.
5359
*/
54-
public function __construct(string $range = '', ?Worksheet $worksheet = null)
60+
public function __construct($range = '', ?Worksheet $worksheet = null)
5561
{
62+
if ($range !== '') {
63+
[, $range] = Worksheet::extractSheetTitle(Validations::validateCellRange($range), true);
64+
}
65+
5666
$this->range = $range;
5767
$this->workSheet = $worksheet;
5868
}
@@ -92,12 +102,19 @@ public function getRange()
92102

93103
/**
94104
* Set AutoFilter Cell Range.
105+
*
106+
* @param AddressRange|array<int>|string $range
107+
* A simple string containing a Cell range like 'A1:E10' is permitted
108+
* or passing in an array of [$fromColumnIndex, $fromRow, $toColumnIndex, $toRow] (e.g. [3, 5, 6, 8]),
109+
* or an AddressRange object.
95110
*/
96-
public function setRange(string $range): self
111+
public function setRange($range = ''): self
97112
{
98113
$this->evaluated = false;
99114
// extract coordinate
100-
[$worksheet, $range] = Worksheet::extractSheetTitle($range, true);
115+
if ($range !== '') {
116+
[, $range] = Worksheet::extractSheetTitle(Validations::validateCellRange($range), true);
117+
}
101118
if (empty($range)) {
102119
// Discard all column rules
103120
$this->columns = [];
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
<?php
2+
3+
namespace PhpOffice\PhpSpreadsheet\Worksheet;
4+
5+
use PhpOffice\PhpSpreadsheet\Cell\AddressRange;
6+
use PhpOffice\PhpSpreadsheet\Cell\CellAddress;
7+
use PhpOffice\PhpSpreadsheet\Cell\CellRange;
8+
9+
class Validations
10+
{
11+
/**
12+
* Validate a cell address.
13+
*
14+
* @param null|array<int>|CellAddress|string $cellAddress Coordinate of the cell as a string, eg: 'C5';
15+
* or as an array of [$columnIndex, $row] (e.g. [3, 5]), or a CellAddress object.
16+
*/
17+
public static function validateCellAddress($cellAddress): string
18+
{
19+
if (is_string($cellAddress)) {
20+
[$worksheet, $address] = Worksheet::extractSheetTitle($cellAddress, true);
21+
// if (!empty($worksheet) && $worksheet !== $this->getTitle()) {
22+
// throw new Exception('Reference is not for this worksheet');
23+
// }
24+
25+
return empty($worksheet) ? strtoupper($address) : $worksheet . '!' . strtoupper($address);
26+
}
27+
28+
if (is_array($cellAddress)) {
29+
$cellAddress = CellAddress::fromColumnRowArray($cellAddress);
30+
}
31+
32+
return (string) $cellAddress;
33+
}
34+
35+
/**
36+
* Validate a cell address or cell range.
37+
*
38+
* @param AddressRange|array<int>|CellAddress|int|string $cellRange Coordinate of the cells as a string, eg: 'C5:F12';
39+
* or as an array of [$fromColumnIndex, $fromRow, $toColumnIndex, $toRow] (e.g. [3, 5, 6, 12]),
40+
* or as a CellAddress or AddressRange object.
41+
*/
42+
public static function validateCellOrCellRange($cellRange): string
43+
{
44+
if (is_string($cellRange) || is_numeric($cellRange)) {
45+
$cellRange = (string) $cellRange;
46+
// Convert a single column reference like 'A' to 'A:A'
47+
$cellRange = (string) preg_replace('/^([A-Z]+)$/', '${1}:${1}', $cellRange);
48+
// Convert a single row reference like '1' to '1:1'
49+
$cellRange = (string) preg_replace('/^(\d+)$/', '${1}:${1}', $cellRange);
50+
} elseif (is_object($cellRange) && $cellRange instanceof CellAddress) {
51+
$cellRange = new CellRange($cellRange, $cellRange);
52+
}
53+
54+
return self::validateCellRange($cellRange);
55+
}
56+
57+
/**
58+
* Validate a cell range.
59+
*
60+
* @param AddressRange|array<int>|string $cellRange Coordinate of the cells as a string, eg: 'C5:F12';
61+
* or as an array of [$fromColumnIndex, $fromRow, $toColumnIndex, $toRow] (e.g. [3, 5, 6, 12]),
62+
* or as an AddressRange object.
63+
*/
64+
public static function validateCellRange($cellRange): string
65+
{
66+
if (is_string($cellRange)) {
67+
[$worksheet, $addressRange] = Worksheet::extractSheetTitle($cellRange, true);
68+
69+
// Convert Column ranges like 'A:C' to 'A1:C1048576'
70+
$addressRange = (string) preg_replace('/^([A-Z]+):([A-Z]+)$/', '${1}1:${2}1048576', $addressRange);
71+
// Convert Row ranges like '1:3' to 'A1:XFD3'
72+
$addressRange = (string) preg_replace('/^(\\d+):(\\d+)$/', 'A${1}:XFD${2}', $addressRange);
73+
74+
return empty($worksheet) ? strtoupper($addressRange) : $worksheet . '!' . strtoupper($addressRange);
75+
}
76+
77+
if (is_array($cellRange)) {
78+
[$from, $to] = array_chunk($cellRange, 2);
79+
$cellRange = new CellRange(CellAddress::fromColumnRowArray($from), CellAddress::fromColumnRowArray($to));
80+
}
81+
82+
return (string) $cellRange;
83+
}
84+
85+
public static function definedNameToCoordinate(string $coordinate, Worksheet $worksheet): string
86+
{
87+
// Uppercase coordinate
88+
$testCoordinate = strtoupper($coordinate);
89+
// Eliminate leading equal sign
90+
$testCoordinate = (string) preg_replace('/^=/', '', $coordinate);
91+
$defined = $worksheet->getParent()->getDefinedName($testCoordinate, $worksheet);
92+
if ($defined !== null) {
93+
if ($defined->getWorksheet() === $worksheet && !$defined->isFormula()) {
94+
$coordinate = (string) preg_replace('/^=/', '', $defined->getValue());
95+
}
96+
}
97+
98+
return $coordinate;
99+
}
100+
}

0 commit comments

Comments
 (0)