Skip to content
MNB PHPExcelDeveloper Guide
AI

Reading workbooks

Read Excel Files in PHP Step by Step

Read Excel files in PHP step by step: choose a package, inspect the workbook, select a sheet, configure rows, consume results, and handle failures.

Level
Beginner
Reading time
24 min
Package
mnb/mnb-phpexcel or mnb/mnb-phpexcel-xlsx
Updated
PHP 8.1+Full packageIndividual XLSXStreaming
Available sincev2.0.3Last API changev2.0.5Version guide
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()

Choose a package and open the workbook#

  1. 01Choose & openPackage, entry class, file validation
  2. 02Inspect & selectMetadata, sheets, active fallback
  3. 03ConfigureHeaders, empty rows, limits
  4. 04ConsumeRows, arrays, cells, summaries
  5. 05ValidateResult checks and exceptions
Start with one entry point

The full package and focused XLSX package lead to the same read-session API after the workbook is opened. Pick one installation model and keep that boundary explicit.

read.php
// Install: composer require mnb/mnb-phpexcel:^2.0

use Mnb\PHPExcel\MnbExcel;
use Mnb\PHPExcel\Support\MnbExcelException;

$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);

Package rule: use MnbExcel with the complete package or Xlsx with the individual XLSX package. Do not mix the entry classes in one example or service boundary.

Inspect before selecting business data#

Workbook discovery

Use metadata and sheet discovery before assuming a worksheet name. This keeps uploads, optional tabs, and active-sheet fallbacks predictable.

01Inspect

Check status, format, encryption, warnings, errors, and worksheet metadata.

inspect()
02List

Show available worksheet names before choosing one.

sheetNames()
03Select

Require a known sheet or intentionally use the workbook active sheet.

hasSheet() activeSheet()
04Fallback

Use a nullable lookup only when fallback behavior is part of the application contract.

sheetIfExists()
Inspect and select
$metadata = $workbook->inspect();
$sheetNames = $workbook->sheetNames();
$active = $workbook->activeSheetInfo();

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

$requiredSheet = 'ALL_PARAMETERS';

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

print_r([
    'format' => $metadata['format'] ?? 'xlsx',
    'encrypted' => $metadata['encrypted'] ?? false,
    'sheets' => $sheetNames,
    'active_sheet' => $active['name'] ?? null,
]);

Indexing rule: worksheet numbers are 1-based. PHP arrays returned later are 0-based, so keep worksheet position and returned-row position conceptually separate.

Configure one read session#

Configuration phase

Describe the read before executing it.

Header selection, empty-row policy, limits, ranges, and projections belong on the session. Keep configuration together so the terminal operation sees one coherent policy.

Headers
withHeaderRow(1)
Empty rows
skip_empty_rows
Safety limit
max_rows
Projection
selectColumns()
Configure and inspect the session
$session = $sheet
    ->withHeaderRow(1)
    ->withOptions([
        'skip_empty_rows' => true,
        'max_rows' => 5000,
    ]);

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

$rowCount = $session->countRows();
$firstRow = $session->first();

Return-type rule: configuration methods keep returning a read session. Methods such as rows(), toArray(), first(), and countRows() are terminal operations and return another type.

Choose the smallest result your task needs#

Process many recordsrows()Yield rows incrementally instead of collecting the complete result.
Read one recordfirst()Stop after the first normalized data row.
Small in-memory datasettoArray()Return a native PHP array for indexing, count(), and array_column().
Only selected fieldsselectColumns()Project columns before the terminal read instead of discarding data afterward.
Fixed workbook coordinatecell("B2")Read an exact Excel cell without depending on the returned row array.
Audit row countstoStructuredSheetArray()Return rows plus source, empty, skipped, header, and final returned counts.
rows.php
foreach ($session->rows() as $row) {
    echo $row['Email'] ?? '';
}

Performance rule: the examples are separate for learning. In production, avoid calling several terminal methods just to inspect the same data; each terminal operation can require another worksheet pass.

Finish with validation and boundary-level error handling#

  1. 01
    Validate the file

    Confirm the path exists, is readable, and is not zero bytes.

  2. 02
    Inspect once

    Review workbook metadata and available sheets before processing business rows.

  3. 03
    Select explicitly

    Require the expected sheet or document an intentional active-sheet fallback.

  4. 04
    Configure once

    Apply headers, empty-row behavior, ranges, limits, and projections together.

  5. 05
    Execute one useful result

    Stream, collect, count, read one row, or request structured output according to the job.

  6. 06
    Handle failures at the boundary

    Return safe application messages while retaining detailed diagnostics for logs.

Application boundary
try {
    $sheet = $workbook->sheet('ALL_PARAMETERS');

    foreach ($sheet->withHeaderRow(1)->rows() as $row) {
        // Validate and process each row.
    }
} catch (MnbExcelException $error) {
    // Log detailed diagnostics server-side.
    error_log(json_encode($error->toErrorArray(debug: true)));

    // Return a safe application-level message.
    echo 'The workbook could not be processed.';
} catch (RuntimeException $error) {
    echo $error->getMessage();
}

Production rule: keep file validation, workbook selection, session configuration, terminal execution, and exception handling as visible boundaries. That structure makes spreadsheet imports much easier to review and debug.