Merge pull request #2687 from PHPOffice/Bugfix_Support-Row/Column-Ranges-in-INDIRECT()-Function

Allow `INDIRECT()` to accept row/column ranges as well as cell ranges
This commit is contained in:
Mark Baker 2022-03-16 23:16:50 +01:00 committed by GitHub
commit 78c27c03ca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 31 additions and 2 deletions

View File

@ -39,6 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org).
### Fixed ### Fixed
- Allow `INDIRECT()` to accept row/column ranges as well as cell ranges [PR #2687](https://github.com/PHPOffice/PhpSpreadsheet/pull/2687)
- Fix bug when deleting cells with hyperlinks, where the hyperlink was then being "inherited" by whatever cell moved to that cell address. - Fix bug when deleting cells with hyperlinks, where the hyperlink was then being "inherited" by whatever cell moved to that cell address.
- Fix bug in Conditional Formatting in the Xls Writer that resulted in a broken file when there were multiple conditional ranges in a worksheet. - Fix bug in Conditional Formatting in the Xls Writer that resulted in a broken file when there were multiple conditional ranges in a worksheet.
- Fix Conditional Formatting in the Xls Writer to work with rules that contain string literals, cell references and formulae. - Fix Conditional Formatting in the Xls Writer to work with rules that contain string literals, cell references and formulae.

View File

@ -72,11 +72,17 @@ class Indirect
[$cellAddress, $worksheet, $sheetName] = Helpers::extractWorksheet($cellAddress, $cell); [$cellAddress, $worksheet, $sheetName] = Helpers::extractWorksheet($cellAddress, $cell);
if (preg_match('/^' . Calculation::CALCULATION_REGEXP_COLUMNRANGE_RELATIVE . '$/miu', $cellAddress, $matches)) {
$cellAddress = self::handleRowColumnRanges($worksheet, ...explode(':', $cellAddress));
} elseif (preg_match('/^' . Calculation::CALCULATION_REGEXP_ROWRANGE_RELATIVE . '$/miu', $cellAddress, $matches)) {
$cellAddress = self::handleRowColumnRanges($worksheet, ...explode(':', $cellAddress));
}
[$cellAddress1, $cellAddress2, $cellAddress] = Helpers::extractCellAddresses($cellAddress, $a1, $cell->getWorkSheet(), $sheetName); [$cellAddress1, $cellAddress2, $cellAddress] = Helpers::extractCellAddresses($cellAddress, $a1, $cell->getWorkSheet(), $sheetName);
if ( if (
(!preg_match('/^' . Calculation::CALCULATION_REGEXP_CELLREF . '$/i', $cellAddress1, $matches)) || (!preg_match('/^' . Calculation::CALCULATION_REGEXP_CELLREF . '$/miu', $cellAddress1, $matches)) ||
(($cellAddress2 !== null) && (!preg_match('/^' . Calculation::CALCULATION_REGEXP_CELLREF . '$/i', $cellAddress2, $matches))) (($cellAddress2 !== null) && (!preg_match('/^' . Calculation::CALCULATION_REGEXP_CELLREF . '$/miu', $cellAddress2, $matches)))
) { ) {
return ExcelError::REF(); return ExcelError::REF();
} }
@ -95,4 +101,22 @@ class Indirect
return Calculation::getInstance($worksheet !== null ? $worksheet->getParent() : null) return Calculation::getInstance($worksheet !== null ? $worksheet->getParent() : null)
->extractCellRange($cellAddress, $worksheet, false); ->extractCellRange($cellAddress, $worksheet, false);
} }
private static function handleRowColumnRanges(?Worksheet $worksheet, string $start, string $end): string
{
// Being lazy, we're only checking a single row/column to get the max
if (ctype_digit($start) && $start <= 1048576) {
// Max 16,384 columns for Excel2007
$endColRef = ($worksheet !== null) ? $worksheet->getHighestDataColumn((int) $start) : 'XFD';
return "A{$start}:{$endColRef}{$end}";
} elseif (ctype_alpha($start) && strlen($start) <= 3) {
// Max 1,048,576 rows for Excel2007
$endRowRef = ($worksheet !== null) ? $worksheet->getHighestDataRow($start) : 1048576;
return "{$start}1:{$end}{$endRowRef}";
}
return "{$start}:{$end}";
}
} }

View File

@ -34,4 +34,8 @@ return [
'supply a1 argument as int' => [900, 'A2:A4', 1], 'supply a1 argument as int' => [900, 'A2:A4', 1],
'supply a1 argument as float' => [900, 'A2:A4', 7.3], 'supply a1 argument as float' => [900, 'A2:A4', 7.3],
'supply a1 argument as string not permitted' => ['#VALUE!', 'A2:A4', '1'], 'supply a1 argument as string not permitted' => ['#VALUE!', 'A2:A4', '1'],
'row range' => [600, '1:3'],
'column range' => [1500, 'A:C'],
'row range on different sheet' => [66, 'OtherSheet!1:3'],
'column range on different sheet' => [165, 'OtherSheet!A:C'],
]; ];