PHPOffice/PhpSpreadsheet · error · PhpOffice\PhpSpreadsheet\Reader\Exception
Not a cell range address
Error message
Not a cell range address
What it means
While decoding a fixed 6-byte BIFF5 cell-range record (1-byte column fields, 2-byte row fields), first row > last row or first column > last column. Excel always stores ranges ordered, so an inverted range means the bytes are not really a range record (misaligned stream) or are corrupt.
Source
Thrown at src/PhpSpreadsheet/Reader/Xls/Biff5.php:32
* section 2.5.14.
*/
public static function readBIFF5CellRangeAddressFixed(string $subData): string
{
// offset: 0; size: 2; index to first row
$fr = self::getUInt2d($subData, 0) + 1;
// offset: 2; size: 2; index to last row
$lr = self::getUInt2d($subData, 2) + 1;
// offset: 4; size: 1; index to first column
$fc = ord($subData[4]);
// offset: 5; size: 1; index to last column
$lc = ord($subData[5]);
// check values
if ($fr > $lr || $fc > $lc) {
throw new ReaderException('Not a cell range address');
}
// column index to letter
$fc = Coordinate::stringFromColumnIndex($fc + 1);
$lc = Coordinate::stringFromColumnIndex($lc + 1);
if ($fr == $lr && $fc == $lc) {
return "$fc$fr";
}
return "$fc$fr:$lc$lr";
}
/**
* Read BIFF5 cell range address list
* section 2.5.15.
*
* @return array{size: int, cellRangeAddresses: string[]}View on GitHub (pinned to 65b080eef4)
Solutions
- Round-trip the file through Excel or LibreOffice (convert to .xlsx) so structures get rewritten cleanly
- Verify the file opens in Excel; if not, treat it as corrupt and obtain a fresh export
- If only values are needed, load with setReadDataOnly(true) so many range-bearing records are skipped
Defensive patterns
Strategy: try-catch
Try / catch
try {
$spreadsheet = IOFactory::load($path);
} catch (\PhpOffice\PhpSpreadsheet\Reader\Exception $e) {
if (str_contains($e->getMessage(), 'Not a cell range address')) {
// convert via LibreOffice to rebuild range records, then retry
}
} Prevention
- Normalize legacy BIFF5 files through conversion before parsing
- Verify uploads open in Excel as an acceptance test
- Use setReadDataOnly(true) when range-bearing metadata is irrelevant
When it happens
Trigger: Reading an .xls where an earlier record had a wrong length so subsequent records are parsed at the wrong offsets; genuinely damaged range structures in BIFF5 (Excel 5/95) files; 0xFFFF sentinel values in deleted ranges.
Common situations: Excel 5/95-era files with unusual or corrupt internal structures; files from archaic exporters; uploads that were truncated or byte-mangled.
Related errors
- Not a cell range address
- Unknown codepage: ${codepage}
- Unexpected file pass record length
- Unsupported encryption algorithm
- Decryption password incorrect
AI-assisted analysis of PHPOffice/PhpSpreadsheet@65b080eef4 (2026-08-17).
Data as JSON: /api/errors/94e066694151ff92.
Report an issue: GitHub.