FastExcelReader: обзор быстрого ридера Excel и CSV для PHP

aVadim 20.03.2026 00:00

Если вам нужно прочитать данные из Excel-файла в PHP, первое, что предложит поисковик, — PhpSpreadsheet. Это мощная библиотека, но за универсальность она платит скоростью и памятью: даже небольшие файлы «съедают» сотни мегабайт, а большие не читаются вовсе. Если ваша задача — именно прочитать данные (импорт, интеграция, миграция), а не редактировать книгу, есть инструмент точнее: avadim/fast-excel-reader. Разберём, что он умеет.

Что это за библиотека

FastExcelReader — часть семейства FastExcelPhp (рядом — FastExcelWriter для записи, FastExcelTemplator для шаблонов и FastExcelLaravel). Её философия: только чтение, зато очень быстрое и экономное. Работает на PHP 7.4+, ставится одной командой:

bash
composer require avadim/fast-excel-reader

Поддерживаемые форматы в 3.0.0 — XLSX (Office 2007+) и CSV.

Главная архитектурная особенность — потоковое чтение. Библиотека не строит в памяти объектную модель книги: XML листа разбирается через XMLReader узел за узлом, а строки отдаются генератором. В памяти в каждый момент — только текущая строка, поэтому файл на 500 000 строк требует примерно столько же памяти, сколько файл на 5 000.

Быстрый старт

php
use avadim\FastExcelReader\Excel;

$excel = Excel::open('report.xlsx');

// весь лист в массив (для небольших файлов)
$rows = $excel->readRows();

// или построчно через генератор (для любых файлов)
$sheet = $excel->sheet();
foreach ($sheet->nextRow() as $rowNum => $rowData) {
    // $rowData = ['A' => ..., 'B' => ...]
}

Несколько листов? Есть выбор по имени и итерация по всем:

php
$excel->getSheetNames();          // имена всех листов
$excel->selectSheet('Прайс');     // выбрать лист по имени

Удобные ключи результата

Буквы колонок в качестве ключей — неудобно. Библиотека умеет превращать первую строку в ключи ассоциативных массивов:

php
// первая строка листа — заголовки
$rows = $excel->sheet()->withHeader()->readRows();
// [2 => ['Артикул' => 'A-100', 'Цена' => 990], 3 => [...], ...]

Можно и задать собственные ключи по колонкам, и управлять нумерацией строк/колонок флагами KEYS_*:

php
$rows = $excel->readRows(['A' => 'sku', 'B' => 'price'], Excel::KEYS_FIRST_ROW | Excel::KEYS_ROW_ZERO_BASED);

Пустые строки и ячейки по умолчанию пропускаются, а флаги TRIM_STRINGS и TREAT_EMPTY_STRING_AS_EMPTY_CELL позволяют считать пустыми и ячейки с пробелами. Обратите внимание: пустые ячейки возвращаются как null (не как пустая строка).

Области чтения

Реальные файлы редко начинаются с A1: сверху «шапка-красота», данные — в середине листа. Область чтения задаётся явно — диапазоном или именованной областью книги:

php
$excel->selectSheet('Demo1')
    ->setReadArea('B4:D11', true)   // true — первая строка области содержит заголовки
    ->readRows();

$excel->setReadArea('Values');      // defined name из книги
$cells = $excel->readCells();

Даты: без магических чисел

Excel хранит даты как серийные числа (например, 45123), и наивные ридеры их так и возвращают. FastExcelReader распознаёт даты по числовым форматам ячеек автоматически, а формат вывода настраивается:

php
$excel->setDateFormat('Y-m-d');
// ячейка с датой вернётся как '2023-10-05', а не 45123

Не только значения: стили, картинки, объединённые ячейки

Редкость для быстрых ридеров — FastExcelReader читает и оформление:

php
// значения вместе со стилями: ['v' => значение, 's' => стили, 'f' => формула]
$rows = $sheet->readRowsWithStyles();

// только стили: шрифты, заливки, границы, форматы
$styles = $sheet->readCellStyles();

Это позволяет, например, не импортировать строки, которые менеджер выделил красным, или отличить подытог (жирный шрифт) от обычной строки.

Объединённые ячейки — частая причина «дырок» при импорте (значение хранится только в первой ячейке диапазона). Библиотека отдаёт всю информацию о них:

php
$sheet->getMergedCells();   // все диапазоны: ['B3:B6', ...]
$sheet->isMerged('B4');     // true
$sheet->mergedRange('B4');  // 'B3:B6'

И — вишенка — извлечение изображений из XLSX. Прайс с фотографиями товаров перестаёт быть проблемой:

php
if ($sheet->hasImage('C7')) {
    $sheet->saveImageTo('C7', $dir);   // сохранить картинку из ячейки в каталог
}
$sheet->getImageBlob('C7');            // или получить бинарно

CSV: тот же API, те же возможности

Версия 3.0.0 читает и CSV — не через обёртку над fgetcsv(), а собственным парсером:

  • автоопределение разделителя (запятая, точка с запятой, табуляция) и кодировки (UTF-8/16/32, windows-1251, KOI8-R, Shift_JIS и другие) — на выходе всегда UTF-8;
  • полная поддержка RFC 4180: кавычки, экранирование, многострочные поля, BOM;
  • режимы strict (строго по стандарту) и tolerant (вытащить максимум из «кривого» файла);
  • пропуск пустых строк, строки-комментарии, обрезка пробелов.
php
$csv = Excel::openCsv('from-1c.csv', ['encoding' => 'Windows-1251', 'delimiter' => ';']);

foreach ($csv->withHeader()->nextRow() as $row) {
    echo $row['Название'];
}

API сознательно повторяет XLSX-ридер: nextRow(), readRows(), withHeader() работают одинаково. Импорт «принимаем и Excel, и CSV» пишется одной веткой кода.

Чего библиотека не делает

Честные границы применимости:

  • не пишет и не редактирует файлы — для этого есть FastExcelWriter;
  • не вычисляет формулы — возвращает текст формулы и последнее рассчитанное значение;
  • формат XLS (Excel 97-2003) в версии 3.0.0 не поддерживается — только XLSX и CSV.

Кому стоит присмотреться

FastExcelReader 3.0.0 — оптимальный выбор, когда задача звучит как «прочитать табличные данные и обработать»: импорт прайсов и каталогов, загрузка пользовательских файлов, интеграции и миграции. Вы получаете скорость и константную память потокового ридера — и при этом не теряете доступ к датам, стилям, объединённым ячейкам и картинкам, ради которых обычно приходится брать тяжёлые универсальные библиотеки.

bash
composer require avadim/fast-excel-reader

Документация и примеры — в репозитории на GitHub.

Комментарии (0)