Merge pull request #2141 from oleibman/moredatefilter
Autofilter Part 1
This commit is contained in:
commit
55b95201ab
|
|
@ -327,14 +327,14 @@ $columnFilter->setFilterType(
|
|||
```
|
||||
|
||||
When defining the rule for a dynamic filter, we don't define a value (we
|
||||
can simply set that to NULL) but we do specify the dynamic filter
|
||||
can simply set that to null string) but we do specify the dynamic filter
|
||||
category.
|
||||
|
||||
```php
|
||||
$columnFilter->createRule()
|
||||
->setRule(
|
||||
\PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_EQUAL,
|
||||
NULL,
|
||||
'',
|
||||
\PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DYNAMIC_YEARTODATE
|
||||
)
|
||||
->setRuleType(
|
||||
|
|
|
|||
|
|
@ -5392,7 +5392,7 @@ parameters:
|
|||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$excelTimestamp of static method PhpOffice\\\\PhpSpreadsheet\\\\Shared\\\\Date\\:\\:excelToTimestamp\\(\\) expects float\\|int, float\\|int\\|string given\\.$#"
|
||||
count: 2
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Worksheet/AutoFilter.php
|
||||
|
||||
-
|
||||
|
|
@ -5405,36 +5405,6 @@ parameters:
|
|||
count: 1
|
||||
path: src/PhpSpreadsheet/Worksheet/AutoFilter.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$now of function strtotime expects int, int\\|false given\\.$#"
|
||||
count: 6
|
||||
path: src/PhpSpreadsheet/Worksheet/AutoFilter.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#5 \\$day of function gmmktime expects int, string given\\.$#"
|
||||
count: 8
|
||||
path: src/PhpSpreadsheet/Worksheet/AutoFilter.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#6 \\$year of function gmmktime expects int, string given\\.$#"
|
||||
count: 13
|
||||
path: src/PhpSpreadsheet/Worksheet/AutoFilter.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#4 \\$mon of function gmmktime expects int, string given\\.$#"
|
||||
count: 2
|
||||
path: src/PhpSpreadsheet/Worksheet/AutoFilter.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#5 \\$day of function gmmktime expects int, float given\\.$#"
|
||||
count: 2
|
||||
path: src/PhpSpreadsheet/Worksheet/AutoFilter.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$attributes of method PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\AutoFilter\\\\Column\\:\\:setAttributes\\(\\) expects array\\<string\\>, array\\<string, float\\|int\\|null\\> given\\.$#"
|
||||
count: 1
|
||||
path: src/PhpSpreadsheet/Worksheet/AutoFilter.php
|
||||
|
||||
-
|
||||
message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\AutoFilter\\:\\:calculateTopTenValue\\(\\) has no return typehint specified\\.$#"
|
||||
count: 1
|
||||
|
|
@ -7415,21 +7385,11 @@ parameters:
|
|||
count: 1
|
||||
path: tests/PhpSpreadsheetTests/Worksheet/AutoFilter/Column/RuleTest.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$attributes of method PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\AutoFilter\\\\Column\\:\\:setAttributes\\(\\) expects array\\<string\\>, array\\<string, int\\> given\\.$#"
|
||||
count: 3
|
||||
path: tests/PhpSpreadsheetTests/Worksheet/AutoFilter/ColumnTest.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$pValue of method PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\AutoFilter\\\\Column\\:\\:setAttribute\\(\\) expects string, int given\\.$#"
|
||||
count: 1
|
||||
path: tests/PhpSpreadsheetTests/Worksheet/AutoFilter/ColumnTest.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$pColumn of method PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\AutoFilter\\:\\:setColumn\\(\\) expects PhpOffice\\\\PhpSpreadsheet\\\\Worksheet\\\\AutoFilter\\\\Column\\|string, float given\\.$#"
|
||||
count: 1
|
||||
path: tests/PhpSpreadsheetTests/Worksheet/AutoFilterTest.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$im of function imagecolorallocate expects resource, resource\\|false given\\.$#"
|
||||
count: 1
|
||||
|
|
|
|||
|
|
@ -0,0 +1,100 @@
|
|||
<?php
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule;
|
||||
|
||||
require __DIR__ . '/../Header.php';
|
||||
|
||||
// Sample can be slightly off if processing begins just before midnight
|
||||
// and does not complete till after midnight.
|
||||
// This possibility is accounted for in unit tests,
|
||||
// but seems unneccesarily complicated for the sample.
|
||||
|
||||
function createSheet(Spreadsheet $spreadsheet, string $rule): void
|
||||
{
|
||||
$sheet = $spreadsheet->createSheet();
|
||||
$sheet->setTitle($rule);
|
||||
$sheet->getCell('A1')->setValue('Date');
|
||||
$row = 1;
|
||||
$date = new DateTime();
|
||||
$year = (int) $date->format('Y');
|
||||
$month = (int) $date->format('m');
|
||||
$day = (int) $date->format('d');
|
||||
$yearMinus2 = $year - 2;
|
||||
$sheet->getCell('B1')->setValue("=DATE($year, $month, $day)");
|
||||
// Each day for two weeks before today through 2 weeks after
|
||||
for ($dayOffset = -14; $dayOffset < 14; ++$dayOffset) {
|
||||
++$row;
|
||||
$sheet->getCell("A$row")->setValue("=B1+($dayOffset)");
|
||||
}
|
||||
// First and last day of each month, starting with January 2 years before,
|
||||
// through December 2 years after.
|
||||
for ($monthOffset = 0; $monthOffset < 48; ++$monthOffset) {
|
||||
++$row;
|
||||
$sheet->getCell("A$row")->setValue("=DATE($yearMinus2, $monthOffset, 1)");
|
||||
++$row;
|
||||
$sheet->getCell("A$row")->setValue("=DATE($yearMinus2, $monthOffset + 1, 0)");
|
||||
}
|
||||
$sheet->getStyle("A2:A$row")->getNumberFormat()->setFormatCode('yyyy-mm-dd');
|
||||
$sheet->getStyle('B1')->getNumberFormat()->setFormatCode('yyyy-mm-dd');
|
||||
$sheet->getColumnDimension('A')->setAutoSize(true);
|
||||
$sheet->getColumnDimension('B')->setAutoSize(true);
|
||||
$autoFilter = $spreadsheet->getActiveSheet()->getAutoFilter();
|
||||
$autoFilter->setRange("A1:A$row");
|
||||
$columnFilter = $autoFilter->getColumn('A');
|
||||
$columnFilter->setFilterType(Column::AUTOFILTER_FILTERTYPE_DYNAMICFILTER);
|
||||
$columnFilter->createRule()
|
||||
->setRule(
|
||||
Rule::AUTOFILTER_COLUMN_RULE_EQUAL,
|
||||
'',
|
||||
$rule
|
||||
)
|
||||
->setRuleType(Rule::AUTOFILTER_RULETYPE_DYNAMICFILTER);
|
||||
$sheet->setSelectedCell('B1');
|
||||
}
|
||||
|
||||
// Create new Spreadsheet object
|
||||
$helper->log('Create new Spreadsheet object');
|
||||
$spreadsheet = new Spreadsheet();
|
||||
|
||||
// Set document properties
|
||||
$helper->log('Set document properties');
|
||||
$spreadsheet->getProperties()->setCreator('Owen Leibman')
|
||||
->setLastModifiedBy('Owen Leibman')
|
||||
->setTitle('PhpSpreadsheet Test Document')
|
||||
->setSubject('PhpSpreadsheet Test Document')
|
||||
->setDescription('Test document for PhpSpreadsheet, generated using PHP classes.')
|
||||
->setKeywords('office PhpSpreadsheet php')
|
||||
->setCategory('Test result file');
|
||||
|
||||
$ruleNames = [
|
||||
Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTMONTH,
|
||||
Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTQUARTER,
|
||||
Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTWEEK,
|
||||
Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTYEAR,
|
||||
Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTMONTH,
|
||||
Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTQUARTER,
|
||||
Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTWEEK,
|
||||
Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTYEAR,
|
||||
Rule::AUTOFILTER_RULETYPE_DYNAMIC_THISMONTH,
|
||||
Rule::AUTOFILTER_RULETYPE_DYNAMIC_THISQUARTER,
|
||||
Rule::AUTOFILTER_RULETYPE_DYNAMIC_THISWEEK,
|
||||
Rule::AUTOFILTER_RULETYPE_DYNAMIC_THISYEAR,
|
||||
Rule::AUTOFILTER_RULETYPE_DYNAMIC_TODAY,
|
||||
Rule::AUTOFILTER_RULETYPE_DYNAMIC_TOMORROW,
|
||||
Rule::AUTOFILTER_RULETYPE_DYNAMIC_YEARTODATE,
|
||||
Rule::AUTOFILTER_RULETYPE_DYNAMIC_YESTERDAY,
|
||||
Rule::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_2,
|
||||
Rule::AUTOFILTER_RULETYPE_DYNAMIC_QUARTER_3,
|
||||
];
|
||||
|
||||
// Create the worksheets
|
||||
foreach ($ruleNames as $ruleName) {
|
||||
$helper->log("Add data and filter for $ruleName");
|
||||
createSheet($spreadsheet, $ruleName);
|
||||
}
|
||||
$spreadsheet->removeSheetByIndex(0);
|
||||
$spreadsheet->setActiveSheetIndex(0);
|
||||
// Save
|
||||
$helper->write($spreadsheet, __FILE__);
|
||||
|
|
@ -2,12 +2,14 @@
|
|||
|
||||
namespace PhpOffice\PhpSpreadsheet\Worksheet;
|
||||
|
||||
use DateTime;
|
||||
use DateTimeZone;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel;
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
|
||||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||
use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\Date;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule;
|
||||
|
||||
class AutoFilter
|
||||
{
|
||||
|
|
@ -358,38 +360,38 @@ class AutoFilter
|
|||
if (is_numeric($rule['value'])) {
|
||||
// Numeric values are tested using the appropriate operator
|
||||
switch ($rule['operator']) {
|
||||
case AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_EQUAL:
|
||||
case Rule::AUTOFILTER_COLUMN_RULE_EQUAL:
|
||||
$retVal = ($cellValue == $rule['value']);
|
||||
|
||||
break;
|
||||
case AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_NOTEQUAL:
|
||||
case Rule::AUTOFILTER_COLUMN_RULE_NOTEQUAL:
|
||||
$retVal = ($cellValue != $rule['value']);
|
||||
|
||||
break;
|
||||
case AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_GREATERTHAN:
|
||||
case Rule::AUTOFILTER_COLUMN_RULE_GREATERTHAN:
|
||||
$retVal = ($cellValue > $rule['value']);
|
||||
|
||||
break;
|
||||
case AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_GREATERTHANOREQUAL:
|
||||
case Rule::AUTOFILTER_COLUMN_RULE_GREATERTHANOREQUAL:
|
||||
$retVal = ($cellValue >= $rule['value']);
|
||||
|
||||
break;
|
||||
case AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_LESSTHAN:
|
||||
case Rule::AUTOFILTER_COLUMN_RULE_LESSTHAN:
|
||||
$retVal = ($cellValue < $rule['value']);
|
||||
|
||||
break;
|
||||
case AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_LESSTHANOREQUAL:
|
||||
case Rule::AUTOFILTER_COLUMN_RULE_LESSTHANOREQUAL:
|
||||
$retVal = ($cellValue <= $rule['value']);
|
||||
|
||||
break;
|
||||
}
|
||||
} elseif ($rule['value'] == '') {
|
||||
switch ($rule['operator']) {
|
||||
case AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_EQUAL:
|
||||
case Rule::AUTOFILTER_COLUMN_RULE_EQUAL:
|
||||
$retVal = (($cellValue == '') || ($cellValue === null));
|
||||
|
||||
break;
|
||||
case AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_NOTEQUAL:
|
||||
case Rule::AUTOFILTER_COLUMN_RULE_NOTEQUAL:
|
||||
$retVal = (($cellValue != '') && ($cellValue !== null));
|
||||
|
||||
break;
|
||||
|
|
@ -439,7 +441,8 @@ class AutoFilter
|
|||
}
|
||||
|
||||
if (is_numeric($cellValue)) {
|
||||
$dateValue = date('m', Date::excelToTimestamp($cellValue));
|
||||
$dateObject = Date::excelToDateTimeObject((float) $cellValue, new DateTimeZone('UTC'));
|
||||
$dateValue = (int) $dateObject->format('m');
|
||||
if (in_array($dateValue, $monthSet)) {
|
||||
return true;
|
||||
}
|
||||
|
|
@ -457,6 +460,224 @@ class AutoFilter
|
|||
|
||||
private static $toReplace = ['.*', '.', '~', '\*', '\?'];
|
||||
|
||||
private static function makeDateObject(int $year, int $month, int $day, int $hour = 0, int $minute = 0, int $second = 0): DateTime
|
||||
{
|
||||
$baseDate = new DateTime();
|
||||
$baseDate->setDate($year, $month, $day);
|
||||
$baseDate->setTime($hour, $minute, $second);
|
||||
|
||||
return $baseDate;
|
||||
}
|
||||
|
||||
private const DATE_FUNCTIONS = [
|
||||
Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTMONTH => 'dynamicLastMonth',
|
||||
Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTQUARTER => 'dynamicLastQuarter',
|
||||
Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTWEEK => 'dynamicLastWeek',
|
||||
Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTYEAR => 'dynamicLastYear',
|
||||
Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTMONTH => 'dynamicNextMonth',
|
||||
Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTQUARTER => 'dynamicNextQuarter',
|
||||
Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTWEEK => 'dynamicNextWeek',
|
||||
Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTYEAR => 'dynamicNextYear',
|
||||
Rule::AUTOFILTER_RULETYPE_DYNAMIC_THISMONTH => 'dynamicThisMonth',
|
||||
Rule::AUTOFILTER_RULETYPE_DYNAMIC_THISQUARTER => 'dynamicThisQuarter',
|
||||
Rule::AUTOFILTER_RULETYPE_DYNAMIC_THISWEEK => 'dynamicThisWeek',
|
||||
Rule::AUTOFILTER_RULETYPE_DYNAMIC_THISYEAR => 'dynamicThisYear',
|
||||
Rule::AUTOFILTER_RULETYPE_DYNAMIC_TODAY => 'dynamicToday',
|
||||
Rule::AUTOFILTER_RULETYPE_DYNAMIC_TOMORROW => 'dynamicTomorrow',
|
||||
Rule::AUTOFILTER_RULETYPE_DYNAMIC_YEARTODATE => 'dynamicYearToDate',
|
||||
Rule::AUTOFILTER_RULETYPE_DYNAMIC_YESTERDAY => 'dynamicYesterday',
|
||||
];
|
||||
|
||||
private static function dynamicLastMonth(): array
|
||||
{
|
||||
$maxval = new DateTime();
|
||||
$year = (int) $maxval->format('Y');
|
||||
$month = (int) $maxval->format('m');
|
||||
$maxval->setDate($year, $month, 1);
|
||||
$maxval->setTime(0, 0, 0);
|
||||
$val = clone $maxval;
|
||||
$val->modify('-1 month');
|
||||
|
||||
return [$val, $maxval];
|
||||
}
|
||||
|
||||
private static function firstDayOfQuarter(): DateTime
|
||||
{
|
||||
$val = new DateTime();
|
||||
$year = (int) $val->format('Y');
|
||||
$month = (int) $val->format('m');
|
||||
$month = 3 * intdiv($month - 1, 3) + 1;
|
||||
$val->setDate($year, $month, 1);
|
||||
$val->setTime(0, 0, 0);
|
||||
|
||||
return $val;
|
||||
}
|
||||
|
||||
private static function dynamicLastQuarter(): array
|
||||
{
|
||||
$maxval = self::firstDayOfQuarter();
|
||||
$val = clone $maxval;
|
||||
$val->modify('-3 months');
|
||||
|
||||
return [$val, $maxval];
|
||||
}
|
||||
|
||||
private static function dynamicLastWeek(): array
|
||||
{
|
||||
$val = new DateTime();
|
||||
$val->setTime(0, 0, 0);
|
||||
$dayOfWeek = (int) $val->format('w'); // Sunday is 0
|
||||
$subtract = $dayOfWeek + 7; // revert to prior Sunday
|
||||
$val->modify("-$subtract days");
|
||||
$maxval = clone $val;
|
||||
$maxval->modify('+7 days');
|
||||
|
||||
return [$val, $maxval];
|
||||
}
|
||||
|
||||
private static function dynamicLastYear(): array
|
||||
{
|
||||
$val = new DateTime();
|
||||
$year = (int) $val->format('Y');
|
||||
$val = self::makeDateObject($year - 1, 1, 1);
|
||||
$maxval = self::makeDateObject($year, 1, 1);
|
||||
|
||||
return [$val, $maxval];
|
||||
}
|
||||
|
||||
private static function dynamicNextMonth(): array
|
||||
{
|
||||
$val = new DateTime();
|
||||
$year = (int) $val->format('Y');
|
||||
$month = (int) $val->format('m');
|
||||
$val->setDate($year, $month, 1);
|
||||
$val->setTime(0, 0, 0);
|
||||
$val->modify('+1 month');
|
||||
$maxval = clone $val;
|
||||
$maxval->modify('+1 month');
|
||||
|
||||
return [$val, $maxval];
|
||||
}
|
||||
|
||||
private static function dynamicNextQuarter(): array
|
||||
{
|
||||
$val = self::firstDayOfQuarter();
|
||||
$val->modify('+3 months');
|
||||
$maxval = clone $val;
|
||||
$maxval->modify('+3 months');
|
||||
|
||||
return [$val, $maxval];
|
||||
}
|
||||
|
||||
private static function dynamicNextWeek(): array
|
||||
{
|
||||
$val = new DateTime();
|
||||
$val->setTime(0, 0, 0);
|
||||
$dayOfWeek = (int) $val->format('w'); // Sunday is 0
|
||||
$add = 7 - $dayOfWeek; // move to next Sunday
|
||||
$val->modify("+$add days");
|
||||
$maxval = clone $val;
|
||||
$maxval->modify('+7 days');
|
||||
|
||||
return [$val, $maxval];
|
||||
}
|
||||
|
||||
private static function dynamicNextYear(): array
|
||||
{
|
||||
$val = new DateTime();
|
||||
$year = (int) $val->format('Y');
|
||||
$val = self::makeDateObject($year + 1, 1, 1);
|
||||
$maxval = self::makeDateObject($year + 2, 1, 1);
|
||||
|
||||
return [$val, $maxval];
|
||||
}
|
||||
|
||||
private static function dynamicThisMonth(): array
|
||||
{
|
||||
$baseDate = new DateTime();
|
||||
$baseDate->setTime(0, 0, 0);
|
||||
$year = (int) $baseDate->format('Y');
|
||||
$month = (int) $baseDate->format('m');
|
||||
$val = self::makeDateObject($year, $month, 1);
|
||||
$maxval = clone $val;
|
||||
$maxval->modify('+1 month');
|
||||
|
||||
return [$val, $maxval];
|
||||
}
|
||||
|
||||
private static function dynamicThisQuarter(): array
|
||||
{
|
||||
$val = self::firstDayOfQuarter();
|
||||
$maxval = clone $val;
|
||||
$maxval->modify('+3 months');
|
||||
|
||||
return [$val, $maxval];
|
||||
}
|
||||
|
||||
private static function dynamicThisWeek(): array
|
||||
{
|
||||
$val = new DateTime();
|
||||
$val->setTime(0, 0, 0);
|
||||
$dayOfWeek = (int) $val->format('w'); // Sunday is 0
|
||||
$subtract = $dayOfWeek; // revert to Sunday
|
||||
$val->modify("-$subtract days");
|
||||
$maxval = clone $val;
|
||||
$maxval->modify('+7 days');
|
||||
|
||||
return [$val, $maxval];
|
||||
}
|
||||
|
||||
private static function dynamicThisYear(): array
|
||||
{
|
||||
$val = new DateTime();
|
||||
$year = (int) $val->format('Y');
|
||||
$val = self::makeDateObject($year, 1, 1);
|
||||
$maxval = self::makeDateObject($year + 1, 1, 1);
|
||||
|
||||
return [$val, $maxval];
|
||||
}
|
||||
|
||||
private static function dynamicToday(): array
|
||||
{
|
||||
$val = new DateTime();
|
||||
$val->setTime(0, 0, 0);
|
||||
$maxval = clone $val;
|
||||
$maxval->modify('+1 day');
|
||||
|
||||
return [$val, $maxval];
|
||||
}
|
||||
|
||||
private static function dynamicTomorrow(): array
|
||||
{
|
||||
$val = new DateTime();
|
||||
$val->setTime(0, 0, 0);
|
||||
$val->modify('+1 day');
|
||||
$maxval = clone $val;
|
||||
$maxval->modify('+1 day');
|
||||
|
||||
return [$val, $maxval];
|
||||
}
|
||||
|
||||
private static function dynamicYearToDate(): array
|
||||
{
|
||||
$maxval = new DateTime();
|
||||
$maxval->setTime(0, 0, 0);
|
||||
$val = self::makeDateObject((int) $maxval->format('Y'), 1, 1);
|
||||
$maxval->modify('+1 day');
|
||||
|
||||
return [$val, $maxval];
|
||||
}
|
||||
|
||||
private static function dynamicYesterday(): array
|
||||
{
|
||||
$maxval = new DateTime();
|
||||
$maxval->setTime(0, 0, 0);
|
||||
$val = clone $maxval;
|
||||
$val->modify('-1 day');
|
||||
|
||||
return [$val, $maxval];
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a dynamic rule daterange to a custom filter range expression for ease of calculation.
|
||||
*
|
||||
|
|
@ -467,118 +688,24 @@ class AutoFilter
|
|||
*/
|
||||
private function dynamicFilterDateRange($dynamicRuleType, &$filterColumn)
|
||||
{
|
||||
$rDateType = Functions::getReturnDateType();
|
||||
Functions::setReturnDateType(Functions::RETURNDATE_PHP_NUMERIC);
|
||||
$val = $maxVal = null;
|
||||
|
||||
$ruleValues = [];
|
||||
$baseDate = DateTimeExcel\Current::now();
|
||||
$callBack = [__CLASS__, self::DATE_FUNCTIONS[$dynamicRuleType]]; // What if not found?
|
||||
// Calculate start/end dates for the required date range based on current date
|
||||
switch ($dynamicRuleType) {
|
||||
case AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTWEEK:
|
||||
$baseDate = strtotime('-7 days', $baseDate);
|
||||
|
||||
break;
|
||||
case AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTWEEK:
|
||||
$baseDate = strtotime('-7 days', $baseDate);
|
||||
|
||||
break;
|
||||
case AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTMONTH:
|
||||
$baseDate = strtotime('-1 month', gmmktime(0, 0, 0, 1, date('m', $baseDate), date('Y', $baseDate)));
|
||||
|
||||
break;
|
||||
case AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTMONTH:
|
||||
$baseDate = strtotime('+1 month', gmmktime(0, 0, 0, 1, date('m', $baseDate), date('Y', $baseDate)));
|
||||
|
||||
break;
|
||||
case AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTQUARTER:
|
||||
$baseDate = strtotime('-3 month', gmmktime(0, 0, 0, 1, date('m', $baseDate), date('Y', $baseDate)));
|
||||
|
||||
break;
|
||||
case AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTQUARTER:
|
||||
$baseDate = strtotime('+3 month', gmmktime(0, 0, 0, 1, date('m', $baseDate), date('Y', $baseDate)));
|
||||
|
||||
break;
|
||||
case AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTYEAR:
|
||||
$baseDate = strtotime('-1 year', gmmktime(0, 0, 0, 1, date('m', $baseDate), date('Y', $baseDate)));
|
||||
|
||||
break;
|
||||
case AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTYEAR:
|
||||
$baseDate = strtotime('+1 year', gmmktime(0, 0, 0, 1, date('m', $baseDate), date('Y', $baseDate)));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
switch ($dynamicRuleType) {
|
||||
case AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DYNAMIC_TODAY:
|
||||
case AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DYNAMIC_YESTERDAY:
|
||||
case AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DYNAMIC_TOMORROW:
|
||||
$maxVal = (int) Date::PHPtoExcel(strtotime('+1 day', $baseDate));
|
||||
$val = (int) Date::PHPToExcel($baseDate);
|
||||
|
||||
break;
|
||||
case AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DYNAMIC_YEARTODATE:
|
||||
$maxVal = (int) Date::PHPtoExcel(strtotime('+1 day', $baseDate));
|
||||
$val = (int) Date::PHPToExcel(gmmktime(0, 0, 0, 1, 1, date('Y', $baseDate)));
|
||||
|
||||
break;
|
||||
case AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DYNAMIC_THISYEAR:
|
||||
case AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTYEAR:
|
||||
case AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTYEAR:
|
||||
$maxVal = (int) Date::PHPToExcel(gmmktime(0, 0, 0, 31, 12, date('Y', $baseDate)));
|
||||
++$maxVal;
|
||||
$val = (int) Date::PHPToExcel(gmmktime(0, 0, 0, 1, 1, date('Y', $baseDate)));
|
||||
|
||||
break;
|
||||
case AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DYNAMIC_THISQUARTER:
|
||||
case AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTQUARTER:
|
||||
case AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTQUARTER:
|
||||
$thisMonth = date('m', $baseDate);
|
||||
$thisQuarter = floor(--$thisMonth / 3);
|
||||
$maxVal = (int) Date::PHPtoExcel(gmmktime(0, 0, 0, date('t', $baseDate), (1 + $thisQuarter) * 3, date('Y', $baseDate)));
|
||||
++$maxVal;
|
||||
$val = (int) Date::PHPToExcel(gmmktime(0, 0, 0, 1, 1 + $thisQuarter * 3, date('Y', $baseDate)));
|
||||
|
||||
break;
|
||||
case AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DYNAMIC_THISMONTH:
|
||||
case AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTMONTH:
|
||||
case AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTMONTH:
|
||||
$maxVal = (int) Date::PHPtoExcel(gmmktime(0, 0, 0, date('t', $baseDate), date('m', $baseDate), date('Y', $baseDate)));
|
||||
++$maxVal;
|
||||
$val = (int) Date::PHPToExcel(gmmktime(0, 0, 0, 1, date('m', $baseDate), date('Y', $baseDate)));
|
||||
|
||||
break;
|
||||
case AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DYNAMIC_THISWEEK:
|
||||
case AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTWEEK:
|
||||
case AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTWEEK:
|
||||
$dayOfWeek = date('w', $baseDate);
|
||||
$val = (int) Date::PHPToExcel($baseDate) - $dayOfWeek;
|
||||
$maxVal = $val + 7;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
switch ($dynamicRuleType) {
|
||||
// Adjust Today dates for Yesterday and Tomorrow
|
||||
case AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DYNAMIC_YESTERDAY:
|
||||
--$maxVal;
|
||||
--$val;
|
||||
|
||||
break;
|
||||
case AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DYNAMIC_TOMORROW:
|
||||
++$maxVal;
|
||||
++$val;
|
||||
|
||||
break;
|
||||
// Val is lowest permitted value.
|
||||
// Maxval is greater than highest permitted value
|
||||
$val = $maxval = 0;
|
||||
if (is_callable($callBack)) {
|
||||
[$val, $maxval] = $callBack();
|
||||
}
|
||||
$val = Date::dateTimeToExcel($val);
|
||||
$maxval = Date::dateTimeToExcel($maxval);
|
||||
|
||||
// Set the filter column rule attributes ready for writing
|
||||
$filterColumn->setAttributes(['val' => $val, 'maxVal' => $maxVal]);
|
||||
$filterColumn->setAttributes(['val' => $val, 'maxVal' => $maxval]);
|
||||
|
||||
// Set the rules for identifying rows for hide/show
|
||||
$ruleValues[] = ['operator' => AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_GREATERTHANOREQUAL, 'value' => $val];
|
||||
$ruleValues[] = ['operator' => AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_LESSTHAN, 'value' => $maxVal];
|
||||
Functions::setReturnDateType($rDateType);
|
||||
$ruleValues[] = ['operator' => Rule::AUTOFILTER_COLUMN_RULE_GREATERTHANOREQUAL, 'value' => $val];
|
||||
$ruleValues[] = ['operator' => Rule::AUTOFILTER_COLUMN_RULE_LESSTHAN, 'value' => $maxval];
|
||||
|
||||
return ['method' => 'filterTestInCustomDataSet', 'arguments' => ['filterRules' => $ruleValues, 'join' => AutoFilter\Column::AUTOFILTER_COLUMN_JOIN_AND]];
|
||||
}
|
||||
|
|
@ -589,7 +716,7 @@ class AutoFilter
|
|||
$dataValues = Functions::flattenArray($this->workSheet->rangeToArray($range, null, true, false));
|
||||
|
||||
$dataValues = array_filter($dataValues);
|
||||
if ($ruleType == AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_TOP) {
|
||||
if ($ruleType == Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_TOP) {
|
||||
rsort($dataValues);
|
||||
} else {
|
||||
sort($dataValues);
|
||||
|
|
@ -630,7 +757,7 @@ class AutoFilter
|
|||
if (count($ruleValues) != count($ruleDataSet)) {
|
||||
$blanks = true;
|
||||
}
|
||||
if ($ruleType == AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_FILTER) {
|
||||
if ($ruleType == Rule::AUTOFILTER_RULETYPE_FILTER) {
|
||||
// Filter on absolute values
|
||||
$columnFilterTests[$columnID] = [
|
||||
'method' => 'filterTestInSimpleDataSet',
|
||||
|
|
@ -646,40 +773,40 @@ class AutoFilter
|
|||
foreach ($ruleDataSet as $ruleValue) {
|
||||
$date = $time = '';
|
||||
if (
|
||||
(isset($ruleValue[AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DATEGROUP_YEAR])) &&
|
||||
($ruleValue[AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DATEGROUP_YEAR] !== '')
|
||||
(isset($ruleValue[Rule::AUTOFILTER_RULETYPE_DATEGROUP_YEAR])) &&
|
||||
($ruleValue[Rule::AUTOFILTER_RULETYPE_DATEGROUP_YEAR] !== '')
|
||||
) {
|
||||
$date .= sprintf('%04d', $ruleValue[AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DATEGROUP_YEAR]);
|
||||
$date .= sprintf('%04d', $ruleValue[Rule::AUTOFILTER_RULETYPE_DATEGROUP_YEAR]);
|
||||
}
|
||||
if (
|
||||
(isset($ruleValue[AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DATEGROUP_MONTH])) &&
|
||||
($ruleValue[AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DATEGROUP_MONTH] != '')
|
||||
(isset($ruleValue[Rule::AUTOFILTER_RULETYPE_DATEGROUP_MONTH])) &&
|
||||
($ruleValue[Rule::AUTOFILTER_RULETYPE_DATEGROUP_MONTH] != '')
|
||||
) {
|
||||
$date .= sprintf('%02d', $ruleValue[AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DATEGROUP_MONTH]);
|
||||
$date .= sprintf('%02d', $ruleValue[Rule::AUTOFILTER_RULETYPE_DATEGROUP_MONTH]);
|
||||
}
|
||||
if (
|
||||
(isset($ruleValue[AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DATEGROUP_DAY])) &&
|
||||
($ruleValue[AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DATEGROUP_DAY] !== '')
|
||||
(isset($ruleValue[Rule::AUTOFILTER_RULETYPE_DATEGROUP_DAY])) &&
|
||||
($ruleValue[Rule::AUTOFILTER_RULETYPE_DATEGROUP_DAY] !== '')
|
||||
) {
|
||||
$date .= sprintf('%02d', $ruleValue[AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DATEGROUP_DAY]);
|
||||
$date .= sprintf('%02d', $ruleValue[Rule::AUTOFILTER_RULETYPE_DATEGROUP_DAY]);
|
||||
}
|
||||
if (
|
||||
(isset($ruleValue[AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DATEGROUP_HOUR])) &&
|
||||
($ruleValue[AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DATEGROUP_HOUR] !== '')
|
||||
(isset($ruleValue[Rule::AUTOFILTER_RULETYPE_DATEGROUP_HOUR])) &&
|
||||
($ruleValue[Rule::AUTOFILTER_RULETYPE_DATEGROUP_HOUR] !== '')
|
||||
) {
|
||||
$time .= sprintf('%02d', $ruleValue[AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DATEGROUP_HOUR]);
|
||||
$time .= sprintf('%02d', $ruleValue[Rule::AUTOFILTER_RULETYPE_DATEGROUP_HOUR]);
|
||||
}
|
||||
if (
|
||||
(isset($ruleValue[AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DATEGROUP_MINUTE])) &&
|
||||
($ruleValue[AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DATEGROUP_MINUTE] !== '')
|
||||
(isset($ruleValue[Rule::AUTOFILTER_RULETYPE_DATEGROUP_MINUTE])) &&
|
||||
($ruleValue[Rule::AUTOFILTER_RULETYPE_DATEGROUP_MINUTE] !== '')
|
||||
) {
|
||||
$time .= sprintf('%02d', $ruleValue[AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DATEGROUP_MINUTE]);
|
||||
$time .= sprintf('%02d', $ruleValue[Rule::AUTOFILTER_RULETYPE_DATEGROUP_MINUTE]);
|
||||
}
|
||||
if (
|
||||
(isset($ruleValue[AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DATEGROUP_SECOND])) &&
|
||||
($ruleValue[AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DATEGROUP_SECOND] !== '')
|
||||
(isset($ruleValue[Rule::AUTOFILTER_RULETYPE_DATEGROUP_SECOND])) &&
|
||||
($ruleValue[Rule::AUTOFILTER_RULETYPE_DATEGROUP_SECOND] !== '')
|
||||
) {
|
||||
$time .= sprintf('%02d', $ruleValue[AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DATEGROUP_SECOND]);
|
||||
$time .= sprintf('%02d', $ruleValue[Rule::AUTOFILTER_RULETYPE_DATEGROUP_SECOND]);
|
||||
}
|
||||
$dateTime = $date . $time;
|
||||
$arguments['date'][] = $date;
|
||||
|
|
@ -727,17 +854,17 @@ class AutoFilter
|
|||
// We should only ever have one Dynamic Filter Rule anyway
|
||||
$dynamicRuleType = $rule->getGrouping();
|
||||
if (
|
||||
($dynamicRuleType == AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DYNAMIC_ABOVEAVERAGE) ||
|
||||
($dynamicRuleType == AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DYNAMIC_BELOWAVERAGE)
|
||||
($dynamicRuleType == Rule::AUTOFILTER_RULETYPE_DYNAMIC_ABOVEAVERAGE) ||
|
||||
($dynamicRuleType == Rule::AUTOFILTER_RULETYPE_DYNAMIC_BELOWAVERAGE)
|
||||
) {
|
||||
// Number (Average) based
|
||||
// Calculate the average
|
||||
$averageFormula = '=AVERAGE(' . $columnID . ($rangeStart[1] + 1) . ':' . $columnID . $rangeEnd[1] . ')';
|
||||
$average = Calculation::getInstance()->calculateFormula($averageFormula, null, $this->workSheet->getCell('A1'));
|
||||
// Set above/below rule based on greaterThan or LessTan
|
||||
$operator = ($dynamicRuleType === AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DYNAMIC_ABOVEAVERAGE)
|
||||
? AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_GREATERTHAN
|
||||
: AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_LESSTHAN;
|
||||
$operator = ($dynamicRuleType === Rule::AUTOFILTER_RULETYPE_DYNAMIC_ABOVEAVERAGE)
|
||||
? Rule::AUTOFILTER_COLUMN_RULE_GREATERTHAN
|
||||
: Rule::AUTOFILTER_COLUMN_RULE_LESSTHAN;
|
||||
$ruleValues[] = [
|
||||
'operator' => $operator,
|
||||
'value' => $average,
|
||||
|
|
@ -788,7 +915,7 @@ class AutoFilter
|
|||
$ruleValue = $rule->getValue();
|
||||
$ruleOperator = $rule->getOperator();
|
||||
}
|
||||
if ($ruleOperator === AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_PERCENT) {
|
||||
if ($ruleOperator === Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_PERCENT) {
|
||||
$ruleValue = floor($ruleValue * ($dataRowCount / 100));
|
||||
}
|
||||
if (!is_array($ruleValue) && $ruleValue < 1) {
|
||||
|
|
@ -800,9 +927,9 @@ class AutoFilter
|
|||
|
||||
$maxVal = $this->calculateTopTenValue($columnID, $rangeStart[1] + 1, $rangeEnd[1], $toptenRuleType, $ruleValue);
|
||||
|
||||
$operator = ($toptenRuleType == AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_TOP)
|
||||
? AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_GREATERTHANOREQUAL
|
||||
: AutoFilter\Column\Rule::AUTOFILTER_COLUMN_RULE_LESSTHANOREQUAL;
|
||||
$operator = ($toptenRuleType == Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_TOP)
|
||||
? Rule::AUTOFILTER_COLUMN_RULE_GREATERTHANOREQUAL
|
||||
: Rule::AUTOFILTER_COLUMN_RULE_LESSTHANOREQUAL;
|
||||
$ruleValues[] = ['operator' => $operator, 'value' => $maxVal];
|
||||
$columnFilterTests[$columnID] = [
|
||||
'method' => 'filterTestInCustomDataSet',
|
||||
|
|
|
|||
|
|
@ -215,11 +215,11 @@ class Column
|
|||
/**
|
||||
* Set AutoFilter Attributes.
|
||||
*
|
||||
* @param string[] $attributes
|
||||
* @param mixed[] $attributes
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setAttributes(array $attributes)
|
||||
public function setAttributes($attributes)
|
||||
{
|
||||
$this->attributes = $attributes;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,91 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Worksheet\AutoFilter;
|
||||
|
||||
use DateTimeImmutable;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class AutoFilterMonthTest extends TestCase
|
||||
{
|
||||
public function providerMonth(): array
|
||||
{
|
||||
return [
|
||||
[[2, 3], Rule::AUTOFILTER_RULETYPE_DYNAMIC_THISMONTH],
|
||||
[[4], Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTMONTH],
|
||||
[[6], Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTMONTH],
|
||||
];
|
||||
}
|
||||
|
||||
private static function setCells(Worksheet $sheet, int $startMonth): void
|
||||
{
|
||||
$sheet->getCell('A1')->setValue('Date');
|
||||
$sheet->getCell('A2')->setValue('=TODAY()');
|
||||
$sheet->getCell('A3')->setValue('=DATE(YEAR(A2), MONTH(A2), 1)');
|
||||
if ($startMonth === 12) {
|
||||
$sheet->getCell('A4')->setValue('=DATE(YEAR(A2) + 1, 1, 1)');
|
||||
$sheet->getCell('A5')->setValue('=DATE(YEAR(A2) + 1, 2, 1)');
|
||||
} elseif ($startMonth === 11) {
|
||||
$sheet->getCell('A4')->setValue('=DATE(YEAR(A2), MONTH(A2) + 1, 1)');
|
||||
$sheet->getCell('A5')->setValue('=DATE(YEAR(A2) + 1, 1, 1)');
|
||||
} else {
|
||||
$sheet->getCell('A4')->setValue('=DATE(YEAR(A2), MONTH(A2) + 1, 1)');
|
||||
$sheet->getCell('A5')->setValue('=DATE(YEAR(A2), MONTH(A2) + 2, 1)');
|
||||
}
|
||||
if ($startMonth === 1) {
|
||||
$sheet->getCell('A6')->setValue('=DATE(YEAR(A2) - 1, 12, 1)');
|
||||
$sheet->getCell('A7')->setValue('=DATE(YEAR(A2) - 1, 10, 1)');
|
||||
} elseif ($startMonth === 2) {
|
||||
$sheet->getCell('A6')->setValue('=DATE(YEAR(A2), 1, 1)');
|
||||
$sheet->getCell('A7')->setValue('=DATE(YEAR(A2) - 1, 12, 1)');
|
||||
} else {
|
||||
$sheet->getCell('A6')->setValue('=DATE(YEAR(A2), MONTH(A2) - 1, 1)');
|
||||
$sheet->getCell('A7')->setValue('=DATE(YEAR(A2), MONTH(A2) - 2, 1)');
|
||||
}
|
||||
$sheet->getCell('A8')->setValue('=DATE(YEAR(A2) + 1, MONTH(A2), 1)');
|
||||
$sheet->getCell('A9')->setValue('=DATE(YEAR(A2) - 1, MONTH(A2), 1)');
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerMonth
|
||||
*/
|
||||
public function testMonths(array $expectedVisible, string $rule): void
|
||||
{
|
||||
// Loop to avoid rare edge case where first calculation
|
||||
// and second do not take place in same day.
|
||||
do {
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
$dtStart = new DateTimeImmutable();
|
||||
$startDay = (int) $dtStart->format('d');
|
||||
$startMonth = (int) $dtStart->format('m');
|
||||
self::setCells($sheet, $startMonth);
|
||||
|
||||
$maxRow = 9;
|
||||
$autoFilter = $spreadsheet->getActiveSheet()->getAutoFilter();
|
||||
$autoFilter->setRange("A1:A$maxRow");
|
||||
$columnFilter = $autoFilter->getColumn('A');
|
||||
$columnFilter->setFilterType(Column::AUTOFILTER_FILTERTYPE_DYNAMICFILTER);
|
||||
$columnFilter->createRule()
|
||||
->setRule(
|
||||
Rule::AUTOFILTER_COLUMN_RULE_EQUAL,
|
||||
'',
|
||||
$rule
|
||||
)
|
||||
->setRuleType(Rule::AUTOFILTER_RULETYPE_DYNAMICFILTER);
|
||||
$autoFilter->showHideRows();
|
||||
$dtEnd = new DateTimeImmutable();
|
||||
$endDay = (int) $dtEnd->format('d');
|
||||
} while ($startDay !== $endDay);
|
||||
$actualVisible = [];
|
||||
for ($row = 2; $row <= $maxRow; ++$row) {
|
||||
if ($sheet->getRowDimension($row)->getVisible()) {
|
||||
$actualVisible[] = $row;
|
||||
}
|
||||
}
|
||||
self::assertEquals($expectedVisible, $actualVisible);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Worksheet\AutoFilter;
|
||||
|
||||
use DateTimeImmutable;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class AutoFilterQuarterTest extends TestCase
|
||||
{
|
||||
public function providerQuarter(): array
|
||||
{
|
||||
return [
|
||||
[[2, 3], Rule::AUTOFILTER_RULETYPE_DYNAMIC_THISQUARTER],
|
||||
[[4], Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTQUARTER],
|
||||
[[6], Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTQUARTER],
|
||||
];
|
||||
}
|
||||
|
||||
private static function setCells(Worksheet $sheet): void
|
||||
{
|
||||
$sheet->getCell('A1')->setValue('Date');
|
||||
$sheet->getCell('A2')->setValue('=TODAY()');
|
||||
$sheet->getCell('A3')->setValue('=DATE(YEAR(A2), MONTH(A2), 1)');
|
||||
$sheet->getCell('A4')->setValue('=DATE(YEAR(A2), MONTH(A2) + 3, 1)');
|
||||
$sheet->getCell('A5')->setValue('=DATE(YEAR(A2), MONTH(A2) + 6, 1)');
|
||||
$sheet->getCell('A6')->setValue('=DATE(YEAR(A2), MONTH(A2) - 3, 1)');
|
||||
$sheet->getCell('A7')->setValue('=DATE(YEAR(A2), MONTH(A2) - 6, 1)');
|
||||
$sheet->getCell('A8')->setValue('=DATE(YEAR(A2) + 1, MONTH(A2), 1)');
|
||||
$sheet->getCell('A9')->setValue('=DATE(YEAR(A2) - 1, MONTH(A2), 1)');
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerQuarter
|
||||
*/
|
||||
public function testQuarters(array $expectedVisible, string $rule): void
|
||||
{
|
||||
// Loop to avoid rare edge case where first calculation
|
||||
// and second do not take place in same day.
|
||||
do {
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
$dtStart = new DateTimeImmutable();
|
||||
$startDay = (int) $dtStart->format('d');
|
||||
self::setCells($sheet);
|
||||
|
||||
$maxRow = 9;
|
||||
$autoFilter = $spreadsheet->getActiveSheet()->getAutoFilter();
|
||||
$autoFilter->setRange("A1:A$maxRow");
|
||||
$columnFilter = $autoFilter->getColumn('A');
|
||||
$columnFilter->setFilterType(Column::AUTOFILTER_FILTERTYPE_DYNAMICFILTER);
|
||||
$columnFilter->createRule()
|
||||
->setRule(
|
||||
Rule::AUTOFILTER_COLUMN_RULE_EQUAL,
|
||||
'',
|
||||
$rule
|
||||
)
|
||||
->setRuleType(Rule::AUTOFILTER_RULETYPE_DYNAMICFILTER);
|
||||
$autoFilter->showHideRows();
|
||||
$dtEnd = new DateTimeImmutable();
|
||||
$endDay = (int) $dtEnd->format('d');
|
||||
} while ($startDay !== $endDay);
|
||||
$actualVisible = [];
|
||||
for ($row = 2; $row <= $maxRow; ++$row) {
|
||||
if ($sheet->getRowDimension($row)->getVisible()) {
|
||||
$actualVisible[] = $row;
|
||||
}
|
||||
}
|
||||
self::assertEquals($expectedVisible, $actualVisible);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Worksheet;
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Worksheet\AutoFilter;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Collection\Cells;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter;
|
||||
|
|
@ -207,6 +207,7 @@ class AutoFilterTest extends TestCase
|
|||
$this->expectException(\PhpOffice\PhpSpreadsheet\Exception::class);
|
||||
|
||||
$invalidColumn = 123.456;
|
||||
// @phpstan-ignore-next-line
|
||||
$this->testAutoFilterObject->setColumn($invalidColumn);
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Worksheet\AutoFilter;
|
||||
|
||||
use DateTimeImmutable;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class AutoFilterTodayTest extends TestCase
|
||||
{
|
||||
public function providerYesterdayTodayTomorrow(): array
|
||||
{
|
||||
return [
|
||||
[[2, 5], Rule::AUTOFILTER_RULETYPE_DYNAMIC_TODAY],
|
||||
[[3, 6], Rule::AUTOFILTER_RULETYPE_DYNAMIC_TOMORROW],
|
||||
[[4, 7], Rule::AUTOFILTER_RULETYPE_DYNAMIC_YESTERDAY],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerYesterdayTodayTomorrow
|
||||
*/
|
||||
public function testYesterdayTodayTomorrow(array $expectedVisible, string $rule): void
|
||||
{
|
||||
// Loop to avoid rare edge case where first calculation
|
||||
// and second do not take place in same day.
|
||||
do {
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
$dtStart = new DateTimeImmutable();
|
||||
$startDay = $dtStart->format('d');
|
||||
$sheet->getCell('A1')->setValue('Date');
|
||||
$sheet->getCell('A2')->setValue('=NOW()');
|
||||
$sheet->getCell('A3')->setValue('=A2+1');
|
||||
$sheet->getCell('A4')->setValue('=A2-1');
|
||||
$sheet->getCell('A5')->setValue('=TODAY()');
|
||||
$sheet->getCell('A6')->setValue('=A5+1');
|
||||
$sheet->getCell('A7')->setValue('=A5-1');
|
||||
$maxRow = 7;
|
||||
$autoFilter = $spreadsheet->getActiveSheet()->getAutoFilter();
|
||||
$autoFilter->setRange("A1:A$maxRow");
|
||||
$columnFilter = $autoFilter->getColumn('A');
|
||||
$columnFilter->setFilterType(Column::AUTOFILTER_FILTERTYPE_DYNAMICFILTER);
|
||||
$columnFilter->createRule()
|
||||
->setRule(
|
||||
Rule::AUTOFILTER_COLUMN_RULE_EQUAL,
|
||||
'',
|
||||
$rule
|
||||
)
|
||||
->setRuleType(Rule::AUTOFILTER_RULETYPE_DYNAMICFILTER);
|
||||
$autoFilter->showHideRows();
|
||||
$dtEnd = new DateTimeImmutable();
|
||||
$endDay = $dtEnd->format('d');
|
||||
} while ($startDay !== $endDay);
|
||||
$actualVisible = [];
|
||||
for ($row = 2; $row <= $maxRow; ++$row) {
|
||||
if ($sheet->getRowDimension($row)->getVisible()) {
|
||||
$actualVisible[] = $row;
|
||||
}
|
||||
}
|
||||
self::assertEquals($expectedVisible, $actualVisible);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Worksheet\AutoFilter;
|
||||
|
||||
use DateTimeImmutable;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class AutoFilterWeekTest extends TestCase
|
||||
{
|
||||
public function providerWeek(): array
|
||||
{
|
||||
return [
|
||||
[[2, 3], Rule::AUTOFILTER_RULETYPE_DYNAMIC_THISWEEK],
|
||||
[[4], Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTWEEK],
|
||||
[[6], Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTWEEK],
|
||||
];
|
||||
}
|
||||
|
||||
private static function setCells(Worksheet $sheet): void
|
||||
{
|
||||
$sheet->getCell('A1')->setValue('Date');
|
||||
$sheet->getCell('A2')->setValue('=TODAY()');
|
||||
$sheet->getCell('B2')->setValue('=WEEKDAY(A2) - 1'); // subtract to get to Sunday
|
||||
$sheet->getCell('A3')->setValue('=DATE(YEAR(A2), MONTH(A2), DAY(A2) - B2)');
|
||||
$sheet->getCell('A4')->setValue('=DATE(YEAR(A3), MONTH(A3), DAY(A3) + 8)');
|
||||
$sheet->getCell('A5')->setValue('=DATE(YEAR(A3), MONTH(A3), DAY(A3) + 19)');
|
||||
$sheet->getCell('A6')->setValue('=DATE(YEAR(A3), MONTH(A3), DAY(A3) - 6)');
|
||||
$sheet->getCell('A7')->setValue('=DATE(YEAR(A3), MONTH(A3), DAY(A3) - 12)');
|
||||
$sheet->getCell('A8')->setValue('=DATE(YEAR(A2) + 1, MONTH(A2), 1)');
|
||||
$sheet->getCell('A9')->setValue('=DATE(YEAR(A2) - 1, MONTH(A2), 1)');
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerWeek
|
||||
*/
|
||||
public function testWeek(array $expectedVisible, string $rule): void
|
||||
{
|
||||
// Loop to avoid rare edge case where first calculation
|
||||
// and second do not take place in same day.
|
||||
do {
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
$dtStart = new DateTimeImmutable();
|
||||
$startDay = (int) $dtStart->format('d');
|
||||
self::setCells($sheet);
|
||||
|
||||
$maxRow = 9;
|
||||
$autoFilter = $spreadsheet->getActiveSheet()->getAutoFilter();
|
||||
$autoFilter->setRange("A1:A$maxRow");
|
||||
$columnFilter = $autoFilter->getColumn('A');
|
||||
$columnFilter->setFilterType(Column::AUTOFILTER_FILTERTYPE_DYNAMICFILTER);
|
||||
$columnFilter->createRule()
|
||||
->setRule(
|
||||
Rule::AUTOFILTER_COLUMN_RULE_EQUAL,
|
||||
'',
|
||||
$rule
|
||||
)
|
||||
->setRuleType(Rule::AUTOFILTER_RULETYPE_DYNAMICFILTER);
|
||||
$autoFilter->showHideRows();
|
||||
$dtEnd = new DateTimeImmutable();
|
||||
$endDay = (int) $dtEnd->format('d');
|
||||
} while ($startDay !== $endDay);
|
||||
$actualVisible = [];
|
||||
for ($row = 2; $row <= $maxRow; ++$row) {
|
||||
if ($sheet->getRowDimension($row)->getVisible()) {
|
||||
$actualVisible[] = $row;
|
||||
}
|
||||
}
|
||||
self::assertEquals($expectedVisible, $actualVisible);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Worksheet\AutoFilter;
|
||||
|
||||
use DateTimeImmutable;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class AutoFilterYearTest extends TestCase
|
||||
{
|
||||
public function providerYear(): array
|
||||
{
|
||||
return [
|
||||
[[5, 6, 7], Rule::AUTOFILTER_RULETYPE_DYNAMIC_THISYEAR],
|
||||
[[2, 3, 4], Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTYEAR],
|
||||
[[8, 9, 10], Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTYEAR],
|
||||
[[], Rule::AUTOFILTER_RULETYPE_DYNAMIC_QUARTER_2],
|
||||
[[2, 5, 8, 11], Rule::AUTOFILTER_RULETYPE_DYNAMIC_QUARTER_1],
|
||||
[[4, 7, 10], Rule::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_11],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerYear
|
||||
*/
|
||||
public function testYears(array $expectedVisible, string $rule): void
|
||||
{
|
||||
// Loop to avoid rare edge case where first calculation
|
||||
// and second do not take place in same day.
|
||||
do {
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
$dtStart = new DateTimeImmutable();
|
||||
$startDay = (int) $dtStart->format('d');
|
||||
$sheet->getCell('A1')->setValue('Date');
|
||||
$year = (int) $dtStart->format('Y') - 1;
|
||||
$row = 1;
|
||||
$iteration = 0;
|
||||
while ($iteration < 3) {
|
||||
for ($month = 3; $month < 13; $month += 4) {
|
||||
++$row;
|
||||
$sheet->getCell("A$row")->setValue("=DATE($year, $month, 1)");
|
||||
}
|
||||
++$year;
|
||||
++$iteration;
|
||||
}
|
||||
++$row;
|
||||
$sheet->getCell("A$row")->setValue('=DATE(2041, 1, 1)'); // beyond epoch
|
||||
$maxRow = $row;
|
||||
$autoFilter = $spreadsheet->getActiveSheet()->getAutoFilter();
|
||||
$autoFilter->setRange("A1:A$maxRow");
|
||||
$columnFilter = $autoFilter->getColumn('A');
|
||||
$columnFilter->setFilterType(Column::AUTOFILTER_FILTERTYPE_DYNAMICFILTER);
|
||||
$columnFilter->createRule()
|
||||
->setRule(
|
||||
Rule::AUTOFILTER_COLUMN_RULE_EQUAL,
|
||||
'',
|
||||
$rule
|
||||
)
|
||||
->setRuleType(Rule::AUTOFILTER_RULETYPE_DYNAMICFILTER);
|
||||
$autoFilter->showHideRows();
|
||||
$dtEnd = new DateTimeImmutable();
|
||||
$endDay = (int) $dtEnd->format('d');
|
||||
} while ($startDay !== $endDay);
|
||||
$actualVisible = [];
|
||||
for ($row = 2; $row <= $maxRow; ++$row) {
|
||||
if ($sheet->getRowDimension($row)->getVisible()) {
|
||||
$actualVisible[] = $row;
|
||||
}
|
||||
}
|
||||
self::assertEquals($expectedVisible, $actualVisible);
|
||||
}
|
||||
|
||||
public function testYearToDate(): void
|
||||
{
|
||||
// Loop to avoid rare edge case where first calculation
|
||||
// and second do not take place in same day.
|
||||
do {
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$sheet = $spreadsheet->getActiveSheet();
|
||||
$dtStart = new DateTimeImmutable();
|
||||
$startDay = (int) $dtStart->format('d');
|
||||
$startMonth = (int) $dtStart->format('m');
|
||||
$sheet->getCell('A1')->setValue('Date');
|
||||
$sheet->getCell('A2')->setValue('=TODAY()');
|
||||
$sheet->getCell('A3')->setValue('=DATE(YEAR(A2), 12, 31)');
|
||||
$sheet->getCell('A4')->setValue('=A3 + 1');
|
||||
$sheet->getCell('A5')->setValue('=DATE(YEAR(A2), 1, 1)');
|
||||
$sheet->getCell('A6')->setValue('=A5 - 1');
|
||||
|
||||
$maxRow = 6;
|
||||
$autoFilter = $spreadsheet->getActiveSheet()->getAutoFilter();
|
||||
$autoFilter->setRange("A1:A$maxRow");
|
||||
$columnFilter = $autoFilter->getColumn('A');
|
||||
$columnFilter->setFilterType(Column::AUTOFILTER_FILTERTYPE_DYNAMICFILTER);
|
||||
$columnFilter->createRule()
|
||||
->setRule(
|
||||
Rule::AUTOFILTER_COLUMN_RULE_EQUAL,
|
||||
'',
|
||||
Rule::AUTOFILTER_RULETYPE_DYNAMIC_YEARTODATE
|
||||
)
|
||||
->setRuleType(Rule::AUTOFILTER_RULETYPE_DYNAMICFILTER);
|
||||
$autoFilter->showHideRows();
|
||||
$dtEnd = new DateTimeImmutable();
|
||||
$endDay = (int) $dtEnd->format('d');
|
||||
} while ($startDay !== $endDay);
|
||||
$actualVisible = [];
|
||||
for ($row = 2; $row <= $maxRow; ++$row) {
|
||||
if ($sheet->getRowDimension($row)->getVisible()) {
|
||||
$actualVisible[] = $row;
|
||||
}
|
||||
}
|
||||
$expected = ($startMonth === 12 && $startDay === 31) ? [2, 3, 5] : [2, 5];
|
||||
self::assertEquals($expected, $actualVisible);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue