mirror of
https://github.com/PHPOffice/PhpSpreadsheet.git
synced 2026-09-13 19:46:31 +00:00
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.
This commit is contained in:
@@ -81,7 +81,6 @@ class Matrix
|
||||
}
|
||||
|
||||
$rowNum = $rowNum ?? 0;
|
||||
$originalColumnNum = $columnNum;
|
||||
$columnNum = $columnNum ?? 0;
|
||||
|
||||
try {
|
||||
@@ -91,6 +90,17 @@ class Matrix
|
||||
return $e->getMessage();
|
||||
}
|
||||
|
||||
if (is_array($matrix) && count($matrix) === 1 && $rowNum > 1) {
|
||||
$matrixKey = array_keys($matrix)[0];
|
||||
if (is_array($matrix[$matrixKey])) {
|
||||
$tempMatrix = [];
|
||||
foreach ($matrix[$matrixKey] as $key => $value) {
|
||||
$tempMatrix[$key] = [$value];
|
||||
}
|
||||
$matrix = $tempMatrix;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_array($matrix) || ($rowNum > count($matrix))) {
|
||||
return ExcelError::REF();
|
||||
}
|
||||
@@ -101,9 +111,6 @@ class Matrix
|
||||
if ($columnNum > count($columnKeys)) {
|
||||
return ExcelError::REF();
|
||||
}
|
||||
if ($originalColumnNum === null && 1 < count($columnKeys)) {
|
||||
return ExcelError::REF();
|
||||
}
|
||||
|
||||
if ($columnNum === 0) {
|
||||
return self::extractRowValue($matrix, $rowKeys, $rowNum);
|
||||
|
||||
@@ -34,4 +34,37 @@ class IndexOnSpreadsheetTest extends AllSetupTeardown
|
||||
{
|
||||
return require 'tests/data/Calculation/LookupRef/INDEXonSpreadsheet.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerIndexLiteralArrays
|
||||
*/
|
||||
public function testLiteralArrays(mixed $expectedResult, string $indexArgs): void
|
||||
{
|
||||
$sheet = $this->getSheet();
|
||||
$sheet->getCell('A10')->setValue(10);
|
||||
$sheet->getCell('B10')->setValue(11);
|
||||
$sheet->getCell('C10')->setValue(12);
|
||||
$sheet->getCell('D10')->setValue(13);
|
||||
$sheet->getCell('X10')->setValue(10);
|
||||
$sheet->getCell('X11')->setValue(11);
|
||||
$sheet->getCell('X12')->setValue(12);
|
||||
$sheet->getCell('X13')->setValue(13);
|
||||
$sheet->getCell('A1')->setValue("=INDEX($indexArgs)");
|
||||
$result = $sheet->getCell('A1')->getCalculatedValue();
|
||||
self::assertEquals($expectedResult, $result);
|
||||
}
|
||||
|
||||
public static function providerIndexLiteralArrays(): array
|
||||
{
|
||||
return [
|
||||
'issue 64' => ['Fourth', '{"First","Second","Third","Fourth","Fifth","Sixth","Seventh"}, 4'],
|
||||
'issue 64 selecting first "row"' => ['First', '{"First","Second","Third","Fourth","Fifth","Sixth","Seventh"}, 1'],
|
||||
'array result condensed to single value' => [40, '{10,11;20,21;30,31;40,41;50,51;60,61},4'],
|
||||
'both row and column' => [41, '{10,11;20,21;30,31;40,41;50,51;60,61},4,2'],
|
||||
'1*1 array' => ['first', '{"first"},1'],
|
||||
'array expressed in rows' => [20, '{10;20;30;40},2'],
|
||||
'spreadsheet single row' => [11, 'A10:D10,2'],
|
||||
'spreadsheet single column' => [13, 'X10:X13,4'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ return [
|
||||
2,
|
||||
],
|
||||
'Column number omitted from 2-column matrix' => [
|
||||
'#REF!', // Expected
|
||||
'abc', // Expected
|
||||
[
|
||||
['abc', 'def'],
|
||||
['xyz', 'tuv'],
|
||||
|
||||
Reference in New Issue
Block a user