PHPOffice/PhpSpreadsheet · error · PhpOffice\PhpSpreadsheet\Exception

No wizard exists for this CF rule type

Error message

No wizard exists for this CF rule type

What it means

Wizard::newRule(string $ruleType) is a factory mapping a fixed set of rule-type identifiers to conditional-formatting wizard objects: Wizard::CELL_VALUE ('cellValue'), TEXT_VALUE ('textValue'), BLANKS/NOT_BLANKS, ERRORS/NOT_ERRORS, EXPRESSION/FORMULA, DATES_OCCURRING ('DateValue') and DUPLICATES/UNIQUE. The match expression has no wildcard arm, so any string that is not exactly one of those identifiers throws. Matching is case-sensitive, and the date wizard's identifier is the camel-cased 'DateValue', not 'datesOccurring'.

Source

Thrown at src/PhpSpreadsheet/Style/ConditionalFormatting/Wizard.php:47

    public function __construct(string $cellRange)
    {
        $this->cellRange = $cellRange;
    }

    public function newRule(string $ruleType): WizardInterface
    {
        return match ($ruleType) {
            self::CELL_VALUE => new Wizard\CellValue($this->cellRange),
            self::TEXT_VALUE => new Wizard\TextValue($this->cellRange),
            self::BLANKS => new Wizard\Blanks($this->cellRange, true),
            self::NOT_BLANKS => new Wizard\Blanks($this->cellRange, false),
            self::ERRORS => new Wizard\Errors($this->cellRange, true),
            self::NOT_ERRORS => new Wizard\Errors($this->cellRange, false),
            self::EXPRESSION, self::FORMULA => new Wizard\Expression($this->cellRange),
            self::DATES_OCCURRING => new Wizard\DateValue($this->cellRange),
            self::DUPLICATES => new Wizard\Duplicates($this->cellRange, false),
            self::UNIQUE => new Wizard\Duplicates($this->cellRange, true),
            default => throw new Exception('No wizard exists for this CF rule type'),
        };
    }

    public static function fromConditional(Conditional $conditional, string $cellRange = 'A1'): WizardInterface
    {
        $conditionalType = $conditional->getConditionType();

        return match ($conditionalType) {
            Conditional::CONDITION_CELLIS => Wizard\CellValue::fromConditional($conditional, $cellRange),
            Conditional::CONDITION_CONTAINSTEXT, Conditional::CONDITION_NOTCONTAINSTEXT, Conditional::CONDITION_BEGINSWITH, Conditional::CONDITION_ENDSWITH => Wizard\TextValue::fromConditional($conditional, $cellRange),
            Conditional::CONDITION_CONTAINSBLANKS, Conditional::CONDITION_NOTCONTAINSBLANKS => Wizard\Blanks::fromConditional($conditional, $cellRange),
            Conditional::CONDITION_CONTAINSERRORS, Conditional::CONDITION_NOTCONTAINSERRORS => Wizard\Errors::fromConditional($conditional, $cellRange),
            Conditional::CONDITION_TIMEPERIOD => Wizard\DateValue::fromConditional($conditional, $cellRange),
            Conditional::CONDITION_EXPRESSION => Wizard\Expression::fromConditional($conditional, $cellRange),
            Conditional::CONDITION_DUPLICATES, Conditional::CONDITION_UNIQUE => Wizard\Duplicates::fromConditional($conditional, $cellRange),
            default => throw new Exception('No wizard exists for this CF rule type'),
        };
    }

View on GitHub (pinned to 65b080eef4)

Solutions

  1. Always pass the Wizard class constants: (new Wizard($range))->newRule(Wizard::CELL_VALUE)
  2. Validate dynamic strings against the list of Wizard::* rule-type constants before calling newRule()
  3. If the input is a condition-type string or a Conditional object, use Wizard::fromConditional() which dispatches on condition type
  4. Normalize config keys to exactly the Wizard constant values at load time

Example fix

// before
$ruleType = $config['rule_type'];                  // e.g. 'Cell Value'
$wizard = (new Wizard('A1:E10'))->newRule($ruleType); // throws

// after
use PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting\Wizard;

$map = [
    'cellValue' => Wizard::CELL_VALUE,
    'textValue' => Wizard::TEXT_VALUE,
    'blanks'    => Wizard::BLANKS,
    'errors'    => Wizard::ERRORS,
    'formula'   => Wizard::EXPRESSION,
    'dates'     => Wizard::DATES_OCCURRING,
    'duplicates'=> Wizard::DUPLICATES,
];
$ruleType = $map[$config['rule_type']] ?? Wizard::CELL_VALUE;
$wizard = (new Wizard('A1:E10'))->newRule($ruleType);
Defensive patterns

Strategy: validation

Validate before calling

use PhpOffice\PhpSpreadsheet\Style\ConditionalFormatting\Wizard;

$validRuleTypes = [
    Wizard::CELL_VALUE, Wizard::TEXT_VALUE, Wizard::BLANKS, Wizard::NOT_BLANKS,
    Wizard::ERRORS, Wizard::NOT_ERRORS, Wizard::EXPRESSION, Wizard::FORMULA,
    Wizard::DATES_OCCURRING, Wizard::DUPLICATES, Wizard::UNIQUE,
];
if (!in_array($ruleType, $validRuleTypes, true)) {
    throw new InvalidArgumentException('Unsupported CF rule type: ' . $ruleType);
}
$wizard = (new Wizard($cellRange))->newRule($ruleType);

Try / catch

use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException;

try {
    $wizard = (new Wizard($cellRange))->newRule($ruleType);
} catch (PhpSpreadsheetException $e) {
    // unknown rule type: fall back to a safe default or reject the input
    throw new InvalidArgumentException('Unknown rule type: ' . $ruleType, 0, $e);
}

Prevention

When it happens

Trigger: Passing raw config/UI strings to newRule() without normalization ('Cell Value', 'cellvalue', 'cellIs'); reusing Conditional condition-type strings (e.g. 'cellIs', 'containsText') which are not Wizard identifiers; wrong casing for the date rule such as 'datevalue'.

Common situations: Mapping a YAML/JSON rule config, database column or form dropdown straight into newRule(); copying cfRule type values from xlsx XML into wizard calls; assuming every rule type a UI offers has a wizard.

Related errors


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