diff --git a/docs/topics/autofilters.md b/docs/topics/autofilters.md
index cd4291f4..d8f37b60 100644
--- a/docs/topics/autofilters.md
+++ b/docs/topics/autofilters.md
@@ -99,6 +99,8 @@ results are unpredictable.
Other filter expression types (such as cell colour filters) are not yet
supported.
+String comparisons in filters are case-insensitive.
+
### Simple filters
In MS Excel, Simple Filters are a dropdown list of all values used in
@@ -113,6 +115,8 @@ will be hidden.
To create a filter expression, we need to start by identifying the
filter type. In this case, we're just going to specify that this filter
is a standard filter.
+*Please note that Excel regards only tests for equal as a standard filter;
+all others, including tests for not equal, must be supplied as custom filters.*
```php
$columnFilter->setFilterType(
@@ -255,6 +259,7 @@ MS Excel uses `*` as a wildcard to match any number of characters, and `?`
as a wildcard to match a single character. `U*` equates to "begins with
a 'U'"; `*U` equates to "ends with a 'U'"; and `*U*` equates to
"contains a 'U'".
+Note that PhpSpreadsheet recognizes wildcards only for equal/not-equal tests.
If you want to match explicitly against `*` or `?`, you can
escape it with a tilde `~`, so `?~**` would explicitly match for `*`
@@ -290,8 +295,8 @@ This defined two rules, filtering numbers that are `>= -20` OR `<=
than OR.
```php
-$columnFilter->setAndOr(
- \PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column::AUTOFILTER_COLUMN_ANDOR_AND
+$columnFilter->setJoin(
+ \PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column::AUTOFILTER_COLUMN_JOIN_AND
);
```
@@ -501,7 +506,7 @@ hiding all other rows within the autofilter area.
### Displaying Filtered Rows
Simply looping through the rows in an autofilter area will still access
-ever row, whether it matches the filter criteria or not. To selectively
+every row, whether it matches the filter criteria or not. To selectively
access only the filtered rows, you need to test each row’s visibility
settings.
diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon
index 4d4b6e1b..bcdba204 100644
--- a/phpstan-baseline.neon
+++ b/phpstan-baseline.neon
@@ -6052,7 +6052,7 @@ parameters:
-
message: "#^Argument of an invalid type mixed supplied for foreach, only iterables are supported\\.$#"
- count: 2
+ count: 1
path: src/PhpSpreadsheet/Worksheet/AutoFilter.php
-
@@ -6065,21 +6065,11 @@ parameters:
count: 1
path: src/PhpSpreadsheet/Worksheet/AutoFilter.php
- -
- message: "#^Cannot access offset 'operator' on mixed\\.$#"
- count: 2
- path: src/PhpSpreadsheet/Worksheet/AutoFilter.php
-
-
message: "#^Cannot access offset 'time' on mixed\\.$#"
count: 1
path: src/PhpSpreadsheet/Worksheet/AutoFilter.php
- -
- message: "#^Cannot access offset 'value' on mixed\\.$#"
- count: 9
- path: src/PhpSpreadsheet/Worksheet/AutoFilter.php
-
-
message: "#^Cannot use array destructuring on mixed\\.$#"
count: 1
@@ -6120,11 +6110,6 @@ parameters:
count: 1
path: src/PhpSpreadsheet/Worksheet/AutoFilter.php
- -
- message: "#^Parameter \\#2 \\$subject of function preg_match expects string, mixed given\\.$#"
- count: 1
- path: src/PhpSpreadsheet/Worksheet/AutoFilter.php
-
-
message: "#^Parameter \\#3 \\$length of function array_slice expects int\\|null, mixed given\\.$#"
count: 1
diff --git a/src/PhpSpreadsheet/Worksheet/AutoFilter.php b/src/PhpSpreadsheet/Worksheet/AutoFilter.php
index 4f857a82..4fad6062 100644
--- a/src/PhpSpreadsheet/Worksheet/AutoFilter.php
+++ b/src/PhpSpreadsheet/Worksheet/AutoFilter.php
@@ -345,6 +345,7 @@ class AutoFilter
*/
private static function filterTestInCustomDataSet($cellValue, $ruleSet)
{
+ /** @var array[] */
$dataSet = $ruleSet['filterRules'];
$join = $ruleSet['join'];
$customRuleForBlanks = $ruleSet['customRuleForBlanks'] ?? false;
@@ -357,38 +358,45 @@ class AutoFilter
}
$returnVal = ($join == AutoFilter\Column::AUTOFILTER_COLUMN_JOIN_AND);
foreach ($dataSet as $rule) {
+ /** @var string */
+ $ruleValue = $rule['value'];
+ /** @var string */
+ $ruleOperator = $rule['operator'];
+ /** @var string */
+ $cellValueString = $cellValue;
$retVal = false;
- if (is_numeric($rule['value'])) {
+ if (is_numeric($ruleValue)) {
// Numeric values are tested using the appropriate operator
- switch ($rule['operator']) {
+ $numericTest = is_numeric($cellValue);
+ switch ($ruleOperator) {
case Rule::AUTOFILTER_COLUMN_RULE_EQUAL:
- $retVal = ($cellValue == $rule['value']);
+ $retVal = $numericTest && ($cellValue == $ruleValue);
break;
case Rule::AUTOFILTER_COLUMN_RULE_NOTEQUAL:
- $retVal = ($cellValue != $rule['value']);
+ $retVal = !$numericTest || ($cellValue != $ruleValue);
break;
case Rule::AUTOFILTER_COLUMN_RULE_GREATERTHAN:
- $retVal = ($cellValue > $rule['value']);
+ $retVal = $numericTest && ($cellValue > $ruleValue);
break;
case Rule::AUTOFILTER_COLUMN_RULE_GREATERTHANOREQUAL:
- $retVal = ($cellValue >= $rule['value']);
+ $retVal = $numericTest && ($cellValue >= $ruleValue);
break;
case Rule::AUTOFILTER_COLUMN_RULE_LESSTHAN:
- $retVal = ($cellValue < $rule['value']);
+ $retVal = $numericTest && ($cellValue < $ruleValue);
break;
case Rule::AUTOFILTER_COLUMN_RULE_LESSTHANOREQUAL:
- $retVal = ($cellValue <= $rule['value']);
+ $retVal = $numericTest && ($cellValue <= $ruleValue);
break;
}
- } elseif ($rule['value'] == '') {
- switch ($rule['operator']) {
+ } elseif ($ruleValue == '') {
+ switch ($ruleOperator) {
case Rule::AUTOFILTER_COLUMN_RULE_EQUAL:
$retVal = (($cellValue == '') || ($cellValue === null));
@@ -404,7 +412,32 @@ class AutoFilter
}
} else {
// String values are always tested for equality, factoring in for wildcards (hence a regexp test)
- $retVal = preg_match('/^' . $rule['value'] . '$/i', $cellValue);
+ switch ($ruleOperator) {
+ case Rule::AUTOFILTER_COLUMN_RULE_EQUAL:
+ $retVal = (bool) preg_match('/^' . $ruleValue . '$/i', $cellValueString);
+
+ break;
+ case Rule::AUTOFILTER_COLUMN_RULE_NOTEQUAL:
+ $retVal = !((bool) preg_match('/^' . $ruleValue . '$/i', $cellValueString));
+
+ break;
+ case Rule::AUTOFILTER_COLUMN_RULE_GREATERTHAN:
+ $retVal = strcasecmp($cellValueString, $ruleValue) > 0;
+
+ break;
+ case Rule::AUTOFILTER_COLUMN_RULE_GREATERTHANOREQUAL:
+ $retVal = strcasecmp($cellValueString, $ruleValue) >= 0;
+
+ break;
+ case Rule::AUTOFILTER_COLUMN_RULE_LESSTHAN:
+ $retVal = strcasecmp($cellValueString, $ruleValue) < 0;
+
+ break;
+ case Rule::AUTOFILTER_COLUMN_RULE_LESSTHANOREQUAL:
+ $retVal = strcasecmp($cellValueString, $ruleValue) <= 0;
+
+ break;
+ }
}
// If there are multiple conditions, then we need to test both using the appropriate join operator
switch ($join) {
@@ -840,7 +873,7 @@ class AutoFilter
break;
case AutoFilter\Column::AUTOFILTER_FILTERTYPE_CUSTOMFILTER:
- $customRuleForBlanks = false;
+ $customRuleForBlanks = true;
$ruleValues = [];
// Build a list of the filter value selections
foreach ($rules as $rule) {
diff --git a/src/PhpSpreadsheet/Worksheet/AutoFilter/Column.php b/src/PhpSpreadsheet/Worksheet/AutoFilter/Column.php
index 48aead7d..ef5396f3 100644
--- a/src/PhpSpreadsheet/Worksheet/AutoFilter/Column.php
+++ b/src/PhpSpreadsheet/Worksheet/AutoFilter/Column.php
@@ -176,6 +176,9 @@ class Column
if (!in_array($filterType, self::$filterTypes)) {
throw new PhpSpreadsheetException('Invalid filter type for column AutoFilter.');
}
+ if ($filterType === self::AUTOFILTER_FILTERTYPE_CUSTOMFILTER && count($this->ruleset) > 2) {
+ throw new PhpSpreadsheetException('No more than 2 rules are allowed in a Custom Filter');
+ }
$this->filterType = $filterType;
@@ -305,6 +308,9 @@ class Column
*/
public function createRule()
{
+ if ($this->filterType === self::AUTOFILTER_FILTERTYPE_CUSTOMFILTER && count($this->ruleset) >= 2) {
+ throw new PhpSpreadsheetException('No more than 2 rules are allowed in a Custom Filter');
+ }
$this->ruleset[] = new Column\Rule($this);
return end($this->ruleset);
diff --git a/src/PhpSpreadsheet/Worksheet/AutoFilter/Column/Rule.php b/src/PhpSpreadsheet/Worksheet/AutoFilter/Column/Rule.php
index 742a7b8a..525b06f6 100644
--- a/src/PhpSpreadsheet/Worksheet/AutoFilter/Column/Rule.php
+++ b/src/PhpSpreadsheet/Worksheet/AutoFilter/Column/Rule.php
@@ -125,15 +125,7 @@ class Rule
self::AUTOFILTER_RULETYPE_DYNAMIC_BELOWAVERAGE,
];
- /*
- * The only valid filter rule operators for filter and customFilter types are:
- *
- *
- *
- *
- *
- *
- */
+ // Filter rule operators for filter and customFilter types.
const AUTOFILTER_COLUMN_RULE_EQUAL = 'equal';
const AUTOFILTER_COLUMN_RULE_NOTEQUAL = 'notEqual';
const AUTOFILTER_COLUMN_RULE_GREATERTHAN = 'greaterThan';
@@ -166,39 +158,17 @@ class Rule
self::AUTOFILTER_COLUMN_RULE_TOPTEN_BOTTOM,
];
- // Rule Operators (Numeric, Boolean etc)
-// const AUTOFILTER_COLUMN_RULE_BETWEEN = 'between'; // greaterThanOrEqual 1 && lessThanOrEqual 2
+ // Unimplented Rule Operators (Numeric, Boolean etc)
+ // const AUTOFILTER_COLUMN_RULE_BETWEEN = 'between'; // greaterThanOrEqual 1 && lessThanOrEqual 2
// Rule Operators (Numeric Special) which are translated to standard numeric operators with calculated values
-// const AUTOFILTER_COLUMN_RULE_TOPTEN = 'topTen'; // greaterThan calculated value
-// const AUTOFILTER_COLUMN_RULE_TOPTENPERCENT = 'topTenPercent'; // greaterThan calculated value
-// const AUTOFILTER_COLUMN_RULE_ABOVEAVERAGE = 'aboveAverage'; // Value is calculated as the average
-// const AUTOFILTER_COLUMN_RULE_BELOWAVERAGE = 'belowAverage'; // Value is calculated as the average
// Rule Operators (String) which are set as wild-carded values
-// const AUTOFILTER_COLUMN_RULE_BEGINSWITH = 'beginsWith'; // A*
-// const AUTOFILTER_COLUMN_RULE_ENDSWITH = 'endsWith'; // *Z
-// const AUTOFILTER_COLUMN_RULE_CONTAINS = 'contains'; // *B*
-// const AUTOFILTER_COLUMN_RULE_DOESNTCONTAIN = 'notEqual'; // notEqual *B*
+ // const AUTOFILTER_COLUMN_RULE_BEGINSWITH = 'beginsWith'; // A*
+ // const AUTOFILTER_COLUMN_RULE_ENDSWITH = 'endsWith'; // *Z
+ // const AUTOFILTER_COLUMN_RULE_CONTAINS = 'contains'; // *B*
+ // const AUTOFILTER_COLUMN_RULE_DOESNTCONTAIN = 'notEqual'; // notEqual *B*
// Rule Operators (Date Special) which are translated to standard numeric operators with calculated values
-// const AUTOFILTER_COLUMN_RULE_BEFORE = 'lessThan';
-// const AUTOFILTER_COLUMN_RULE_AFTER = 'greaterThan';
-// const AUTOFILTER_COLUMN_RULE_YESTERDAY = 'yesterday';
-// const AUTOFILTER_COLUMN_RULE_TODAY = 'today';
-// const AUTOFILTER_COLUMN_RULE_TOMORROW = 'tomorrow';
-// const AUTOFILTER_COLUMN_RULE_LASTWEEK = 'lastWeek';
-// const AUTOFILTER_COLUMN_RULE_THISWEEK = 'thisWeek';
-// const AUTOFILTER_COLUMN_RULE_NEXTWEEK = 'nextWeek';
-// const AUTOFILTER_COLUMN_RULE_LASTMONTH = 'lastMonth';
-// const AUTOFILTER_COLUMN_RULE_THISMONTH = 'thisMonth';
-// const AUTOFILTER_COLUMN_RULE_NEXTMONTH = 'nextMonth';
-// const AUTOFILTER_COLUMN_RULE_LASTQUARTER = 'lastQuarter';
-// const AUTOFILTER_COLUMN_RULE_THISQUARTER = 'thisQuarter';
-// const AUTOFILTER_COLUMN_RULE_NEXTQUARTER = 'nextQuarter';
-// const AUTOFILTER_COLUMN_RULE_LASTYEAR = 'lastYear';
-// const AUTOFILTER_COLUMN_RULE_THISYEAR = 'thisYear';
-// const AUTOFILTER_COLUMN_RULE_NEXTYEAR = 'nextYear';
-// const AUTOFILTER_COLUMN_RULE_YEARTODATE = 'yearToDate'; //
-// const AUTOFILTER_COLUMN_RULE_ALLDATESINMONTH = 'allDatesInMonth'; // for Month/February
-// const AUTOFILTER_COLUMN_RULE_ALLDATESINQUARTER = 'allDatesInQuarter'; // for Quarter 2
+ // const AUTOFILTER_COLUMN_RULE_BEFORE = 'lessThan';
+ // const AUTOFILTER_COLUMN_RULE_AFTER = 'greaterThan';
/**
* Autofilter Column.
diff --git a/tests/PhpSpreadsheetTests/Worksheet/AutoFilter/AutoFilterCustomNumericTest.php b/tests/PhpSpreadsheetTests/Worksheet/AutoFilter/AutoFilterCustomNumericTest.php
new file mode 100644
index 00000000..792e92e9
--- /dev/null
+++ b/tests/PhpSpreadsheetTests/Worksheet/AutoFilter/AutoFilterCustomNumericTest.php
@@ -0,0 +1,210 @@
+getSheet();
+ $sheet->getCell('A1')->setValue('Header');
+ $sheet->getCell('A2')->setValue(1);
+ $sheet->getCell('A3')->setValue(3);
+ $sheet->getCell('A4')->setValue(5);
+ // nothing in cell A5
+ $sheet->getCell('A6')->setValue(7);
+ $sheet->getCell('A7')->setValue(9);
+ $sheet->getCell('A8')->setValue(7);
+ $sheet->getCell('A9')->setValue(5);
+ $sheet->getCell('A10')->setValue(3);
+ $sheet->getCell('A11')->setValue(1);
+ $sheet->getCell('A12')->setValue('x');
+ $this->maxRow = 12;
+
+ return $sheet;
+ }
+
+ public function providerCustomRule(): array
+ {
+ return [
+ 'equal to 3' => [[3, 10], Rule::AUTOFILTER_COLUMN_RULE_EQUAL, 3],
+ 'not equal to 3' => [[2, 4, 5, 6, 7, 8, 9, 11, 12], Rule::AUTOFILTER_COLUMN_RULE_NOTEQUAL, 3],
+ 'greater than 3' => [[4, 6, 7, 8, 9], Rule::AUTOFILTER_COLUMN_RULE_GREATERTHAN, 3],
+ 'greater than or equal to 3' => [[3, 4, 6, 7, 8, 9, 10], Rule::AUTOFILTER_COLUMN_RULE_GREATERTHANOREQUAL, 3],
+ 'less than 3' => [[2, 11], Rule::AUTOFILTER_COLUMN_RULE_LESSTHAN, 3],
+ 'less than or equal to 3' => [[2, 3, 10, 11], Rule::AUTOFILTER_COLUMN_RULE_LESSTHANOREQUAL, 3],
+ ];
+ }
+
+ /**
+ * @dataProvider providerCustomRule
+ */
+ public function testCustomTest(array $expectedVisible, string $rule, int $comparand): void
+ {
+ $sheet = $this->initSheet();
+ $maxRow = $this->maxRow;
+ $autoFilter = $sheet->getAutoFilter();
+ $autoFilter->setRange("A1:A$maxRow");
+ $columnFilter = $autoFilter->getColumn('A');
+ $columnFilter->setFilterType(Column::AUTOFILTER_FILTERTYPE_CUSTOMFILTER);
+ $columnFilter->createRule()
+ ->setRule(
+ $rule,
+ $comparand
+ )
+ ->setRuleType(Rule::AUTOFILTER_RULETYPE_CUSTOMFILTER);
+
+ self::assertEquals($expectedVisible, $this->getVisible());
+ }
+
+ public function testEqualsListSimple(): void
+ {
+ $sheet = $this->initSheet();
+ $maxRow = $this->maxRow;
+ $autoFilter = $sheet->getAutoFilter();
+ $autoFilter->setRange("A1:A$maxRow");
+ $columnFilter = $autoFilter->getColumn('A');
+ $columnFilter->setFilterType(Column::AUTOFILTER_FILTERTYPE_FILTER);
+ $columnFilter->createRule()
+ ->setRule(
+ Rule::AUTOFILTER_COLUMN_RULE_EQUAL,
+ 3
+ )
+ ->setRuleType(Rule::AUTOFILTER_RULETYPE_FILTER);
+ $columnFilter->createRule()
+ ->setRule(
+ Rule::AUTOFILTER_COLUMN_RULE_EQUAL,
+ 5
+ )
+ ->setRuleType(Rule::AUTOFILTER_RULETYPE_FILTER);
+ $columnFilter->createRule()
+ ->setRule(
+ Rule::AUTOFILTER_COLUMN_RULE_EQUAL,
+ 7
+ )
+ ->setRuleType(Rule::AUTOFILTER_RULETYPE_FILTER);
+
+ self::assertEquals([3, 4, 6, 8, 9, 10], $this->getVisible());
+ }
+
+ public function testEqualsList(): void
+ {
+ $sheet = $this->initSheet();
+ $maxRow = $this->maxRow;
+ $autoFilter = $sheet->getAutoFilter();
+ $autoFilter->setRange("A1:A$maxRow");
+ $columnFilter = $autoFilter->getColumn('A');
+ $columnFilter->setFilterType(Column::AUTOFILTER_FILTERTYPE_CUSTOMFILTER);
+ $columnFilter->setJoin(Column::AUTOFILTER_COLUMN_JOIN_OR);
+ $columnFilter->createRule()
+ ->setRule(
+ Rule::AUTOFILTER_COLUMN_RULE_EQUAL,
+ 3
+ )
+ ->setRuleType(Rule::AUTOFILTER_RULETYPE_CUSTOMFILTER);
+ $columnFilter->createRule()
+ ->setRule(
+ Rule::AUTOFILTER_COLUMN_RULE_EQUAL,
+ 5
+ )
+ ->setRuleType(Rule::AUTOFILTER_RULETYPE_CUSTOMFILTER);
+
+ self::assertEquals([3, 4, 9, 10], $this->getVisible());
+ }
+
+ public function testNotEqualsList(): void
+ {
+ $sheet = $this->initSheet();
+ $maxRow = $this->maxRow;
+ $autoFilter = $sheet->getAutoFilter();
+ $autoFilter->setRange("A1:A$maxRow");
+ $columnFilter = $autoFilter->getColumn('A');
+ $columnFilter->setFilterType(Column::AUTOFILTER_FILTERTYPE_CUSTOMFILTER);
+ $columnFilter->setJoin(Column::AUTOFILTER_COLUMN_JOIN_AND);
+ $columnFilter->createRule()
+ ->setRule(
+ Rule::AUTOFILTER_COLUMN_RULE_NOTEQUAL,
+ 3
+ )
+ ->setRuleType(Rule::AUTOFILTER_RULETYPE_CUSTOMFILTER);
+ $columnFilter->createRule()
+ ->setRule(
+ Rule::AUTOFILTER_COLUMN_RULE_NOTEQUAL,
+ 5
+ )
+ ->setRuleType(Rule::AUTOFILTER_RULETYPE_CUSTOMFILTER);
+
+ self::assertEquals([2, 5, 6, 7, 8, 11, 12], $this->getVisible());
+ }
+
+ public function testNotEqualsListWith3Members(): void
+ {
+ $this->expectException(PhpSpreadsheetException::class);
+ $this->expectExceptionMessage('No more than 2 rules');
+ $sheet = $this->initSheet();
+ $maxRow = $this->maxRow;
+ $autoFilter = $sheet->getAutoFilter();
+ $autoFilter->setRange("A1:A$maxRow");
+ $columnFilter = $autoFilter->getColumn('A');
+ $columnFilter->setFilterType(Column::AUTOFILTER_FILTERTYPE_CUSTOMFILTER);
+ $columnFilter->setJoin(Column::AUTOFILTER_COLUMN_JOIN_AND);
+ $columnFilter->createRule()
+ ->setRule(
+ Rule::AUTOFILTER_COLUMN_RULE_NOTEQUAL,
+ 3
+ )
+ ->setRuleType(Rule::AUTOFILTER_RULETYPE_CUSTOMFILTER);
+ $columnFilter->createRule()
+ ->setRule(
+ Rule::AUTOFILTER_COLUMN_RULE_NOTEQUAL,
+ 5
+ )
+ ->setRuleType(Rule::AUTOFILTER_RULETYPE_CUSTOMFILTER);
+ $columnFilter->createRule()
+ ->setRule(
+ Rule::AUTOFILTER_COLUMN_RULE_NOTEQUAL,
+ 7
+ )
+ ->setRuleType(Rule::AUTOFILTER_RULETYPE_CUSTOMFILTER);
+
+ self::assertEquals([2, 5, 7, 11, 12], $this->getVisible());
+ }
+
+ public function testNotEqualsListWith3MembersFilterTypeAfterRules(): void
+ {
+ $this->expectException(PhpSpreadsheetException::class);
+ $this->expectExceptionMessage('No more than 2 rules');
+ $sheet = $this->initSheet();
+ $maxRow = $this->maxRow;
+ $autoFilter = $sheet->getAutoFilter();
+ $autoFilter->setRange("A1:A$maxRow");
+ $columnFilter = $autoFilter->getColumn('A');
+ $columnFilter->setJoin(Column::AUTOFILTER_COLUMN_JOIN_AND);
+ $columnFilter->createRule()
+ ->setRule(
+ Rule::AUTOFILTER_COLUMN_RULE_NOTEQUAL,
+ 3
+ )
+ ->setRuleType(Rule::AUTOFILTER_RULETYPE_CUSTOMFILTER);
+ $columnFilter->createRule()
+ ->setRule(
+ Rule::AUTOFILTER_COLUMN_RULE_NOTEQUAL,
+ 5
+ )
+ ->setRuleType(Rule::AUTOFILTER_RULETYPE_CUSTOMFILTER);
+ $columnFilter->createRule()
+ ->setRule(
+ Rule::AUTOFILTER_COLUMN_RULE_NOTEQUAL,
+ 7
+ )
+ ->setRuleType(Rule::AUTOFILTER_RULETYPE_CUSTOMFILTER);
+ $columnFilter->setFilterType(Column::AUTOFILTER_FILTERTYPE_CUSTOMFILTER);
+
+ self::assertEquals([2, 5, 7, 11, 12], $this->getVisible());
+ }
+}
diff --git a/tests/PhpSpreadsheetTests/Worksheet/AutoFilter/AutoFilterCustomTextTest.php b/tests/PhpSpreadsheetTests/Worksheet/AutoFilter/AutoFilterCustomTextTest.php
index 643ffc0f..da2682d6 100644
--- a/tests/PhpSpreadsheetTests/Worksheet/AutoFilter/AutoFilterCustomTextTest.php
+++ b/tests/PhpSpreadsheetTests/Worksheet/AutoFilter/AutoFilterCustomTextTest.php
@@ -13,7 +13,7 @@ class AutoFilterCustomTextTest extends SetupTeardown
$sheet = $this->getSheet();
$sheet->getCell('A1')->setValue('Header');
$sheet->getCell('A2')->setValue('abc');
- $sheet->getCell('A3')->setValue('cba');
+ $sheet->getCell('A3')->setValue('cBa');
$sheet->getCell('A4')->setValue('cab');
// nothing in cell A5
$sheet->getCell('A6')->setValue('c*b');
@@ -67,7 +67,7 @@ class AutoFilterCustomTextTest extends SetupTeardown
self::assertEquals($expectedVisible, $this->getVisible());
}
- public function testCustomTestNotEqual(): void
+ public function testCustomTestNotEqualBlank(): void
{
$sheet = $this->initSheet();
$maxRow = $this->maxRow;
@@ -85,7 +85,7 @@ class AutoFilterCustomTextTest extends SetupTeardown
self::assertEquals([2, 3, 4, 6, 7, 8, 9, 10, 11, 12], $this->getVisible());
}
- public function testCustomTestGreaterThan(): void
+ public function testCustomTestNotEqualString(): void
{
$sheet = $this->initSheet();
$maxRow = $this->maxRow;
@@ -95,11 +95,118 @@ class AutoFilterCustomTextTest extends SetupTeardown
$columnFilter->setFilterType(Column::AUTOFILTER_FILTERTYPE_CUSTOMFILTER);
$columnFilter->createRule()
->setRule(
- Rule::AUTOFILTER_COLUMN_RULE_GREATERTHAN,
- ''
+ Rule::AUTOFILTER_COLUMN_RULE_NOTEQUAL,
+ 'cba'
)
->setRuleType(Rule::AUTOFILTER_RULETYPE_CUSTOMFILTER);
- self::assertEquals([2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], $this->getVisible());
+ self::assertEquals([2, 4, 5, 6, 7, 8, 9, 10, 11, 12], $this->getVisible());
+ }
+
+ public function testEqualsListSimple(): void
+ {
+ $sheet = $this->initSheet();
+ $maxRow = $this->maxRow;
+ $autoFilter = $sheet->getAutoFilter();
+ $autoFilter->setRange("A1:A$maxRow");
+ $columnFilter = $autoFilter->getColumn('A');
+ $columnFilter->setFilterType(Column::AUTOFILTER_FILTERTYPE_FILTER);
+ $columnFilter->createRule()
+ ->setRule(
+ Rule::AUTOFILTER_COLUMN_RULE_EQUAL,
+ 'c?b' // simple filter - no wildcards
+ )
+ ->setRuleType(Rule::AUTOFILTER_RULETYPE_FILTER);
+ $columnFilter->createRule()
+ ->setRule(
+ Rule::AUTOFILTER_COLUMN_RULE_EQUAL,
+ 'a'
+ )
+ ->setRuleType(Rule::AUTOFILTER_RULETYPE_FILTER);
+
+ self::assertEquals([7, 8], $this->getVisible());
+ }
+
+ public function testEqualsList(): void
+ {
+ $sheet = $this->initSheet();
+ $maxRow = $this->maxRow;
+ $autoFilter = $sheet->getAutoFilter();
+ $autoFilter->setRange("A1:A$maxRow");
+ $columnFilter = $autoFilter->getColumn('A');
+ $columnFilter->setFilterType(Column::AUTOFILTER_FILTERTYPE_CUSTOMFILTER);
+ $columnFilter->setJoin(Column::AUTOFILTER_COLUMN_JOIN_OR);
+ $columnFilter->createRule()
+ ->setRule(
+ Rule::AUTOFILTER_COLUMN_RULE_EQUAL,
+ 'a*'
+ )
+ ->setRuleType(Rule::AUTOFILTER_RULETYPE_CUSTOMFILTER);
+ $columnFilter->createRule()
+ ->setRule(
+ Rule::AUTOFILTER_COLUMN_RULE_EQUAL,
+ '*c*'
+ )
+ ->setRuleType(Rule::AUTOFILTER_RULETYPE_CUSTOMFILTER);
+
+ self::assertEquals([2, 3, 4, 6, 7, 8, 9, 10], $this->getVisible());
+ }
+
+ public function testNotEqualsList(): void
+ {
+ $sheet = $this->initSheet();
+ $maxRow = $this->maxRow;
+ $autoFilter = $sheet->getAutoFilter();
+ $autoFilter->setRange("A1:A$maxRow");
+ $columnFilter = $autoFilter->getColumn('A');
+ $columnFilter->setFilterType(Column::AUTOFILTER_FILTERTYPE_CUSTOMFILTER);
+ $columnFilter->setJoin(Column::AUTOFILTER_COLUMN_JOIN_AND);
+ $columnFilter->createRule()
+ ->setRule(
+ Rule::AUTOFILTER_COLUMN_RULE_NOTEQUAL,
+ 'a*'
+ )
+ ->setRuleType(Rule::AUTOFILTER_RULETYPE_CUSTOMFILTER);
+ $columnFilter->createRule()
+ ->setRule(
+ Rule::AUTOFILTER_COLUMN_RULE_NOTEQUAL,
+ '*c*'
+ )
+ ->setRuleType(Rule::AUTOFILTER_RULETYPE_CUSTOMFILTER);
+
+ self::assertEquals([5, 11, 12], $this->getVisible());
+ }
+
+ public function providerCustomRule(): array
+ {
+ return [
+ 'equal to cba' => [[3], Rule::AUTOFILTER_COLUMN_RULE_EQUAL, 'cba'],
+ 'not equal to cba' => [[2, 4, 5, 6, 7, 8, 9, 10, 11, 12], Rule::AUTOFILTER_COLUMN_RULE_NOTEQUAL, 'cba'],
+ 'greater than cba' => [[9, 10, 11, 12], Rule::AUTOFILTER_COLUMN_RULE_GREATERTHAN, 'cba'],
+ 'greater than or equal to cba' => [[3, 9, 10, 11, 12], Rule::AUTOFILTER_COLUMN_RULE_GREATERTHANOREQUAL, 'cba'],
+ 'less than cba' => [[2, 4, 5, 6, 7, 8], Rule::AUTOFILTER_COLUMN_RULE_LESSTHAN, 'cba'],
+ 'less than or equal to cba' => [[2, 3, 4, 5, 6, 7, 8], Rule::AUTOFILTER_COLUMN_RULE_LESSTHANOREQUAL, 'cba'],
+ ];
+ }
+
+ /**
+ * @dataProvider providerCustomRule
+ */
+ public function testCustomRuleTest(array $expectedVisible, string $rule, string $comparand): void
+ {
+ $sheet = $this->initSheet();
+ $maxRow = $this->maxRow;
+ $autoFilter = $sheet->getAutoFilter();
+ $autoFilter->setRange("A1:A$maxRow");
+ $columnFilter = $autoFilter->getColumn('A');
+ $columnFilter->setFilterType(Column::AUTOFILTER_FILTERTYPE_CUSTOMFILTER);
+ $columnFilter->createRule()
+ ->setRule(
+ $rule,
+ $comparand
+ )
+ ->setRuleType(Rule::AUTOFILTER_RULETYPE_CUSTOMFILTER);
+
+ self::assertEquals($expectedVisible, $this->getVisible());
}
}