PHPOffice/PhpSpreadsheet · error · PhpOffice\PhpSpreadsheet\Exception

Conditional is not a Cell Value CF Rule conditional

Error message

Conditional is not a Cell Value CF Rule conditional

What it means

Wizard\CellValue::fromConditional() rebuilds a CellValue wizard from an existing Conditional, and only CONDITION_CELLIS conditionals qualify - those are the rules built from comparison operators (equal, greaterThan, between, ...). Text, expression, blanks, errors and date rules use different condition types and are rejected up front.

Source

Thrown at src/PhpSpreadsheet/Style/ConditionalFormatting/Wizard/CellValue.php:123

        $conditional->setStyle($this->getStyle());
        $conditional->setStopIfTrue($this->getStopIfTrue());

        return $conditional;
    }

    protected static function unwrapString(string $condition): string
    {
        if ((str_starts_with($condition, '"')) && (str_starts_with(strrev($condition), '"'))) {
            $condition = substr($condition, 1, -1);
        }

        return str_replace('""', '"', $condition);
    }

    public static function fromConditional(Conditional $conditional, string $cellRange = 'A1'): WizardInterface
    {
        if ($conditional->getConditionType() !== Conditional::CONDITION_CELLIS) {
            throw new Exception('Conditional is not a Cell Value CF Rule conditional');
        }

        $wizard = new self($cellRange);
        $wizard->style = $conditional->getStyle();
        $wizard->stopIfTrue = $conditional->getStopIfTrue();

        $wizard->operator = $conditional->getOperatorType();
        $conditions = $conditional->getConditions();
        foreach ($conditions as $index => $condition) {
            // Best-guess to try and identify if the text is a string literal, a cell reference or a formula?
            $operandValueType = Wizard::VALUE_TYPE_LITERAL;
            if (is_string($condition)) {
                if (Calculation::keyInExcelConstants($condition)) {
                    $condition = Calculation::getExcelConstants($condition);
                } elseif (preg_match('/^' . Calculation::CALCULATION_REGEXP_CELLREF_RELATIVE . '$/i', $condition)) {
                    $operandValueType = Wizard::VALUE_TYPE_CELL;
                    $condition = self::reverseAdjustCellRef($condition, $cellRange);
                } elseif (

View on GitHub (pinned to 65b080eef4)

Solutions

  1. Check $conditional->getConditionType() === Conditional::CONDITION_CELLIS first
  2. Use Wizard::fromConditional() to dispatch to the correct wizard automatically
  3. For formula-style comparisons, use Wizard\Expression::fromConditional() instead
  4. Guard batch loops with try/catch to skip non-cellIs rules

Example fix

// before
$wizard = Wizard\CellValue::fromConditional($conditional); // throws unless type is cellIs

// after
use PhpOffice\PhpSpreadsheet\Style\Conditional;

if ($conditional->getConditionType() === Conditional::CONDITION_CELLIS) {
    $wizard = Wizard\CellValue::fromConditional($conditional);
} else {
    $wizard = Wizard::fromConditional($conditional); // dispatches on actual type
}
Defensive patterns

Strategy: type-guard

Validate before calling

use PhpOffice\PhpSpreadsheet\Style\Conditional;

if ($conditional->getConditionType() === Conditional::CONDITION_CELLIS) {
    $wizard = Wizard\CellValue::fromConditional($conditional, $cellRange);
} else {
    $wizard = Wizard::fromConditional($conditional, $cellRange);
}

Type guard

function isCellValueConditional(Conditional $conditional): bool
{
    return $conditional->getConditionType() === Conditional::CONDITION_CELLIS;
}

Try / catch

use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException;

try {
    $wizard = Wizard\CellValue::fromConditional($conditional, $cellRange);
} catch (PhpSpreadsheetException $e) {
    $wizard = Wizard::fromConditional($conditional, $cellRange);
}

Prevention

When it happens

Trigger: Passing a Conditional whose getConditionType() is containsText, expression, timePeriod, containsBlanks, containsErrors, etc. to CellValue::fromConditional(); iterating mixed rules with a hard-coded CellValue factory call.

Common situations: Generic 'edit existing rule' UIs that pick the wrong wizard class; converting rules loaded from files where the condition type is unknown; copy-pasted conversion pipelines that never check the type.

Related errors


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