PHPOffice/PhpSpreadsheet · error · PhpOffice\PhpSpreadsheet\Calculation\Exception
#VALUE!
#VALUE!
Error message
#VALUE!
What it means
MatrixFunctions::getMatrix() (used by MDETERM, MINVERSE and MMULT) coerces the argument into a 2x2 grid and rejects any cell that is a string or null by throwing Calculation\Exception with ExcelError::VALUE(). Excel matrix functions require a pure numeric matrix, so a single text or blank cell makes the whole function return #VALUE!. Note that even numeric strings count as strings here.
Source
Thrown at src/PhpSpreadsheet/Calculation/MathTrig/MatrixFunctions.php:34
*
* @param mixed $matrixValues A matrix of values
*/
private static function getMatrix(mixed $matrixValues): Matrix
{
$matrixData = [];
if (!is_array($matrixValues)) {
$matrixValues = [[$matrixValues]];
}
$row = 0;
foreach ($matrixValues as $matrixRow) {
if (!is_array($matrixRow)) {
$matrixRow = [$matrixRow];
}
$column = 0;
foreach ($matrixRow as $matrixCell) {
if ((is_string($matrixCell)) || ($matrixCell === null)) {
throw new Exception(ExcelError::VALUE());
}
$matrixData[$row][$column] = $matrixCell;
++$column;
}
++$row;
}
return new Matrix($matrixData);
}
/**
* SEQUENCE.
*
* Generates a list of sequential numbers in an array.
*
* Excel Function:
* SEQUENCE(rows,[columns],[start],[step])
*View on GitHub (pinned to 65b080eef4)
Solutions
- Restrict the range to the numeric block only, excluding headers/labels
- Replace blanks in the source range with 0 (or fill them) so the matrix is fully numeric
- Use =IF(COUNT(A1:B2)=4, MMULT(...), "non-numeric matrix") style guards or ISNUMBER checks per cell when generating formulas
- When calling from PHP, array_map the matrix with a coercion that rejects/filters non-numeric entries first
Example fix
// before: A1:B2 contains a blank cell -> #VALUE!
$sheet->getCell('E1')->setValue('=MINVERSE(A1:B2)');
// after: normalize blanks to 0 first
foreach ($sheet->rangeToArray('A1:B2', null, true, true, false) as $r => $row) {
foreach ($row as $c => $v) {
if ($v === null || is_string($v)) {
$sheet->getCell([$c + 1, $r + 1])->setValue(0);
}
}
} Defensive patterns
Strategy: validation
Validate before calling
// Reject matrices with string/null cells before MMULT/MINVERSE/MDETERM
$flat = [];
array_walk_recursive($matrix, function ($v) use (&$flat) { $flat[] = $v; });
$bad = array_filter($flat, fn ($v) => !is_int($v) && !is_float($v));
if ($bad !== []) {
throw new InvalidArgumentException('matrix contains non-numeric cell');
} Type guard
/** @param array<int,array<int,int|float>> $m */
function isNumericMatrix(array $m): bool
{
foreach ($m as $row) {
foreach ($row as $cell) {
if (!is_int($cell) && !is_float($cell)) return false;
}
}
return true;
} Try / catch
try {
$r = MatrixFunctions::MMULT($a, $b);
} catch (\PhpOffice\PhpSpreadsheet\Calculation\Exception $e) {
$r = $e->getMessage(); // '#VALUE!'
} Prevention
- Select only the numeric block of ranges; exclude header/label rows
- Fill sparse matrices with 0 instead of leaving blanks
- Numeric strings are still strings - cast PHP data to int/float before writing cells
- Add =COUNT(range)=ROWS(range)*COLUMNS(range) sanity checks when generating matrix formulas
When it happens
Trigger: =MMULT(A1:B2, C1:D2) where any referenced cell contains text, a space, or is empty; =MDETERM(A1:B2) with a blank cell; ranges that include header labels; passing a PHP array containing strings/nulls to MatrixFunctions::MMULT() directly.
Common situations: Ranges that accidentally include header rows or annotation text; sparse matrices from database exports where missing entries are blank instead of 0; mixed-type columns where one row holds a note; formulas built dynamically from user-selected ranges that include labels.
Related errors
AI-assisted analysis of PHPOffice/PhpSpreadsheet@65b080eef4 (2026-08-17).
Data as JSON: /api/errors/0d4073b4f2b75599.
Report an issue: GitHub.