Skip to content

Commit 070ceef

Browse files
committed
Changes to INDEX Function
Fix #64 (really!), closed as stale in December 2017, another in our "better late than never" series. Excel's INDEX function doesn't really behave quite as described. If a single row is used as an argument, either in literal form `{item1, item2, item3}` or expressed as a range `A1:A6`, INDEX is happy to evaluate the array as if each entry were a row rather than a single item. PhpSpreadsheet is changed to do likewise. INDEX also returned `#REF!` when it would normally return an array (which would often be reduced to its leftmost topmost entry later). This code is deleted, invalidating one existing test, and INDEX will now operate like other functions which can return arrays.
1 parent 1b68270 commit 070ceef

File tree

3 files changed

+45
-5
lines changed

3 files changed

+45
-5
lines changed

src/PhpSpreadsheet/Calculation/LookupRef/Matrix.php

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ public static function index(mixed $matrix, mixed $rowNum = 0, mixed $columnNum
8181
}
8282

8383
$rowNum = $rowNum ?? 0;
84-
$originalColumnNum = $columnNum;
8584
$columnNum = $columnNum ?? 0;
8685

8786
try {
@@ -91,6 +90,17 @@ public static function index(mixed $matrix, mixed $rowNum = 0, mixed $columnNum
9190
return $e->getMessage();
9291
}
9392

93+
if (is_array($matrix) && count($matrix) === 1 && $rowNum > 1) {
94+
$matrixKey = array_keys($matrix)[0];
95+
if (is_array($matrix[$matrixKey])) {
96+
$tempMatrix = [];
97+
foreach ($matrix[$matrixKey] as $key => $value) {
98+
$tempMatrix[$key] = [$value];
99+
}
100+
$matrix = $tempMatrix;
101+
}
102+
}
103+
94104
if (!is_array($matrix) || ($rowNum > count($matrix))) {
95105
return ExcelError::REF();
96106
}
@@ -101,9 +111,6 @@ public static function index(mixed $matrix, mixed $rowNum = 0, mixed $columnNum
101111
if ($columnNum > count($columnKeys)) {
102112
return ExcelError::REF();
103113
}
104-
if ($originalColumnNum === null && 1 < count($columnKeys)) {
105-
return ExcelError::REF();
106-
}
107114

108115
if ($columnNum === 0) {
109116
return self::extractRowValue($matrix, $rowKeys, $rowNum);

tests/PhpSpreadsheetTests/Calculation/Functions/LookupRef/IndexOnSpreadsheetTest.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,37 @@ public static function providerINDEXonSpreadsheet(): array
3434
{
3535
return require 'tests/data/Calculation/LookupRef/INDEXonSpreadsheet.php';
3636
}
37+
38+
/**
39+
* @dataProvider providerIndexLiteralArrays
40+
*/
41+
public function testLiteralArrays(mixed $expectedResult, string $indexArgs): void
42+
{
43+
$sheet = $this->getSheet();
44+
$sheet->getCell('A10')->setValue(10);
45+
$sheet->getCell('B10')->setValue(11);
46+
$sheet->getCell('C10')->setValue(12);
47+
$sheet->getCell('D10')->setValue(13);
48+
$sheet->getCell('X10')->setValue(10);
49+
$sheet->getCell('X11')->setValue(11);
50+
$sheet->getCell('X12')->setValue(12);
51+
$sheet->getCell('X13')->setValue(13);
52+
$sheet->getCell('A1')->setValue("=INDEX($indexArgs)");
53+
$result = $sheet->getCell('A1')->getCalculatedValue();
54+
self::assertEquals($expectedResult, $result);
55+
}
56+
57+
public static function providerIndexLiteralArrays(): array
58+
{
59+
return [
60+
'issue 64' => ['Fourth', '{"First","Second","Third","Fourth","Fifth","Sixth","Seventh"}, 4'],
61+
'issue 64 selecting first "row"' => ['First', '{"First","Second","Third","Fourth","Fifth","Sixth","Seventh"}, 1'],
62+
'array result condensed to single value' => [40, '{10,11;20,21;30,31;40,41;50,51;60,61},4'],
63+
'both row and column' => [41, '{10,11;20,21;30,31;40,41;50,51;60,61},4,2'],
64+
'1*1 array' => ['first', '{"first"},1'],
65+
'array expressed in rows' => [20, '{10;20;30;40},2'],
66+
'spreadsheet single row' => [11, 'A10:D10,2'],
67+
'spreadsheet single column' => [13, 'X10:X13,4'],
68+
];
69+
}
3770
}

tests/data/Calculation/LookupRef/INDEXonSpreadsheet.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@
8282
2,
8383
],
8484
'Column number omitted from 2-column matrix' => [
85-
'#REF!', // Expected
85+
'abc', // Expected
8686
[
8787
['abc', 'def'],
8888
['xyz', 'tuv'],

0 commit comments

Comments
 (0)