Skip to content

Commit d27b6a6

Browse files
authored
Cleanup 3 LookupRef Tests (#3097)
Scrutinizer had previously suggested annotations for 3 LookupRef tests, but it no longer accepts its own annotation for those cases. This PR cleans them up. ColumnsTest and RowsTest are extremely straightforward. IndexTest is a bit more complicated, but only because, unlike the other two, it had no test which executed in the context of a spreadsheet. And, when I added those, I discovered a couple of bugs. INDEX always requires at least 2 parameters (row# is always required), but its entry in the function table specified 1-4 parameters, now changed to 2-4. And, omitting col# is not handled the same way as specifying 0 for col#, though the code had treated them identically. (The same would have been true for row# but, because it is now required, ...)
1 parent 35b42cc commit d27b6a6

File tree

7 files changed

+297
-9
lines changed

7 files changed

+297
-9
lines changed

src/PhpSpreadsheet/Calculation/Calculation.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1450,7 +1450,7 @@ class Calculation
14501450
'INDEX' => [
14511451
'category' => Category::CATEGORY_LOOKUP_AND_REFERENCE,
14521452
'functionCall' => [LookupRef\Matrix::class, 'index'],
1453-
'argumentCount' => '1-4',
1453+
'argumentCount' => '2-4',
14541454
],
14551455
'INDIRECT' => [
14561456
'category' => Category::CATEGORY_LOOKUP_AND_REFERENCE,

src/PhpSpreadsheet/Calculation/LookupRef/Matrix.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,14 @@ public static function transpose($matrixData)
7676
* If an array of values is passed as the $rowNum and/or $columnNum arguments, then the returned result
7777
* will also be an array with the same dimensions
7878
*/
79-
public static function index($matrix, $rowNum = 0, $columnNum = 0)
79+
public static function index($matrix, $rowNum = 0, $columnNum = null)
8080
{
8181
if (is_array($rowNum) || is_array($columnNum)) {
8282
return self::evaluateArrayArgumentsSubsetFrom([self::class, __FUNCTION__], 1, $matrix, $rowNum, $columnNum);
8383
}
8484

8585
$rowNum = $rowNum ?? 0;
86+
$originalColumnNum = $columnNum;
8687
$columnNum = $columnNum ?? 0;
8788

8889
try {
@@ -102,6 +103,9 @@ public static function index($matrix, $rowNum = 0, $columnNum = 0)
102103
if ($columnNum > count($columnKeys)) {
103104
return ExcelError::REF();
104105
}
106+
if ($originalColumnNum === null && 1 < count($columnKeys)) {
107+
return ExcelError::REF();
108+
}
105109

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

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@ class ColumnsTest extends TestCase
1212
* @dataProvider providerCOLUMNS
1313
*
1414
* @param mixed $expectedResult
15+
* @param null|array|string $arg
1516
*/
16-
public function testCOLUMNS($expectedResult, ...$args): void
17+
public function testCOLUMNS($expectedResult, $arg): void
1718
{
18-
$result = LookupRef::COLUMNS(/** @scrutinizer ignore-type */ ...$args);
19+
$result = LookupRef::COLUMNS($arg);
1920
self::assertEquals($expectedResult, $result);
2021
}
2122

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\LookupRef;
4+
5+
class IndexOnSpreadsheetTest extends AllSetupTeardown
6+
{
7+
/**
8+
* @dataProvider providerINDEXonSpreadsheet
9+
*
10+
* @param mixed $expectedResult
11+
* @param null|int|string $rowNum
12+
* @param null|int|string $colNum
13+
*/
14+
public function testIndexOnSpreadsheet($expectedResult, array $matrix, $rowNum = null, $colNum = null): void
15+
{
16+
$this->mightHaveException($expectedResult);
17+
$sheet = $this->getSheet();
18+
$sheet->fromArray($matrix);
19+
$maxRow = $sheet->getHighestRow();
20+
$maxColumn = $sheet->getHighestColumn();
21+
$formulaArray = "A1:$maxColumn$maxRow";
22+
if ($rowNum === null) {
23+
$formula = "=INDEX($formulaArray)";
24+
} elseif ($colNum === null) {
25+
$formula = "=INDEX($formulaArray, $rowNum)";
26+
} else {
27+
$formula = "=INDEX($formulaArray, $rowNum, $colNum)";
28+
}
29+
$sheet->getCell('ZZ98')->setValue('x');
30+
$sheet->getCell('ZZ99')->setValue($formula);
31+
$result = $sheet->getCell('ZZ99')->getCalculatedValue();
32+
self::assertEquals($expectedResult, $result);
33+
}
34+
35+
public function providerINDEXonSpreadsheet(): array
36+
{
37+
return require 'tests/data/Calculation/LookupRef/INDEXonSpreadsheet.php';
38+
}
39+
}

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

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\LookupRef;
44

55
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
6-
use PhpOffice\PhpSpreadsheet\Calculation\LookupRef;
6+
use PhpOffice\PhpSpreadsheet\Calculation\LookupRef\Matrix;
77
use PHPUnit\Framework\TestCase;
88

99
class IndexTest extends TestCase
@@ -12,10 +12,19 @@ class IndexTest extends TestCase
1212
* @dataProvider providerINDEX
1313
*
1414
* @param mixed $expectedResult
15+
* @param mixed $matrix
16+
* @param mixed $rowNum
17+
* @param mixed $colNum
1518
*/
16-
public function testINDEX($expectedResult, ...$args): void
19+
public function testINDEX($expectedResult, $matrix, $rowNum = null, $colNum = null): void
1720
{
18-
$result = LookupRef::INDEX(/** @scrutinizer ignore-type */ ...$args);
21+
if ($rowNum === null) {
22+
$result = Matrix::index($matrix);
23+
} elseif ($colNum === null) {
24+
$result = Matrix::index($matrix, $rowNum);
25+
} else {
26+
$result = Matrix::index($matrix, $rowNum, $colNum);
27+
}
1928
self::assertEquals($expectedResult, $result);
2029
}
2130

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@ class RowsTest extends TestCase
1212
* @dataProvider providerROWS
1313
*
1414
* @param mixed $expectedResult
15+
* @param null|array|string $arg
1516
*/
16-
public function testROWS($expectedResult, ...$args): void
17+
public function testROWS($expectedResult, $arg): void
1718
{
18-
$result = LookupRef::ROWS(/** @scrutinizer ignore-type */ ...$args);
19+
$result = LookupRef::ROWS($arg);
1920
self::assertEquals($expectedResult, $result);
2021
}
2122

Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
<?php
2+
3+
return [
4+
'Single Cell' => [
5+
1, // Expected
6+
[
7+
[1],
8+
],
9+
0,
10+
],
11+
'Row Number omitted' => [
12+
'exception', // Expected
13+
[
14+
[1],
15+
],
16+
],
17+
'Negative Row' => [
18+
'#VALUE!', // Expected
19+
[
20+
[1],
21+
[2],
22+
],
23+
-1,
24+
],
25+
'Row > matrix rows' => [
26+
'#REF!', // Expected
27+
[
28+
[1],
29+
[2],
30+
],
31+
10,
32+
],
33+
'Row is not a number' => [
34+
'#NAME?', // Expected
35+
[
36+
[1],
37+
[2],
38+
],
39+
'NaN',
40+
],
41+
'Row is reference to non-number' => [
42+
'#VALUE!', // Expected
43+
[
44+
[1],
45+
[2],
46+
],
47+
'ZZ98',
48+
],
49+
'Row is quoted non-numeric result' => [
50+
'#VALUE!', // Expected
51+
[
52+
[1],
53+
[2],
54+
],
55+
'"string"',
56+
],
57+
'Row is Error' => [
58+
'#N/A', // Expected
59+
[
60+
[1],
61+
[2],
62+
],
63+
'#N/A',
64+
],
65+
'Return row 2 only one column' => [
66+
'xyz', // Expected
67+
[
68+
['abc'],
69+
['xyz'],
70+
],
71+
2,
72+
],
73+
'Return row 1 col 2' => [
74+
'def', // Expected
75+
[
76+
['abc', 'def'],
77+
['xyz', 'tuv'],
78+
],
79+
1,
80+
2,
81+
],
82+
'Column number omitted from 2-column matrix' => [
83+
'#REF!', // Expected
84+
[
85+
['abc', 'def'],
86+
['xyz', 'tuv'],
87+
],
88+
1,
89+
],
90+
'Column number omitted from 1-column matrix' => [
91+
'xyz', // Expected
92+
[
93+
['abc'],
94+
['xyz'],
95+
],
96+
2,
97+
],
98+
'Return row 2 from larger matrix (Phpspreadsheet flattens expected [2,4] to single value)' => [
99+
2, // Expected
100+
// Input
101+
[
102+
[1, 3],
103+
[2, 4],
104+
],
105+
2,
106+
0,
107+
],
108+
'Negative Column' => [
109+
'#VALUE!', // Expected
110+
[
111+
[1, 3],
112+
[2, 4],
113+
],
114+
0,
115+
-1,
116+
],
117+
'Column > matrix columns' => [
118+
'#REF!', // Expected
119+
[
120+
[1, 3],
121+
[2, 4],
122+
],
123+
2,
124+
10,
125+
],
126+
'Column is not a number' => [
127+
'#NAME?', // Expected
128+
[
129+
[1],
130+
[2],
131+
],
132+
1,
133+
'NaN',
134+
],
135+
'Column is reference to non-number' => [
136+
'#VALUE!', // Expected
137+
[
138+
[1],
139+
[2],
140+
],
141+
1,
142+
'ZZ98',
143+
],
144+
'Column is quoted non-number' => [
145+
'#VALUE!', // Expected
146+
[
147+
[1],
148+
[2],
149+
],
150+
1,
151+
'"string"',
152+
],
153+
'Column is Error' => [
154+
'#N/A', // Expected
155+
[
156+
[1],
157+
[2],
158+
],
159+
1,
160+
'#N/A',
161+
],
162+
'Row 2 Column 2' => [
163+
4, // Expected
164+
[
165+
[1, 3],
166+
[2, 4],
167+
],
168+
2,
169+
2,
170+
],
171+
'Row 2 Column 2 Alphabetic' => [
172+
'Pears',
173+
[
174+
['Apples', 'Lemons'],
175+
['Bananas', 'Pears'],
176+
],
177+
2,
178+
2,
179+
],
180+
'Row 2 Column 1 Alphabetic' => [
181+
'Bananas',
182+
[
183+
['Apples', 'Lemons'],
184+
['Bananas', 'Pears'],
185+
],
186+
2,
187+
1,
188+
],
189+
'Row 2 Column 0 (PhpSpreadsheet flattens result)' => [
190+
'Bananas',
191+
[
192+
['Apples', 'Lemons'],
193+
['Bananas', 'Pears'],
194+
],
195+
2,
196+
0,
197+
],
198+
'Row 5 column 2' => [
199+
3,
200+
[
201+
[4, 6],
202+
[5, 3],
203+
[6, 9],
204+
[7, 5],
205+
[8, 3],
206+
],
207+
5,
208+
2,
209+
],
210+
'Row 5 column 0 (flattened)' => [
211+
8,
212+
[
213+
[4, 6],
214+
[5, 3],
215+
[6, 9],
216+
[7, 5],
217+
[8, 3],
218+
],
219+
5,
220+
0,
221+
],
222+
'Row 0 column 2 (flattened)' => [
223+
6,
224+
[
225+
[4, 6],
226+
[5, 3],
227+
[6, 9],
228+
[7, 5],
229+
[8, 3],
230+
],
231+
0,
232+
2,
233+
],
234+
];

0 commit comments

Comments
 (0)