From b77a7a3a0957b337363471a5b8e870e7ae8d3227 Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Thu, 11 Mar 2021 18:02:05 +0100 Subject: [PATCH 1/7] Extract LookupRef\INDEX() into index() method of LookupRef\Matrix class Additional tests --- samples/Calculations/LookupRef/ADDRESS.php | 22 ++++++ samples/Calculations/LookupRef/COLUMN.php | 23 +++++++ samples/Calculations/LookupRef/COLUMNS.php | 21 ++++++ samples/Calculations/LookupRef/INDEX.php | 39 +++++++++++ samples/Calculations/LookupRef/ROW.php | 20 ++++++ samples/Calculations/LookupRef/ROWS.php | 20 ++++++ src/PhpSpreadsheet/Calculation/LookupRef.php | 52 ++------------ .../Calculation/LookupRef/Matrix.php | 68 +++++++++++++++++++ .../LookupRef/RowColumnInformation.php | 13 ++-- tests/data/Calculation/LookupRef/INDEX.php | 42 ++++++++++++ tests/data/Calculation/LookupRef/ROW.php | 7 ++ 11 files changed, 274 insertions(+), 53 deletions(-) create mode 100644 samples/Calculations/LookupRef/ADDRESS.php create mode 100644 samples/Calculations/LookupRef/COLUMN.php create mode 100644 samples/Calculations/LookupRef/COLUMNS.php create mode 100644 samples/Calculations/LookupRef/INDEX.php create mode 100644 samples/Calculations/LookupRef/ROW.php create mode 100644 samples/Calculations/LookupRef/ROWS.php diff --git a/samples/Calculations/LookupRef/ADDRESS.php b/samples/Calculations/LookupRef/ADDRESS.php new file mode 100644 index 0000000000..2377541d80 --- /dev/null +++ b/samples/Calculations/LookupRef/ADDRESS.php @@ -0,0 +1,22 @@ +log('Returns a text reference to a single cell in a worksheet.'); + +// Create new PhpSpreadsheet object +$spreadsheet = new Spreadsheet(); +$worksheet = $spreadsheet->getActiveSheet(); + +$worksheet->getCell('A1')->setValue('=ADDRESS(2,3)'); +$worksheet->getCell('A2')->setValue('=ADDRESS(2,3,2)'); +$worksheet->getCell('A3')->setValue('=ADDRESS(2,3,2,FALSE)'); +$worksheet->getCell('A4')->setValue('=ADDRESS(2,3,1,FALSE,"[Book1]Sheet1")'); +$worksheet->getCell('A5')->setValue('=ADDRESS(2,3,1,FALSE,"EXCEL SHEET")'); + +for ($row = 1; $row <= 5; ++$row) { + $cell = $worksheet->getCell("A{$row}"); + $helper->log("A{$row}: {$cell->getValue()} => {$cell->getCalculatedValue()}"); +} diff --git a/samples/Calculations/LookupRef/COLUMN.php b/samples/Calculations/LookupRef/COLUMN.php new file mode 100644 index 0000000000..e9e5846608 --- /dev/null +++ b/samples/Calculations/LookupRef/COLUMN.php @@ -0,0 +1,23 @@ +log('Returns the column index of a cell.'); + +// Create new PhpSpreadsheet object +$spreadsheet = new Spreadsheet(); +$worksheet = $spreadsheet->getActiveSheet(); + +$worksheet->getCell('A1')->setValue('=COLUMN(C13)'); +$worksheet->getCell('A2')->setValue('=COLUMN(E13:G15)'); +$worksheet->getCell('F1')->setValue('=COLUMN()'); + +for ($row = 1; $row <= 2; ++$row) { + $cell = $worksheet->getCell("A{$row}"); + $helper->log("A{$row}: {$cell->getValue()} => {$cell->getCalculatedValue()}"); +} + +$cell = $worksheet->getCell('F1'); +$helper->log("F1: {$cell->getValue()} => {$cell->getCalculatedValue()}"); diff --git a/samples/Calculations/LookupRef/COLUMNS.php b/samples/Calculations/LookupRef/COLUMNS.php new file mode 100644 index 0000000000..4d7f8d10e6 --- /dev/null +++ b/samples/Calculations/LookupRef/COLUMNS.php @@ -0,0 +1,21 @@ +log('Returns the number of columns in an array or reference.'); + +// Create new PhpSpreadsheet object +$spreadsheet = new Spreadsheet(); +$worksheet = $spreadsheet->getActiveSheet(); + +$worksheet->getCell('A1')->setValue('=COLUMNS(C1:G4)'); +$worksheet->getCell('A2')->setValue('=COLUMNS({1,2,3;4,5,6})'); +$worksheet->getCell('A3')->setValue('=ROWS(C1:E4 D3:G5)'); +$worksheet->getCell('A4')->setValue('=COLUMNS(1:1)'); + +for ($row = 1; $row <= 4; ++$row) { + $cell = $worksheet->getCell("A{$row}"); + $helper->log("A{$row}: {$cell->getValue()} => {$cell->getCalculatedValue()}"); +} diff --git a/samples/Calculations/LookupRef/INDEX.php b/samples/Calculations/LookupRef/INDEX.php new file mode 100644 index 0000000000..2a483189dd --- /dev/null +++ b/samples/Calculations/LookupRef/INDEX.php @@ -0,0 +1,39 @@ +log('Returns the row index of a cell.'); + +// Create new PhpSpreadsheet object +$spreadsheet = new Spreadsheet(); +$worksheet = $spreadsheet->getActiveSheet(); + +$data1 = [ + ['Apples', 'Lemons'], + ['Bananas', 'Pears'], +]; + +$data2 = [ + [4, 6], + [5, 3], + [6, 9], + [7, 5], + [8, 3], +]; + +$worksheet->fromArray($data1,null, 'A1'); +$worksheet->fromArray($data2,null, 'C1'); + +$worksheet->getCell('A11')->setValue('=INDEX(A1:B2, 2, 2)'); +$worksheet->getCell('A12')->setValue('=INDEX(A1:B2, 2, 1)'); +$worksheet->getCell('A13')->setValue('=INDEX({1,2;3,4}, 0, 2)'); +$worksheet->getCell('A14')->setValue('=INDEX(C1:C5, 5)'); +$worksheet->getCell('A15')->setValue('=INDEX(C1:D5, 5, 2)'); +$worksheet->getCell('A16')->setValue('=SUM(INDEX(C1:D5, 5, 0))'); + +for ($row = 11; $row <= 16; ++$row) { + $cell = $worksheet->getCell("A{$row}"); + $helper->log("A{$row}: {$cell->getValue()} => {$cell->getCalculatedValue()}"); +} diff --git a/samples/Calculations/LookupRef/ROW.php b/samples/Calculations/LookupRef/ROW.php new file mode 100644 index 0000000000..560639a516 --- /dev/null +++ b/samples/Calculations/LookupRef/ROW.php @@ -0,0 +1,20 @@ +log('Returns the row index of a cell.'); + +// Create new PhpSpreadsheet object +$spreadsheet = new Spreadsheet(); +$worksheet = $spreadsheet->getActiveSheet(); + +$worksheet->getCell('A1')->setValue('=ROW(C13)'); +$worksheet->getCell('A2')->setValue('=ROW(E19:G21)'); +$worksheet->getCell('A3')->setValue('=ROW()'); + +for ($row = 1; $row <= 3; ++$row) { + $cell = $worksheet->getCell("A{$row}"); + $helper->log("A{$row}: {$cell->getValue()} => {$cell->getCalculatedValue()}"); +} diff --git a/samples/Calculations/LookupRef/ROWS.php b/samples/Calculations/LookupRef/ROWS.php new file mode 100644 index 0000000000..3cdf085bd9 --- /dev/null +++ b/samples/Calculations/LookupRef/ROWS.php @@ -0,0 +1,20 @@ +log('Returns the row index of a cell.'); + +// Create new PhpSpreadsheet object +$spreadsheet = new Spreadsheet(); +$worksheet = $spreadsheet->getActiveSheet(); + +$worksheet->getCell('A1')->setValue('=ROWS(C1:E4)'); +$worksheet->getCell('A2')->setValue('=ROWS({1,2,3;4,5,6})'); +$worksheet->getCell('A3')->setValue('=ROWS(C1:E4 D3:G5)'); + +for ($row = 1; $row <= 3; ++$row) { + $cell = $worksheet->getCell("A{$row}"); + $helper->log("A{$row}: {$cell->getValue()} => {$cell->getCalculatedValue()}"); +} diff --git a/src/PhpSpreadsheet/Calculation/LookupRef.php b/src/PhpSpreadsheet/Calculation/LookupRef.php index 39823a205d..8ae59d4669 100644 --- a/src/PhpSpreadsheet/Calculation/LookupRef.php +++ b/src/PhpSpreadsheet/Calculation/LookupRef.php @@ -529,59 +529,19 @@ public static function MATCH($lookupValue, $lookupArray, $matchType = 1) * Excel Function: * =INDEX(range_array, row_num, [column_num]) * + * @Deprecated 1.18.0 + * + * @see Use the index() method in the LookupRef\Matrix class instead + * * @param mixed $arrayValues A range of cells or an array constant * @param mixed $rowNum The row in array from which to return a value. If row_num is omitted, column_num is required. * @param mixed $columnNum The column in array from which to return a value. If column_num is omitted, row_num is required. * * @return mixed the value of a specified cell or array of cells */ - public static function INDEX($arrayValues, $rowNum = 0, $columnNum = 0) + public static function INDEX($matrix, $rowNum = 0, $columnNum = 0) { - $rowNum = Functions::flattenSingleValue($rowNum); - $columnNum = Functions::flattenSingleValue($columnNum); - - if (($rowNum < 0) || ($columnNum < 0)) { - return Functions::VALUE(); - } - - if (!is_array($arrayValues) || ($rowNum > count($arrayValues))) { - return Functions::REF(); - } - - $rowKeys = array_keys($arrayValues); - $columnKeys = @array_keys($arrayValues[$rowKeys[0]]); - - if ($columnNum > count($columnKeys)) { - return Functions::VALUE(); - } elseif ($columnNum == 0) { - if ($rowNum == 0) { - return $arrayValues; - } - $rowNum = $rowKeys[--$rowNum]; - $returnArray = []; - foreach ($arrayValues as $arrayColumn) { - if (is_array($arrayColumn)) { - if (isset($arrayColumn[$rowNum])) { - $returnArray[] = $arrayColumn[$rowNum]; - } else { - return [$rowNum => $arrayValues[$rowNum]]; - } - } else { - return $arrayValues[$rowNum]; - } - } - - return $returnArray; - } - $columnNum = $columnKeys[--$columnNum]; - if ($rowNum > count($rowKeys)) { - return Functions::VALUE(); - } elseif ($rowNum == 0) { - return $arrayValues[$columnNum]; - } - $rowNum = $rowKeys[--$rowNum]; - - return $arrayValues[$rowNum][$columnNum]; + return Matrix::index($matrix, $rowNum, $columnNum); } /** diff --git a/src/PhpSpreadsheet/Calculation/LookupRef/Matrix.php b/src/PhpSpreadsheet/Calculation/LookupRef/Matrix.php index 99fd6e6e74..567f9531e5 100644 --- a/src/PhpSpreadsheet/Calculation/LookupRef/Matrix.php +++ b/src/PhpSpreadsheet/Calculation/LookupRef/Matrix.php @@ -2,6 +2,8 @@ namespace PhpOffice\PhpSpreadsheet\Calculation\LookupRef; +use PhpOffice\PhpSpreadsheet\Calculation\Functions; + class Matrix { /** @@ -30,4 +32,70 @@ public static function transpose($matrixData) return $returnMatrix; } + + /** + * INDEX. + * + * Uses an index to choose a value from a reference or array + * + * Excel Function: + * =INDEX(range_array, row_num, [column_num]) + * + * @param mixed $matrix A range of cells or an array constant + * @param mixed $rowNum The row in array from which to return a value. + * If row_num is omitted, column_num is required. + * @param mixed $columnNum The column in array from which to return a value. + * If column_num is omitted, row_num is required. + * + * @return mixed the value of a specified cell or array of cells + */ + public static function index($matrix, $rowNum = 0, $columnNum = 0) + { + $rowNum = Functions::flattenSingleValue($rowNum); + $columnNum = Functions::flattenSingleValue($columnNum); + + if (!is_numeric($rowNum) || !is_numeric($columnNum) ||( $rowNum < 0) || ($columnNum < 0)) { + return Functions::VALUE(); + } + + if (!is_array($matrix) || ($rowNum > count($matrix))) { + return Functions::REF(); + } + + $rowKeys = array_keys($matrix); + $columnKeys = @array_keys($matrix[$rowKeys[0]]); + + if ($columnNum > count($columnKeys)) { + return Functions::VALUE(); + } elseif ($columnNum == 0) { + if ($rowNum == 0) { + return $matrix; + } + $rowNum = $rowKeys[--$rowNum]; + $returnArray = []; + foreach ($matrix as $arrayColumn) { + if (is_array($arrayColumn)) { + if (isset($arrayColumn[$rowNum])) { + $returnArray[] = $arrayColumn[$rowNum]; + } else { + return [$rowNum => $matrix[$rowNum]]; + } + } else { + return $matrix[$rowNum]; + } + } + + return $returnArray; + } + + $columnNum = $columnKeys[--$columnNum]; + if ($rowNum > count($rowKeys)) { + return Functions::VALUE(); + } elseif ($rowNum == 0) { + return $matrix[$columnNum]; + } + $rowNum = $rowKeys[--$rowNum]; + + return $matrix[$rowNum][$columnNum]; + } } diff --git a/src/PhpSpreadsheet/Calculation/LookupRef/RowColumnInformation.php b/src/PhpSpreadsheet/Calculation/LookupRef/RowColumnInformation.php index 0cce806a5a..b0def78524 100644 --- a/src/PhpSpreadsheet/Calculation/LookupRef/RowColumnInformation.php +++ b/src/PhpSpreadsheet/Calculation/LookupRef/RowColumnInformation.php @@ -45,12 +45,11 @@ public static function COLUMN($cellAddress = null, ?Cell $cell = null) [$startAddress, $endAddress] = explode(':', $cellAddress); $startAddress = preg_replace('/[^a-z]/i', '', $startAddress); $endAddress = preg_replace('/[^a-z]/i', '', $endAddress); - $returnValue = []; - do { - $returnValue[] = (int) Coordinate::columnIndexFromString($startAddress); - } while ($startAddress++ != $endAddress); - return $returnValue; + return range( + (int) Coordinate::columnIndexFromString($startAddress), + (int) Coordinate::columnIndexFromString($endAddress) + ); } $cellAddress = preg_replace('/[^a-z]/i', '', $cellAddress); @@ -114,8 +113,8 @@ public static function ROW($cellAddress = null, ?Cell $pCell = null) } if (is_array($cellAddress)) { - foreach ($cellAddress as $columnKey => $rowValue) { - foreach ($rowValue as $rowKey => $cellValue) { + foreach ($cellAddress as $rowKey => $rowValue) { + foreach ($rowValue as $columnKey => $cellValue) { return (int) preg_replace('/\D/', '', $rowKey); } } diff --git a/tests/data/Calculation/LookupRef/INDEX.php b/tests/data/Calculation/LookupRef/INDEX.php index 55206270e0..e825774a54 100644 --- a/tests/data/Calculation/LookupRef/INDEX.php +++ b/tests/data/Calculation/LookupRef/INDEX.php @@ -87,4 +87,46 @@ '21' => ['R' => 2], ], ], + [ + 'Pears', + [ + ['Apples', 'Lemons'], + ['Bananas', 'Pears'], + ], + 2, + 2 + ], + [ + 'Bananas', + [ + ['Apples', 'Lemons'], + ['Bananas', 'Pears'], + ], + 2, + 1 + ], + [ + 3, + [ + [4, 6], + [5, 3], + [6, 9], + [7, 5], + [8, 3], + ], + 5, + 2 + ], + [ + [4 => [8, 3]], + [ + [4, 6], + [5, 3], + [6, 9], + [7, 5], + [8, 3], + ], + 5, + 0 + ], ]; diff --git a/tests/data/Calculation/LookupRef/ROW.php b/tests/data/Calculation/LookupRef/ROW.php index 89566011ef..62545c7674 100644 --- a/tests/data/Calculation/LookupRef/ROW.php +++ b/tests/data/Calculation/LookupRef/ROW.php @@ -17,6 +17,13 @@ [[10], [11], [12]], 'C10:D12', ], + [ + 4, + [ + 4 => ['B' => 'B5', 'C' => 'C5', 'D' => 'D5'], + 5 => ['B' => 'B5', 'C' => 'C5', 'D' => 'D5'], + ], + ], [ [[10], [11], [12]], 'Sheet1!C10:C12', From f7f55f7a43c4f6dbe9cbe30143f555d45437231e Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Thu, 11 Mar 2021 18:06:18 +0100 Subject: [PATCH 2/7] Cosmetics --- samples/Calculations/LookupRef/INDEX.php | 4 ++-- src/PhpSpreadsheet/Calculation/LookupRef.php | 8 +++++--- src/PhpSpreadsheet/Calculation/LookupRef/Matrix.php | 6 +++--- tests/data/Calculation/LookupRef/INDEX.php | 8 ++++---- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/samples/Calculations/LookupRef/INDEX.php b/samples/Calculations/LookupRef/INDEX.php index 2a483189dd..9ef0b94562 100644 --- a/samples/Calculations/LookupRef/INDEX.php +++ b/samples/Calculations/LookupRef/INDEX.php @@ -23,8 +23,8 @@ [8, 3], ]; -$worksheet->fromArray($data1,null, 'A1'); -$worksheet->fromArray($data2,null, 'C1'); +$worksheet->fromArray($data1, null, 'A1'); +$worksheet->fromArray($data2, null, 'C1'); $worksheet->getCell('A11')->setValue('=INDEX(A1:B2, 2, 2)'); $worksheet->getCell('A12')->setValue('=INDEX(A1:B2, 2, 1)'); diff --git a/src/PhpSpreadsheet/Calculation/LookupRef.php b/src/PhpSpreadsheet/Calculation/LookupRef.php index 8ae59d4669..f1a147f18c 100644 --- a/src/PhpSpreadsheet/Calculation/LookupRef.php +++ b/src/PhpSpreadsheet/Calculation/LookupRef.php @@ -533,9 +533,11 @@ public static function MATCH($lookupValue, $lookupArray, $matchType = 1) * * @see Use the index() method in the LookupRef\Matrix class instead * - * @param mixed $arrayValues A range of cells or an array constant - * @param mixed $rowNum The row in array from which to return a value. If row_num is omitted, column_num is required. - * @param mixed $columnNum The column in array from which to return a value. If column_num is omitted, row_num is required. + * @param mixed $rowNum The row in the array or range from which to return a value. + * If row_num is omitted, column_num is required. + * @param mixed $columnNum The column in the array or range from which to return a value. + * If column_num is omitted, row_num is required. + * @param mixed $matrix * * @return mixed the value of a specified cell or array of cells */ diff --git a/src/PhpSpreadsheet/Calculation/LookupRef/Matrix.php b/src/PhpSpreadsheet/Calculation/LookupRef/Matrix.php index 567f9531e5..6719af25c4 100644 --- a/src/PhpSpreadsheet/Calculation/LookupRef/Matrix.php +++ b/src/PhpSpreadsheet/Calculation/LookupRef/Matrix.php @@ -42,9 +42,9 @@ public static function transpose($matrixData) * =INDEX(range_array, row_num, [column_num]) * * @param mixed $matrix A range of cells or an array constant - * @param mixed $rowNum The row in array from which to return a value. + * @param mixed $rowNum The row in the array or range from which to return a value. * If row_num is omitted, column_num is required. - * @param mixed $columnNum The column in array from which to return a value. + * @param mixed $columnNum The column in the array or range from which to return a value. * If column_num is omitted, row_num is required. * * @return mixed the value of a specified cell or array of cells @@ -54,7 +54,7 @@ public static function index($matrix, $rowNum = 0, $columnNum = 0) $rowNum = Functions::flattenSingleValue($rowNum); $columnNum = Functions::flattenSingleValue($columnNum); - if (!is_numeric($rowNum) || !is_numeric($columnNum) ||( $rowNum < 0) || ($columnNum < 0)) { + if (!is_numeric($rowNum) || !is_numeric($columnNum) || ($rowNum < 0) || ($columnNum < 0)) { return Functions::VALUE(); } diff --git a/tests/data/Calculation/LookupRef/INDEX.php b/tests/data/Calculation/LookupRef/INDEX.php index e825774a54..342fb00f72 100644 --- a/tests/data/Calculation/LookupRef/INDEX.php +++ b/tests/data/Calculation/LookupRef/INDEX.php @@ -94,7 +94,7 @@ ['Bananas', 'Pears'], ], 2, - 2 + 2, ], [ 'Bananas', @@ -103,7 +103,7 @@ ['Bananas', 'Pears'], ], 2, - 1 + 1, ], [ 3, @@ -115,7 +115,7 @@ [8, 3], ], 5, - 2 + 2, ], [ [4 => [8, 3]], @@ -127,6 +127,6 @@ [8, 3], ], 5, - 0 + 0, ], ]; From 42b0a543c9f06a47752b7941d49dc3b3754f0436 Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Thu, 11 Mar 2021 20:17:03 +0100 Subject: [PATCH 3/7] Bugfix for returning a column using INDEX() --- .../Calculation/LookupRef/Matrix.php | 9 ++++-- .../Functions/LookupRef/IndexTest.php | 1 + tests/data/Calculation/LookupRef/INDEX.php | 30 ++++++++++++++++++- 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/src/PhpSpreadsheet/Calculation/LookupRef/Matrix.php b/src/PhpSpreadsheet/Calculation/LookupRef/Matrix.php index 6719af25c4..7e69451879 100644 --- a/src/PhpSpreadsheet/Calculation/LookupRef/Matrix.php +++ b/src/PhpSpreadsheet/Calculation/LookupRef/Matrix.php @@ -66,7 +66,7 @@ public static function index($matrix, $rowNum = 0, $columnNum = 0) $columnKeys = @array_keys($matrix[$rowKeys[0]]); if ($columnNum > count($columnKeys)) { - return Functions::VALUE(); + return Functions::REF(); } elseif ($columnNum == 0) { if ($rowNum == 0) { return $matrix; @@ -92,7 +92,12 @@ public static function index($matrix, $rowNum = 0, $columnNum = 0) if ($rowNum > count($rowKeys)) { return Functions::VALUE(); } elseif ($rowNum == 0) { - return $matrix[$columnNum]; + return array_map( + function ($value) { + return [$value]; + }, + array_column($matrix, $columnNum) + ); } $rowNum = $rowKeys[--$rowNum]; diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/LookupRef/IndexTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/LookupRef/IndexTest.php index 8ff6693169..c84a504de2 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/LookupRef/IndexTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/LookupRef/IndexTest.php @@ -21,6 +21,7 @@ protected function setUp(): void public function testINDEX($expectedResult, ...$args): void { $result = LookupRef::INDEX(...$args); +// var_dump($result); self::assertEquals($expectedResult, $result); } diff --git a/tests/data/Calculation/LookupRef/INDEX.php b/tests/data/Calculation/LookupRef/INDEX.php index 342fb00f72..157794ab18 100644 --- a/tests/data/Calculation/LookupRef/INDEX.php +++ b/tests/data/Calculation/LookupRef/INDEX.php @@ -54,7 +54,7 @@ -1, ], [ - '#VALUE!', // Expected + '#REF!', // Expected // Input [ '20' => ['R' => 1, 'S' => 3], @@ -63,6 +63,16 @@ 2, 10, ], + [ + '#REF!', // Expected + // Input + [ + '20' => ['R' => 1, 'S' => 3], + '21' => ['R' => 2, 'S' => 4], + ], + 10, + 2, + ], [ 4, // Expected // Input @@ -129,4 +139,22 @@ 5, 0, ], + [ + [ + [6], + [3], + [9], + [5], + [3], + ], + [ + [4, 6], + [5, 3], + [6, 9], + [7, 5], + [8, 3], + ], + 0, + 2, + ], ]; From b451846dcaaccf5d73069d72be6be37d8e0946b7 Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Thu, 11 Mar 2021 20:55:58 +0100 Subject: [PATCH 4/7] Some improvements to ROW() and COLUMN() --- .../Calculation/LookupRef/Matrix.php | 8 +-- .../LookupRef/RowColumnInformation.php | 59 ++++++++++--------- 2 files changed, 34 insertions(+), 33 deletions(-) diff --git a/src/PhpSpreadsheet/Calculation/LookupRef/Matrix.php b/src/PhpSpreadsheet/Calculation/LookupRef/Matrix.php index 7e69451879..decc5b401b 100644 --- a/src/PhpSpreadsheet/Calculation/LookupRef/Matrix.php +++ b/src/PhpSpreadsheet/Calculation/LookupRef/Matrix.php @@ -67,7 +67,9 @@ public static function index($matrix, $rowNum = 0, $columnNum = 0) if ($columnNum > count($columnKeys)) { return Functions::REF(); - } elseif ($columnNum == 0) { + } + + if ($columnNum == 0) { if ($rowNum == 0) { return $matrix; } @@ -89,9 +91,7 @@ public static function index($matrix, $rowNum = 0, $columnNum = 0) } $columnNum = $columnKeys[--$columnNum]; - if ($rowNum > count($rowKeys)) { - return Functions::VALUE(); - } elseif ($rowNum == 0) { + if ($rowNum == 0) { return array_map( function ($value) { return [$value]; diff --git a/src/PhpSpreadsheet/Calculation/LookupRef/RowColumnInformation.php b/src/PhpSpreadsheet/Calculation/LookupRef/RowColumnInformation.php index b0def78524..32977b8c7e 100644 --- a/src/PhpSpreadsheet/Calculation/LookupRef/RowColumnInformation.php +++ b/src/PhpSpreadsheet/Calculation/LookupRef/RowColumnInformation.php @@ -39,22 +39,23 @@ public static function COLUMN($cellAddress = null, ?Cell $cell = null) return (int) Coordinate::columnIndexFromString($columnKey); } - } else { - [, $cellAddress] = Worksheet::extractSheetTitle($cellAddress, true); - if (strpos($cellAddress, ':') !== false) { - [$startAddress, $endAddress] = explode(':', $cellAddress); - $startAddress = preg_replace('/[^a-z]/i', '', $startAddress); - $endAddress = preg_replace('/[^a-z]/i', '', $endAddress); - - return range( - (int) Coordinate::columnIndexFromString($startAddress), - (int) Coordinate::columnIndexFromString($endAddress) - ); - } - $cellAddress = preg_replace('/[^a-z]/i', '', $cellAddress); + } - return (int) Coordinate::columnIndexFromString($cellAddress); + [, $cellAddress] = Worksheet::extractSheetTitle($cellAddress, true); + if (strpos($cellAddress, ':') !== false) { + [$startAddress, $endAddress] = explode(':', $cellAddress); + $startAddress = preg_replace('/[^a-z]/i', '', $startAddress); + $endAddress = preg_replace('/[^a-z]/i', '', $endAddress); + + return range( + (int) Coordinate::columnIndexFromString($startAddress), + (int) Coordinate::columnIndexFromString($endAddress) + ); } + + $cellAddress = preg_replace('/[^a-z]/i', '', $cellAddress); + + return (int) Coordinate::columnIndexFromString($cellAddress); } /** @@ -118,23 +119,23 @@ public static function ROW($cellAddress = null, ?Cell $pCell = null) return (int) preg_replace('/\D/', '', $rowKey); } } - } else { - [, $cellAddress] = Worksheet::extractSheetTitle($cellAddress, true); - if (strpos($cellAddress, ':') !== false) { - [$startAddress, $endAddress] = explode(':', $cellAddress); - $startAddress = preg_replace('/\D/', '', $startAddress); - $endAddress = preg_replace('/\D/', '', $endAddress); - $returnValue = []; - do { - $returnValue[][] = (int) $startAddress; - } while ($startAddress++ != $endAddress); - - return $returnValue; - } - [$cellAddress] = explode(':', $cellAddress); + } - return (int) preg_replace('/\D/', '', $cellAddress); + [, $cellAddress] = Worksheet::extractSheetTitle($cellAddress, true); + if (strpos($cellAddress, ':') !== false) { + [$startAddress, $endAddress] = explode(':', $cellAddress); + $startAddress = preg_replace('/\D/', '', $startAddress); + $endAddress = preg_replace('/\D/', '', $endAddress); + $returnValue = []; + do { + $returnValue[][] = (int) $startAddress; + } while ($startAddress++ != $endAddress); + + return $returnValue; } + [$cellAddress] = explode(':', $cellAddress); + + return (int) preg_replace('/\D/', '', $cellAddress); } /** From 3bbbd1bd0a4addf5a084cbbd6d1c5c36f09a31e6 Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Thu, 11 Mar 2021 21:30:43 +0100 Subject: [PATCH 5/7] Simplify some of the INDEX() logic, eliminating redundant code --- .../Calculation/LookupRef/Matrix.php | 17 +++++------------ .../LookupRef/RowColumnInformation.php | 4 ++-- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/src/PhpSpreadsheet/Calculation/LookupRef/Matrix.php b/src/PhpSpreadsheet/Calculation/LookupRef/Matrix.php index decc5b401b..bf06814485 100644 --- a/src/PhpSpreadsheet/Calculation/LookupRef/Matrix.php +++ b/src/PhpSpreadsheet/Calculation/LookupRef/Matrix.php @@ -73,21 +73,14 @@ public static function index($matrix, $rowNum = 0, $columnNum = 0) if ($rowNum == 0) { return $matrix; } + $rowNum = $rowKeys[--$rowNum]; - $returnArray = []; - foreach ($matrix as $arrayColumn) { - if (is_array($arrayColumn)) { - if (isset($arrayColumn[$rowNum])) { - $returnArray[] = $arrayColumn[$rowNum]; - } else { - return [$rowNum => $matrix[$rowNum]]; - } - } else { - return $matrix[$rowNum]; - } + $row = $matrix[$rowNum]; + if (is_array($row)) { + return [$rowNum => $row]; } - return $returnArray; + return $row; } $columnNum = $columnKeys[--$columnNum]; diff --git a/src/PhpSpreadsheet/Calculation/LookupRef/RowColumnInformation.php b/src/PhpSpreadsheet/Calculation/LookupRef/RowColumnInformation.php index 32977b8c7e..c78e65db56 100644 --- a/src/PhpSpreadsheet/Calculation/LookupRef/RowColumnInformation.php +++ b/src/PhpSpreadsheet/Calculation/LookupRef/RowColumnInformation.php @@ -73,7 +73,7 @@ public static function COLUMN($cellAddress = null, ?Cell $cell = null) */ public static function COLUMNS($cellAddress = null) { - if ($cellAddress === null || $cellAddress === '') { + if ($cellAddress === null || (is_string($cellAddress) && trim($cellAddress) === '')) { return 1; } elseif (!is_array($cellAddress)) { return Functions::VALUE(); @@ -153,7 +153,7 @@ public static function ROW($cellAddress = null, ?Cell $pCell = null) */ public static function ROWS($cellAddress = null) { - if ($cellAddress === null || $cellAddress === '') { + if ($cellAddress === null || (is_string($cellAddress) && trim($cellAddress) === '')) { return 1; } elseif (!is_array($cellAddress)) { return Functions::VALUE(); From 36211c27675757238eabedda41570619f50f45a1 Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Thu, 11 Mar 2021 21:57:31 +0100 Subject: [PATCH 6/7] Some refactoring --- .../Calculation/LookupRef/Matrix.php | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/PhpSpreadsheet/Calculation/LookupRef/Matrix.php b/src/PhpSpreadsheet/Calculation/LookupRef/Matrix.php index bf06814485..8859a28757 100644 --- a/src/PhpSpreadsheet/Calculation/LookupRef/Matrix.php +++ b/src/PhpSpreadsheet/Calculation/LookupRef/Matrix.php @@ -70,17 +70,7 @@ public static function index($matrix, $rowNum = 0, $columnNum = 0) } if ($columnNum == 0) { - if ($rowNum == 0) { - return $matrix; - } - - $rowNum = $rowKeys[--$rowNum]; - $row = $matrix[$rowNum]; - if (is_array($row)) { - return [$rowNum => $row]; - } - - return $row; + return self::extractRowValue($matrix, $rowKeys, $rowNum); } $columnNum = $columnKeys[--$columnNum]; @@ -96,4 +86,19 @@ function ($value) { return $matrix[$rowNum][$columnNum]; } + + private static function extractRowValue(array $matrix, array $rowKeys, int $rowNum) + { + if ($rowNum == 0) { + return $matrix; + } + + $rowNum = $rowKeys[--$rowNum]; + $row = $matrix[$rowNum]; + if (is_array($row)) { + return [$rowNum => $row]; + } + + return $row; + } } From 7714a033c99893f8d26fff3839fea09eaefa1fdc Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Thu, 11 Mar 2021 22:16:30 +0100 Subject: [PATCH 7/7] Some refactoring --- .../LookupRef/RowColumnInformation.php | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/PhpSpreadsheet/Calculation/LookupRef/RowColumnInformation.php b/src/PhpSpreadsheet/Calculation/LookupRef/RowColumnInformation.php index c78e65db56..19d0d5ff8a 100644 --- a/src/PhpSpreadsheet/Calculation/LookupRef/RowColumnInformation.php +++ b/src/PhpSpreadsheet/Calculation/LookupRef/RowColumnInformation.php @@ -41,7 +41,7 @@ public static function COLUMN($cellAddress = null, ?Cell $cell = null) } } - [, $cellAddress] = Worksheet::extractSheetTitle($cellAddress, true); + [, $cellAddress] = Worksheet::extractSheetTitle((string) $cellAddress, true); if (strpos($cellAddress, ':') !== false) { [$startAddress, $endAddress] = explode(':', $cellAddress); $startAddress = preg_replace('/[^a-z]/i', '', $startAddress); @@ -121,17 +121,18 @@ public static function ROW($cellAddress = null, ?Cell $pCell = null) } } - [, $cellAddress] = Worksheet::extractSheetTitle($cellAddress, true); + [, $cellAddress] = Worksheet::extractSheetTitle((string) $cellAddress, true); if (strpos($cellAddress, ':') !== false) { [$startAddress, $endAddress] = explode(':', $cellAddress); $startAddress = preg_replace('/\D/', '', $startAddress); $endAddress = preg_replace('/\D/', '', $endAddress); - $returnValue = []; - do { - $returnValue[][] = (int) $startAddress; - } while ($startAddress++ != $endAddress); - return $returnValue; + return array_map( + function ($value) { + return [$value]; + }, + range($startAddress, $endAddress) + ); } [$cellAddress] = explode(':', $cellAddress);