Fast PHP Excel Library for Large Files
Use MNB PHPExcel as a fast, lightweight and memory-efficient PHP XLSX reader with forward-only rows, stream chunk processing and selective column reads.
Updated
PHP 8.1+Individual XLSXStreamingLow memory
MnbExcel::read()MnbExcel::largeRead()ReadSession::rows()LargeXlsxReadSession::chunk()ReadSession::selectColumns()What you will learn
- Choose between the full package and the individual XLSX package.
- Stream worksheet rows without collecting the complete workbook into a PHP array.
- Process predictable chunks and measure peak memory with your own production files.
Choose the package entry point#
composer require mnb/mnb-phpexcel:^2.0composer require mnb/mnb-phpexcel-xlsx:^2.0The full package provides the MnbExcel facade and large-file helpers. The individual XLSX package keeps the install focused and uses Mnb\PHPExcel\Format\Xlsx.
Stream rows instead of building one large array#
<?php
use Mnb\PHPExcel\MnbExcel;
$sheet = MnbExcel::read(__DIR__ . '/orders.xlsx')
->sheetOrActive('Orders')
->withHeaderRow(1)
->withOptions([
'skip_empty_rows' => true,
'include_cell_metadata' => false,
])
->selectColumns(['Order ID', 'Customer', 'Amount']);
foreach ($sheet->rows() as $row) {
processOrder($row);
}<?php
use Mnb\PHPExcel\Format\Xlsx;
$sheet = Xlsx::read(__DIR__ . '/orders.xlsx')
->sheetOrActive('Orders')
->withHeaderRow(1)
->withOptions([
'skip_empty_rows' => true,
'include_cell_metadata' => false,
])
->selectColumns(['Order ID', 'Customer', 'Amount']);
foreach ($sheet->rows() as $row) {
processOrder($row);
}Use the PHP Excel stream chunk reader#
<?php
use Mnb\PHPExcel\MnbExcel;
MnbExcel::largeRead(__DIR__ . '/orders.xlsx')
->sheet('Orders')
->withHeader()
->onlyColumns(['Order ID', 'Customer', 'Amount'])
->memoryGuardRatio(0.80)
->chunk(1000, function (array $rows, array $state): void {
importOrderBatch($rows);
printf("Processed %d rows\n", $state['rows_read'] ?? 0);
});<?php
use Mnb\PHPExcel\Format\Xlsx;
$rows = Xlsx::read(__DIR__ . '/orders.xlsx')
->sheetOrActive('Orders')
->withHeaderRow(1)
->withOptions(['skip_empty_rows' => true])
->rows();
$batch = [];
foreach ($rows as $row) {
$batch[] = $row;
if (count($batch) === 1000) {
importOrderBatch($batch);
$batch = [];
}
}
if ($batch !== []) {
importOrderBatch($batch);
}Measure peak memory and elapsed time#
<?php
$startedAt = hrtime(true);
$startingMemory = memory_get_usage(true);
$rowCount = 0;
foreach ($sheet->rows() as $row) {
++$rowCount;
processOrder($row);
}
$result = [
'rows' => $rowCount,
'seconds' => round((hrtime(true) - $startedAt) / 1_000_000_000, 3),
'memory_delta_mb' => round((memory_get_usage(true) - $startingMemory) / 1048576, 2),
'peak_memory_mb' => round(memory_get_peak_usage(true) / 1048576, 2),
];
print_r($result);Run each benchmark in a fresh PHP process. PHP peak-memory counters are process-wide, so comparing multiple libraries inside one process can produce misleading results.
Keep the large-file path lightweight#
- Use
rows()orlargeRead()instead oftoArray()for unbounded files. - Select only the columns required by the import or report.
- Disable cell metadata when values are sufficient.
- Install
ext-zipandext-xmlreaderfor the strongest streaming path. - Process and persist each batch before requesting the next batch.
- Benchmark with representative formulas, shared strings, dates and row widths—not only row count.
For a fair side-by-side test, continue to MNB PHPExcel vs PhpSpreadsheet performance benchmark.
Was this guide useful?Use GitHub issues for corrections, missing examples, or unclear behavior.
Open an issue