MNB PHPExcelDeveloper Guide
Reading workbooks

Read Excel Step by Step

Read Excel step by step: install a package, inspect metadata, select sheets, stream rows, access columns and cells, and report structured counts.

Updated

PHP 8.1+Full packageIndividual XLSXStreaming
Available sincev2.0.3Last API changev2.0.5Version guide
LevelBeginnerReading time24 minPackagemnb/mnb-phpexcel or mnb/mnb-phpexcel-xlsx
MnbExcel::read()Xlsx::read()ReadSession::inspect()ReadSession::sheetNames()ReadSession::activeSheet()ReadSession::hasSheet()ReadSession::sheetIfExists()ReadSession::withHeaderRow()ReadSession::isEmpty()ReadSession::countRows()ReadSession::rows()ReadSession::toArray()ReadSession::first()ReadSession::selectColumns()ReadSession::cell()ReadSession::toStructuredSheetArray()

What you will learn

  • Choose either the full package or the individual XLSX package without mixing entry classes.
  • Inspect and validate a workbook before reading business data.
  • Move from sheets to rows, columns, array indexes, direct cells, and structured summaries in a predictable order.

1. Install the package#

Terminal
composer require mnb/mnb-phpexcel:^2.0

Choose one installation mode. The full package includes the facade and all supported modules. The individual package installs only the XLSX implementation and its declared dependencies.

2. Import the correct entry class#

index.php
use Mnb\PHPExcel\MnbExcel;
use Mnb\PHPExcel\Support\MnbExcelException;

3. Open the workbook#

index.php
$path = __DIR__ . '/excels/excel1.xlsx';

if (!is_file($path) || filesize($path) === 0) {
    throw new RuntimeException('The Excel file is missing or empty.');
}

$workbook = MnbExcel::read($path);

All remaining examples use the shared $workbook variable.

4. Inspect workbook metadata#

PHP
$metadata = $workbook->inspect();

print_r([
    'status' => $metadata['status'] ?? null,
    'file' => $metadata['file'] ?? $path,
    'size_bytes' => $metadata['size_bytes'] ?? null,
    'format' => $metadata['format'] ?? 'xlsx',
    'encrypted' => $metadata['encrypted'] ?? false,
    'sheet_count' => count($metadata['sheets'] ?? []),
    'warnings' => $metadata['warnings'] ?? [],
    'errors' => $metadata['errors'] ?? [],
]);

Inspection is the best first step for upload previews because it reports package status and worksheet metadata without first collecting every row into memory.

5. List worksheet names#

PHP
$sheetNames = $workbook->sheetNames();

if ($sheetNames === []) {
    throw new RuntimeException('The workbook has no readable worksheets.');
}

foreach ($sheetNames as $index => $name) {
    printf("%d. %s\n", $index + 1, $name);
}

Worksheet numbers in the library are 1-based, while PHP array indexes are 0-based.

6. Get the active worksheet#

PHP
$active = $workbook->activeSheetInfo();

echo 'Active sheet name: ' . $active['name'] . PHP_EOL;
echo 'Active sheet number: ' . $active['index'] . PHP_EOL;

$activeSheet = $workbook->activeSheet();

For XLSX, the active worksheet follows Excel workbook metadata. When that metadata is unavailable, the first readable worksheet is used.

7. Check whether a worksheet exists#

PHP
$requiredSheet = 'ALL_PARAMETERS';

if (!$workbook->hasSheet($requiredSheet)) {
    printf(
        "Worksheet %s was not found. Available: %s\n",
        $requiredSheet,
        implode(', ', $sheetNames)
    );
}

8. Select a worksheet safely#

PHP
$sheet = $workbook->sheetIfExists('ALL_PARAMETERS')
    ?? $workbook->activeSheet();

Use sheet() when the worksheet is mandatory and a missing name must throw an exception. Use sheetIfExists() when fallback behavior is intentional.

9. Configure headers and row options#

PHP
$session = $sheet
    ->withHeaderRow(1)
    ->withOptions([
        'skip_empty_rows' => true,
        'max_rows' => 5000,
    ]);

Configuration methods return a read session. Keep this session until you deliberately call a terminal method such as toArray() or toStructuredSheetArray().

10. Check whether the worksheet is empty#

PHP
if ($session->isEmpty()) {
    echo 'No data rows were found after applying the header and filters.';
    return;
}

// Equivalent positive check:
if (!$session->hasRows()) {
    return;
}

A header-only worksheet is considered empty after withHeaderRow(1). Empty checks use the current header, range, filter, projection, offset, limit, and skip-empty settings.

11. Count final data rows#

PHP
$returnedRowCount = $session->countRows();

echo 'Final data rows: ' . $returnedRowCount . PHP_EOL;

12. Stream rows#

PHP
foreach ($session->rows() as $row) {
    print_r($row);
}

Streaming is the preferred choice for large files because rows are yielded one at a time.

13. Convert rows to an array#

PHP
$rows = $session->toArray();

if ($rows === []) {
    echo 'No rows were returned.';
}

14. Read one row#

PHP
$firstRow = $session->first();

if ($firstRow !== null) {
    print_r($firstRow);
}

15. Read one column#

PHP
$emails = array_column($rows, 'Email');

foreach ($emails as $email) {
    echo $email . PHP_EOL;
}

Header names are case-sensitive array keys after normalization, so use the exact key returned by your header row.

16. Access $rows[$row][$column]#

PHP
$rowIndex = 0;          // First returned data row.
$columnName = 'Email';  // Header key.

$email = $rows[$rowIndex][$columnName] ?? null;

// Example: fifth returned row, Customer ID column.
$customerId = $rows[4]['Customer ID'] ?? null;

The first array index is zero-based and refers to returned data, not necessarily the physical Excel row number. Header, empty-row, range, offset, and filter options can change that relationship.

17. Read a direct Excel cell such as B2#

PHP
$value = $sheet->cell('B2');

echo 'B2: ' . (string) $value . PHP_EOL;

Direct cell access uses Excel coordinates and does not depend on the collected $rows array. This is useful for lookup-style workbooks, totals, and fixed report fields.

18. Read structured output and row counts#

PHP
$structured = $sheet->toStructuredSheetArray([
    'header_row' => 1,
    'skip_empty_rows' => true,
    'include_cell_metadata' => false,
    'row_format' => 'flat',
]);

$counts = $structured['summary']['row_counts'];

print_r([
    'total_logical_rows' => $counts['total'],
    'stored_row_records' => $counts['source_records'],
    'non_empty_rows' => $counts['non_empty'],
    'empty_rows' => $counts['empty'],
    'explicit_empty_rows' => $counts['explicit_empty'],
    'implicit_sparse_rows' => $counts['implicit_empty'],
    'skipped_empty_rows' => $counts['skipped_empty'],
    'header_rows' => $counts['header'],
    'final_returned_rows' => $counts['returned'],
]);

foreach ($structured['rows'] as $row) {
    print_r($row);
}

19. Handle exceptions#

PHP
try {
    // Create $workbook using the Full package or Individual XLSX tab above.
    $sheet = $workbook->sheet('ALL_PARAMETERS');
    $rows = $sheet->withHeaderRow(1)->toArray();
} catch (MnbExcelException $error) {
    print_r($error->toErrorArray(debug: true));
} catch (RuntimeException $error) {
    echo $error->getMessage();
}

Catch MnbExcelException at your application boundary to show actionable library messages without exposing a raw vendor stack trace to users.

  1. Validate the file
    Check that it exists, is readable, and is not zero bytes.
  2. Inspect once
    Review metadata and worksheet names before selecting data.
  3. Select explicitly
    Use a required sheet or an intentional active-sheet fallback.
  4. Configure once
    Apply headers, empty-row behavior, ranges, limits, and projections to a session.
  5. Choose one consumption method
    Stream, count, read the first row, collect an array, or build structured output according to the task.
  6. Handle failures at the boundary
    Catch MNB exceptions and log debug context server-side.