PHPOffice/PhpSpreadsheet · error · PhpOffice\PhpSpreadsheet\Calculation\Exception

#NUM!

#NUM!

Error message

#NUM!

What it means

SheetView::setView() accepts exactly three layout types - SheetView::SHEETVIEW_NORMAL ('normal'), SHEETVIEW_PAGE_LAYOUT ('pageLayout'), SHEETVIEW_PAGE_BREAK_PREVIEW ('pageBreakPreview') - or null, which is normalized to 'normal'. Anything else throws 'Invalid sheetview layout type.' because the values must match the OOXML sheetView view attribute. The match is exact, so casing and spelling matter.

Source

Thrown at src/PhpSpreadsheet/Calculation/DateTimeExcel/Difference.php:74

        $PHPDiffDateObject = $PHPEndDateObject->diff($PHPStartDateObject);

        $retVal = false;
        $retVal = self::replaceRetValue($retVal, $unit, 'D') ?? self::datedifD($difference);
        $retVal = self::replaceRetValue($retVal, $unit, 'M') ?? self::datedifM($PHPDiffDateObject);
        $retVal = self::replaceRetValue($retVal, $unit, 'MD') ?? self::datedifMD($startDays, $endDays, $PHPEndDateObject, $PHPDiffDateObject);
        $retVal = self::replaceRetValue($retVal, $unit, 'Y') ?? self::datedifY($PHPDiffDateObject);
        $retVal = self::replaceRetValue($retVal, $unit, 'YD') ?? self::datedifYD($difference, $startYears, $endYears, $PHPStartDateObject, $PHPEndDateObject);
        $retVal = self::replaceRetValue($retVal, $unit, 'YM') ?? self::datedifYM($PHPDiffDateObject);

        return is_bool($retVal) ? ExcelError::VALUE() : $retVal;
    }

    private static function initialDiff(float $startDate, float $endDate): float
    {
        // Validate parameters
        if ($startDate > $endDate) {
            throw new Exception(ExcelError::NAN());
        }

        return $endDate - $startDate;
    }

    /**
     * Decide whether it's time to set retVal.
     */
    private static function replaceRetValue(bool|int $retVal, string $unit, string $compare): null|bool|int
    {
        if ($retVal !== false || $unit !== $compare) {
            return $retVal;
        }

        return null;
    }

    private static function datedifD(float $difference): int

View on GitHub (pinned to 65b080eef4)

Solutions

  1. Use the constants: setView(SheetView::SHEETVIEW_PAGE_BREAK_PREVIEW)
  2. Map/whitelist external values to the three constants before calling
  3. Pass null when you want the default normal view

Example fix

// before
$sheet->getSheetView()->setView('PageLayout'); // wrong case -> exception

// after
use PhpOffice\PhpSpreadsheet\Worksheet\SheetView;
$sheet->getSheetView()->setView(SheetView::SHEETVIEW_PAGE_LAYOUT);
Defensive patterns

Strategy: type-guard

Validate before calling

$allowed = [SheetView::SHEETVIEW_NORMAL, SheetView::SHEETVIEW_PAGE_LAYOUT, SheetView::SHEETVIEW_PAGE_BREAK_PREVIEW];
$viewType = in_array($candidate, $allowed, true) ? $candidate : null; // null -> normal
$sheet->getSheetView()->setView($viewType);

Type guard

function isValidSheetViewType(?string $type): bool
{
    return in_array($type, ['normal', 'pageLayout', 'pageBreakPreview'], true);
}

Try / catch

try {
    $sheet->getSheetView()->setView($viewType);
} catch (\PhpOffice\PhpSpreadsheet\Exception $e) {
    $sheet->getSheetView()->setView(null); // default to normal
}

Prevention

When it happens

Trigger: setView('PageLayout') (wrong case), setView('pagebreakpreview'), setView('page_break_preview'), or forwarding a view name produced by another library, a config file, or a legacy PHPExcel codebase into this setter.

Common situations: Hardcoded strings instead of the class constants; user- or config-supplied view names; uppercase or underscore variants that 'look right' but are not the exact OOXML token.

Related errors


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