AutoFilter Improvements (#2393)
* AutoFilter Improvements Fix issue #2378. The following changes are made: - NotEqual tests must be part of a custom filter. Documentation has been changed to indicate that. - Method setAndOr was replaced by setJoin some time ago. Documentation now reflects that change. - Documentation to indicate that string filters are not case-sensitive, same as in Excel. - Filters testing against numeric value now include a numeric test (not numeric for not equal, numeric for all others). - String filter had previously treated everything as a test for "equal". It now handles "not equal" and the variants of "greater/less" with or without "equal". - Documentation correctly stated that no more than 2 rules are allowed in a custom filter. Code did not enforce this restriction. It now does, throwing an exception if an attempt is made to add a third rule. - Deleted a lot of comments in Rule.php to make it easier to see what is not yet implemented (between, begins with, etc.). I may take these on in future. - Added a number of tests for the new functionality. * Not Sure Why Phpstan Results Differ Local vs Github Let's see if this change suffices. * Phpstan Still Not sure how to convince it. Let's try this. * Phpstan Solved Figured out the problem on my local machine. Expect this to work.
This commit is contained in:
parent
52585a9d7c
commit
2a12587f05
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -125,15 +125,7 @@ class Rule
|
|||
self::AUTOFILTER_RULETYPE_DYNAMIC_BELOWAVERAGE,
|
||||
];
|
||||
|
||||
/*
|
||||
* The only valid filter rule operators for filter and customFilter types are:
|
||||
* <xsd:enumeration value="equal"/>
|
||||
* <xsd:enumeration value="lessThan"/>
|
||||
* <xsd:enumeration value="lessThanOrEqual"/>
|
||||
* <xsd:enumeration value="notEqual"/>
|
||||
* <xsd:enumeration value="greaterThanOrEqual"/>
|
||||
* <xsd:enumeration value="greaterThan"/>
|
||||
*/
|
||||
// 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'; // <dynamicFilter val="40909" type="yearToDate" maxVal="41113"/>
|
||||
// const AUTOFILTER_COLUMN_RULE_ALLDATESINMONTH = 'allDatesInMonth'; // <dynamicFilter type="M2"/> for Month/February
|
||||
// const AUTOFILTER_COLUMN_RULE_ALLDATESINQUARTER = 'allDatesInQuarter'; // <dynamicFilter type="Q2"/> for Quarter 2
|
||||
// const AUTOFILTER_COLUMN_RULE_BEFORE = 'lessThan';
|
||||
// const AUTOFILTER_COLUMN_RULE_AFTER = 'greaterThan';
|
||||
|
||||
/**
|
||||
* Autofilter Column.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,210 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Worksheet\AutoFilter;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||
|
||||
class AutoFilterCustomNumericTest extends SetupTeardown
|
||||
{
|
||||
public function initsheet(): Worksheet
|
||||
{
|
||||
$sheet = $this->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());
|
||||
}
|
||||
}
|
||||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue