MNB PHPExcelDeveloper Guide
Production guide

Troubleshoot by Symptom

Start from the error or unexpected result you see, confirm the likely cause, and apply the shortest safe fix.

Updated

Full packageIndividual packagesError codesProduction guidance
Available sincev2.0.3Last API changev2.0.5Version guide
LevelAll levelsReading time14 minPackageAny installed MNB PHPExcel package

What you will learn

  • Diagnose problems from the visible symptom rather than an internal class name.
  • Confirm whether installed Composer code matches the expected release.
  • Choose a safe fix without exposing vendor paths or stack traces to users.

Find the symptom first#

Class not found#

Symptom

PHP reports that Mnb\PHPExcel\MnbExcel or Mnb\PHPExcel\Format\Xlsx does not exist.

Confirm and fix
  1. Run composer show mnb/* in the same project directory as the failing script.
  2. Confirm the script requires the project’s vendor/autoload.php.
  3. Use MnbExcel only with the full package; use Format\Xlsx with the individual XLSX package.
Terminal
composer show mnb/*
composer dump-autoload -o

Composer has old code#

Symptom

GitHub main contains a fix, but the installed package still shows the previous implementation.

Confirm and fix
  1. Check the installed and locked versions with composer show.
  2. Remember that a published tag is immutable; commits added after v2.0.0 are not part of that release.
  3. Publish a new patch tag and update the package with dependencies.
Terminal
composer show mnb/mnb-phpexcel-core
composer show mnb/mnb-phpexcel-core --locked
composer update mnb/mnb-phpexcel-core -W

XMLReader or libxml error#

Symptom

The stack mentions Support\Xml\XmlReader, isEmptyElement, or “Failed to read property due to libxml error”.

Confirm and fix
  1. Verify the installed Core version contains the native XMLReader initialization fix.
  2. Check php -m for libxml and preferably xmlreader.
  3. Confirm Apache and the command-line terminal use the same PHP installation.
verify-core-fix.php
$path = 'vendor/mnb/mnb-phpexcel-core/src/Support/Xml/XmlReader.php';

$source = file_get_contents($path);
var_dump(str_contains($source, 'resetPublicState'));

Worksheet selection fails#

Symptom

You see an empty-name, zero-index, or worksheet-not-found exception.

Confirm and fix
  1. Call sheetNames() before assuming a visible worksheet name.
  2. Use sheet(1) for the first worksheet; worksheet numbers are 1-based.
  3. Use sheetIfExists() for optional input or sheetOrActive() when null/empty input should select the active worksheet.
safe-sheet-selection.php
$workbook = MnbExcel::read($path);
print_r($workbook->sheetNames());

$sheet = $workbook->sheetIfExists($requestedSheet)
    ?? $workbook->activeSheet();

No rows are returned#

Symptom

The workbook opens, but rows() yields nothing or toArray() returns [].

Confirm and fix
  1. Confirm the selected worksheet and physical header row.
  2. Temporarily remove limits, ranges, filters, and projections.
  3. Use structured output to compare source records, empty rows, header rows, and returned rows.
inspect-row-counts.php
$data = $sheet->toStructuredSheetArray([
    'header_row' => 1,
    'skip_empty_rows' => true,
    'row_format' => 'flat',
]);

print_r($data['summary']['row_counts']);

Method called on array#

Symptom

PHP reports “Call to a member function isEmpty() on array” or a similar programming error.

Confirm and fix
  1. toArray() and toStructuredSheetArray() are terminal methods.
  2. Call isEmpty(), hasRows(), or rows() on ReadSession before conversion.
  3. After conversion, use native array checks such as $rows === [].
correct-session-boundary.php
$session = $sheet->withHeaderRow(1);

if ($session->isEmpty()) {
    return;
}

$rows = $session->toArray();

Row counts look wrong#

Symptom

The physical row number, stored row count, skipped rows, and final array count do not match.

Confirm and fix
  1. total includes logical positions and sparse row gaps.
  2. source_records counts rows physically represented in the source.
  3. returned is the final business-row count after header and empty-row processing.
CountMeaning
totalLogical row positions from the first through last selected row.
source_recordsRows physically represented by source records.
emptyExplicit empty records plus implicit sparse gaps.
skipped_emptyExplicit empty records removed by the active option.
headerHeader rows consumed before business data is returned.
returnedFinal rows available in $data['rows'].

Memory limit exceeded#

Symptom

PHP stops with an allowed-memory-size error while reading a large workbook.

Confirm and fix
  1. Use rows() or chunks(), not toArray().
  2. Select only required columns and set a row range or maximum rows.
  3. Enable ext-zip and ext-xmlreader for the native forward-only XLSX path.
bounded-memory-read.php
$session = MnbExcel::read($path)
    ->sheet('Orders')
    ->withHeaderRow(1)
    ->selectColumns(['Order ID', 'Customer', 'Amount']);

foreach ($session->chunks(1000) as $rows) {
    processBatch($rows);
}

Downloaded XLSX is corrupt#

Symptom

Excel reports that the downloaded file is damaged, or the file begins with HTML/error text.

Confirm and fix
  1. Save and validate the workbook before sending HTTP headers.
  2. Clear output buffers so notices, whitespace, and templates cannot precede the binary bytes.
  3. Send the exact content type and length, stream the file, then exit.
download.php
while (ob_get_level() > 0) {
    ob_end_clean();
}

header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Length: ' . filesize($path));
header('Content-Disposition: attachment; filename="report.xlsx"');
readfile($path);
exit;