parent = $parent; $this->worksheetXml = $worksheetXml; } public function load(): void { // Remove all "$" in the auto filter range $attrs = $this->worksheetXml->autoFilter->attributes() ?? []; $autoFilterRange = (string) preg_replace('/\$/', '', $attrs['ref'] ?? ''); if (str_contains($autoFilterRange, ':')) { $this->readAutoFilter($autoFilterRange); } } private function readAutoFilter(string $autoFilterRange): void { $autoFilter = $this->parent->getAutoFilter(); $autoFilter->setRange($autoFilterRange); foreach ($this->worksheetXml->autoFilter->filterColumn as $filterColumn) { $attributes = $filterColumn->attributes() ?? []; $column = $autoFilter->getColumnByOffset((int) ($attributes['colId'] ?? 0)); // Check for standard filters if ($filterColumn->filters) { $column->setFilterType(Column::AUTOFILTER_FILTERTYPE_FILTER); $filters = Xlsx::testSimpleXml($filterColumn->filters->attributes()); if ((isset($filters['blank'])) && ((int) $filters['blank'] == 1)) { // Operator is undefined, but always treated as EQUAL $column->createRule()->setRule('', '')->setRuleType(Rule::AUTOFILTER_RULETYPE_FILTER); } // Standard filters are always an OR join, so no join rule needs to be set // Entries can be either filter elements foreach ($filterColumn->filters->filter as $filterRule) { // Operator is undefined, but always treated as EQUAL $attr2 = $filterRule->attributes() ?? ['val' => '']; $column->createRule()->setRule('', (string) $attr2['val'])->setRuleType(Rule::AUTOFILTER_RULETYPE_FILTER); } // Or Date Group elements $this->readDateRangeAutoFilter($filterColumn->filters, $column); } // Check for custom filters $this->readCustomAutoFilter($filterColumn, $column); // Check for dynamic filters $this->readDynamicAutoFilter($filterColumn, $column); // Check for dynamic filters $this->readTopTenAutoFilter($filterColumn, $column); } $autoFilter->setEvaluated(true); } private function readDateRangeAutoFilter(SimpleXMLElement $filters, Column $column): void { foreach ($filters->dateGroupItem as $dateGroupItemx) { // Operator is undefined, but always treated as EQUAL $dateGroupItem = $dateGroupItemx->attributes(); if ($dateGroupItem !== null) { $column->createRule()->setRule( '', [ 'year' => (string) $dateGroupItem['year'], 'month' => (string) $dateGroupItem['month'], 'day' => (string) $dateGroupItem['day'], 'hour' => (string) $dateGroupItem['hour'], 'minute' => (string) $dateGroupItem['minute'], 'second' => (string) $dateGroupItem['second'], ], (string) $dateGroupItem['dateTimeGrouping'] )->setRuleType(Rule::AUTOFILTER_RULETYPE_DATEGROUP); } } } private function readCustomAutoFilter(?SimpleXMLElement $filterColumn, Column $column): void { if (isset($filterColumn, $filterColumn->customFilters)) { $column->setFilterType(Column::AUTOFILTER_FILTERTYPE_CUSTOMFILTER); $customFilters = $filterColumn->customFilters; $attributes = $customFilters->attributes(); // Custom filters can an AND or an OR join; // and there should only ever be one or two entries if ((isset($attributes['and'])) && ((string) $attributes['and'] === '1')) { $column->setJoin(Column::AUTOFILTER_COLUMN_JOIN_AND); } foreach ($customFilters->customFilter as $filterRule) { $attr2 = $filterRule->attributes() ?? ['operator' => '', 'val' => '']; $column->createRule()->setRule( (string) $attr2['operator'], (string) $attr2['val'] )->setRuleType(Rule::AUTOFILTER_RULETYPE_CUSTOMFILTER); } } } private function readDynamicAutoFilter(?SimpleXMLElement $filterColumn, Column $column): void { if (isset($filterColumn, $filterColumn->dynamicFilter)) { $column->setFilterType(Column::AUTOFILTER_FILTERTYPE_DYNAMICFILTER); // We should only ever have one dynamic filter foreach ($filterColumn->dynamicFilter as $filterRule) { // Operator is undefined, but always treated as EQUAL $attr2 = $filterRule->attributes() ?? []; $column->createRule()->setRule( '', (string) ($attr2['val'] ?? ''), (string) ($attr2['type'] ?? '') )->setRuleType(Rule::AUTOFILTER_RULETYPE_DYNAMICFILTER); if (isset($attr2['val'])) { $column->setAttribute('val', (string) $attr2['val']); } if (isset($attr2['maxVal'])) { $column->setAttribute('maxVal', (string) $attr2['maxVal']); } } } } private function readTopTenAutoFilter(?SimpleXMLElement $filterColumn, Column $column): void { if (isset($filterColumn, $filterColumn->top10)) { $column->setFilterType(Column::AUTOFILTER_FILTERTYPE_TOPTENFILTER); // We should only ever have one top10 filter foreach ($filterColumn->top10 as $filterRule) { $attr2 = $filterRule->attributes() ?? []; $column->createRule()->setRule( ( ((isset($attr2['percent'])) && ((string) $attr2['percent'] === '1')) ? Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_PERCENT : Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_BY_VALUE ), (string) ($attr2['val'] ?? ''), ( ((isset($attr2['top'])) && ((string) $attr2['top'] === '1')) ? Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_TOP : Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_BOTTOM ) )->setRuleType(Rule::AUTOFILTER_RULETYPE_TOPTENFILTER); } } } }