Skip to content

Commit 5c643a8

Browse files
authored
Merge pull request #4491 from oleibman/filterparm
Minor Changes to FILTER Function
2 parents df3a069 + 347980a commit 5c643a8

File tree

3 files changed

+157
-4
lines changed

3 files changed

+157
-4
lines changed

src/PhpSpreadsheet/Calculation/Calculation.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
use ReflectionMethod;
2323
use ReflectionParameter;
2424
use Throwable;
25+
use TypeError;
2526

2627
class Calculation extends CalculationLocale
2728
{
@@ -2150,8 +2151,14 @@ private function processTokenStack(false|array $tokens, ?string $cellID = null,
21502151
}
21512152

21522153
/** @var callable $functionCall */
2153-
$result = call_user_func_array($functionCall, $args);
2154-
2154+
try {
2155+
$result = call_user_func_array($functionCall, $args);
2156+
} catch (TypeError $e) {
2157+
if (!$this->suppressFormulaErrors) {
2158+
throw $e;
2159+
}
2160+
$result = false;
2161+
}
21552162
if ($functionName !== 'MKMATRIX') {
21562163
$this->debugLog->writeDebugLog('Evaluation Result for %s() function call is %s', self::localeFunc($functionName), $this->showTypeDetails($result));
21572164
}

src/PhpSpreadsheet/Calculation/LookupRef/Filter.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,12 @@
66

77
class Filter
88
{
9-
/** @param mixed[] $lookupArray */
10-
public static function filter(array $lookupArray, mixed $matchArray, mixed $ifEmpty = null): mixed
9+
public static function filter(mixed $lookupArray, mixed $matchArray, mixed $ifEmpty = null): mixed
1110
{
11+
if (!is_array($lookupArray)) {
12+
return ExcelError::VALUE();
13+
}
14+
/** @var mixed[] $lookupArray */
1215
if (!is_array($matchArray)) {
1316
return ExcelError::VALUE();
1417
}
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\LookupRef;
6+
7+
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
8+
use PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError;
9+
use PhpOffice\PhpSpreadsheet\Spreadsheet;
10+
use PHPUnit\Framework\TestCase;
11+
12+
class FilterOnSpreadsheetTest extends TestCase
13+
{
14+
public function testFilterByRow(): void
15+
{
16+
$spreadsheet = new Spreadsheet();
17+
Calculation::getInstance($spreadsheet)
18+
->setInstanceArrayReturnType(
19+
Calculation::RETURN_ARRAY_AS_ARRAY
20+
);
21+
$sheet = $spreadsheet->getActiveSheet();
22+
$criteria = [[true], [false], [false], [false], [true], [false], [false], [false], [false], [false], [false], [true], [false], [false], [false], [true]];
23+
$sheet->fromArray($criteria, null, 'A1', true);
24+
$sheet->fromArray($this->sampleDataForRow(), null, 'C1', true);
25+
$sheet->getCell('H1')->setValue('=FILTER(C1:F16, A1:A16)');
26+
$expectedResult = [
27+
['East', 'Tom', 'Apple', 6830],
28+
['East', 'Fritz', 'Apple', 4394],
29+
['South', 'Sal', 'Apple', 1310],
30+
['South', 'Hector', 'Apple', 8144],
31+
];
32+
$result = $sheet->getCell('H1')->getCalculatedValue();
33+
self::assertSame($expectedResult, $result);
34+
$spreadsheet->disconnectWorksheets();
35+
}
36+
37+
public function testFilterByColumn(): void
38+
{
39+
$spreadsheet = new Spreadsheet();
40+
Calculation::getInstance($spreadsheet)
41+
->setInstanceArrayReturnType(
42+
Calculation::RETURN_ARRAY_AS_ARRAY
43+
);
44+
$sheet = $spreadsheet->getActiveSheet();
45+
$criteria = [[false, false, true, false, true, false, false, false, true, true]];
46+
$sheet->fromArray($criteria, null, 'A1', true);
47+
$sheet->fromArray($this->sampleDataForColumn(), null, 'A3', true);
48+
$sheet->getCell('A8')->setValue('=FILTER(A3:J5, A1:J1)');
49+
$expectedResult = [
50+
['Betty', 'Charlotte', 'Oliver', 'Zoe'],
51+
['B', 'B', 'B', 'B'],
52+
[1, 2, 4, 8],
53+
];
54+
$result = $sheet->getCell('A8')->getCalculatedValue();
55+
self::assertSame($expectedResult, $result);
56+
$spreadsheet->disconnectWorksheets();
57+
}
58+
59+
public function testFilterInvalidMatchArray(): void
60+
{
61+
$spreadsheet = new Spreadsheet();
62+
Calculation::getInstance($spreadsheet)
63+
->setInstanceArrayReturnType(
64+
Calculation::RETURN_ARRAY_AS_ARRAY
65+
);
66+
$sheet = $spreadsheet->getActiveSheet();
67+
$sheet->fromArray($this->sampleDataForColumn(), null, 'A3', true);
68+
$sheet->getCell('A12')->setValue('=FILTER(A3:J5, "INVALID")');
69+
$expectedResult = ExcelError::VALUE();
70+
$result = $sheet->getCell('A12')->getCalculatedValue();
71+
self::assertSame($expectedResult, $result);
72+
$spreadsheet->disconnectWorksheets();
73+
}
74+
75+
public function testFilterInvalidLookupArray(): void
76+
{
77+
$spreadsheet = new Spreadsheet();
78+
Calculation::getInstance($spreadsheet)
79+
->setInstanceArrayReturnType(
80+
Calculation::RETURN_ARRAY_AS_ARRAY
81+
);
82+
$sheet = $spreadsheet->getActiveSheet();
83+
$criteria = [[false, false, true, false, true, false, false, false, true, true]];
84+
$sheet->fromArray($criteria, null, 'A1', true);
85+
$sheet->fromArray($this->sampleDataForColumn(), null, 'A3', true);
86+
$sheet->getCell('A14')->setValue('=FILTER("invalid", A1:J1)');
87+
$expectedResult = ExcelError::VALUE();
88+
$result = $sheet->getCell('A14')->getCalculatedValue();
89+
self::assertSame($expectedResult, $result);
90+
$spreadsheet->disconnectWorksheets();
91+
}
92+
93+
public function testFilterEmpty(): void
94+
{
95+
$spreadsheet = new Spreadsheet();
96+
Calculation::getInstance($spreadsheet)
97+
->setInstanceArrayReturnType(
98+
Calculation::RETURN_ARRAY_AS_ARRAY
99+
);
100+
$sheet = $spreadsheet->getActiveSheet();
101+
$criteria = [[false, false, true, false, true, false, false, false, true, true]];
102+
$sheet->fromArray($criteria, null, 'A1', true);
103+
$sheet->fromArray($this->sampleDataForColumn(), null, 'A3', true);
104+
$sheet->getCell('A16')->setValue('=FILTER(A3:B5, A1:B1)');
105+
$expectedResult = ExcelError::CALC();
106+
$result = $sheet->getCell('A16')->getCalculatedValue();
107+
self::assertSame($expectedResult, $result);
108+
$spreadsheet->disconnectWorksheets();
109+
}
110+
111+
/** @return array<array{string, string, string, int}> */
112+
protected function sampleDataForRow(): array
113+
{
114+
return [
115+
['East', 'Tom', 'Apple', 6830],
116+
['West', 'Fred', 'Grape', 5619],
117+
['North', 'Amy', 'Pear', 4565],
118+
['South', 'Sal', 'Banana', 5323],
119+
['East', 'Fritz', 'Apple', 4394],
120+
['West', 'Sravan', 'Grape', 7195],
121+
['North', 'Xi', 'Pear', 5231],
122+
['South', 'Hector', 'Banana', 2427],
123+
['East', 'Tom', 'Banana', 4213],
124+
['West', 'Fred', 'Pear', 3239],
125+
['North', 'Amy', 'Grape', 6420],
126+
['South', 'Sal', 'Apple', 1310],
127+
['East', 'Fritz', 'Banana', 6274],
128+
['West', 'Sravan', 'Pear', 4894],
129+
['North', 'Xi', 'Grape', 7580],
130+
['South', 'Hector', 'Apple', 8144],
131+
];
132+
}
133+
134+
/** @return array<array<int|string>> */
135+
protected function sampleDataForColumn(): array
136+
{
137+
return [
138+
['Aiden', 'Andrew', 'Betty', 'Caden', 'Charlotte', 'Emma', 'Isabella', 'Mason', 'Oliver', 'Zoe'],
139+
['A', 'C', 'B', 'A', 'B', 'C', 'A', 'A', 'B', 'B'],
140+
[0, 4, 1, 2, 2, 0, 2, 4, 4, 8],
141+
];
142+
}
143+
}

0 commit comments

Comments
 (0)