PHPOffice/PhpSpreadsheet · error · PhpOffice\PhpSpreadsheet\Exception

Invalid grouping for column AutoFilter Rule.

Error message

Invalid grouping for column AutoFilter Rule.

What it means

Rule::setGrouping() accepts three disjoint sets: the date/time group names (year, month, day, hour, minute, second), the dynamic filter names (yesterday ... belowAverage, M1-M12, Q1-Q4), and the top-ten types ('top', 'bottom'). Any other string is rejected.

Source

Thrown at src/PhpSpreadsheet/Worksheet/AutoFilter/Column/Rule.php:337

    public function getGrouping(): string
    {
        return $this->grouping;
    }

    /**
     * Set AutoFilter Rule Grouping.
     *
     * @return $this
     */
    public function setGrouping(string $grouping): static
    {
        $this->setEvaluatedFalse();
        if (
            (!in_array($grouping, self::DATE_TIME_GROUPS))
            && (!in_array($grouping, self::DYNAMIC_TYPES))
            && (!in_array($grouping, self::TOP_TEN_TYPE))
        ) {
            throw new PhpSpreadsheetException('Invalid grouping for column AutoFilter Rule.');
        }
        $this->grouping = $grouping;

        return $this;
    }

    /**
     * Set AutoFilter Rule.
     *
     * @param string $operator see self::AUTOFILTER_COLUMN_RULE_*
     * @param int|int[]|string|string[] $value
     *
     * @return $this
     */
    public function setRule(string $operator, $value, ?string $grouping = null): static
    {
        $this->setEvaluatedFalse();
        $this->setOperator($operator);

View on GitHub (pinned to 65b080eef4)

Solutions

  1. Use the Rule constants: AUTOFILTER_RULETYPE_DATEGROUP_* for date groups, AUTOFILTER_RULETYPE_DYNAMIC_* for dynamic filters, AUTOFILTER_COLUMN_RULE_TOPTEN_TOP/BOTTOM for top-ten
  2. Note that setGrouping does not lowercase input — pass exact lowercase values when mapping from external data

Example fix

// before
$rule->setGrouping('month of year');

// after
$rule->setGrouping(\PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::AUTOFILTER_RULETYPE_DATEGROUP_MONTH);
Defensive patterns

Strategy: validation

Validate before calling

use PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule;
$valid = array_merge(
    ['year', 'month', 'day', 'hour', 'minute', 'second'], // date groups
    ['top', 'bottom'], // top-ten types
    array_map(fn ($c) => constant(Rule::class . '::' . $c), preg_grep('/^AUTOFILTER_RULETYPE_DYNAMIC_/', array_keys((new ReflectionClass(Rule::class))->getConstants())))
);
if (!in_array(strtolower($grouping), $valid, true)) {
    throw new InvalidArgumentException("Unknown grouping '$grouping'");
}
$rule->setGrouping(strtolower($grouping));

Type guard

function isValidRuleGrouping(string $grouping): bool
{
    static $valid;
    $valid ??= array_merge(
        ['year', 'month', 'day', 'hour', 'minute', 'second', 'top', 'bottom'],
        array_values(array_filter(
            array_map(fn ($v) => is_string($v) ? $v : null,
                (new ReflectionClass(\PhpOffice\PhpSpreadsheet\Worksheet\AutoFilter\Column\Rule::class))->getConstants()),
            fn ($v) => is_string($v) && preg_match('/^(yesterday|today|tomorrow|yearToDate|(this|last|next)(Year|Quarter|Month|Week)|M([1-9]|1[0-2])|Q[1-4]|aboveAverage|belowAverage)$/', $v)
        ))
    );

    return in_array(strtolower($grouping), $valid, true);
}

Try / catch

try {
    $rule->setGrouping($grouping);
} catch (\PhpOffice\PhpSpreadsheet\Exception $e) {
    $rule->setGrouping(Rule::AUTOFILTER_RULETYPE_DATEGROUP_MONTH);
}

Prevention

When it happens

Trigger: ->setGrouping('weekly'), ->setGrouping('Top') (case matters — the input is not lowercased) or ->setGrouping('quarter').

Common situations: Hand-written grouping strings with wrong casing or invented names; values copied from Excel UI labels ('Top 10') rather than the internal tokens.

Related errors


AI-assisted analysis of PHPOffice/PhpSpreadsheet@65b080eef4 (2026-08-17). Data as JSON: /api/errors/fbbfa0ee89b3ac82. Report an issue: GitHub.