PhpSpreadsheet для PHP: полное руководство с примерами
1. Что это и зачем нужна
PhpSpreadsheet — это мощная библиотека для языка PHP, предназначенная для чтения, записи и управления электронными таблицами в форматах Excel (XLSX, XLS), LibreOffice Calc (ODS), CSV, HTML и других. Она является наследником популярной, но устаревшей библиотеки PHPExcel, которая прекратила своё развитие в 2017 году. PhpSpreadsheet полностью переписана с учётом современных стандартов PHP (PSR-4, PSR-7, PSR-12) и поддерживает работу с большими объёмами данных, сложными формулами, стилями, диаграммами и условным форматированием.
Зачем она нужна? В веб-разработке часто возникает необходимость экспортировать данные из базы данных в Excel-отчёты, импортировать загруженные пользователями таблицы, генерировать счета, прайс-листы или финансовые документы. PhpSpreadsheet позволяет делать это программно, без установки на сервер офисных пакетов. Она поддерживает более 30 форматов файлов, включая XLSX, ODS, CSV, HTML, PDF (через внешние библиотеки), и может работать с формулами, условным форматированием, объединёнными ячейками, изображениями и комментариями.
Библиотека активно развивается (более 3000 звёзд на GitHub) и используется в таких проектах, как Laravel Excel, PhpOffice Suite и многих корпоративных системах. Она идеально подходит для создания отчётов, миграции данных, автоматизации документооборота и интеграции с CRM/ERP системами.
2. Установка
PhpSpreadsheet устанавливается через Composer — стандартный менеджер зависимостей для PHP. Убедитесь, что у вас установлен PHP версии 7.4 или выше (рекомендуется 8.0+).
composer require phpoffice/phpspreadsheet
После установки в проекте появится папка vendor и файл composer.json. Для использования библиотеки достаточно подключить автозагрузчик:
require 'vendor/autoload.php';
Если вы используете фреймворк (Laravel, Symfony), библиотека обычно подключается автоматически через сервис-провайдеры.
3. Быстрый старт — минимальный рабочий пример
Создадим простой скрипт, который генерирует Excel-файл с таблицей данных и выводит его на скачивание:
getActiveSheet();
// 2. Заполняем ячейки
$sheet->setCellValue('A1', 'Имя');
$sheet->setCellValue('B1', 'Email');
$sheet->setCellValue('A2', 'Иван Иванов');
$sheet->setCellValue('B2', 'ivan@example.com');
$sheet->setCellValue('A3', 'Петр Петров');
$sheet->setCellValue('B3', 'petr@example.com');
// 3. Настраиваем заголовки для скачивания
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment;filename="users.xlsx"');
header('Cache-Control: max-age=0');
// 4. Записываем файл в вывод
$writer = new Xlsx($spreadsheet);
$writer->save('php://output');
exit;
Этот код создаёт файл users.xlsx с двумя строками данных. Вы можете открыть его в Excel или LibreOffice Calc.
4. Основные методы/функции/классы
4.1. Spreadsheet::__construct()
Сигнатура: new Spreadsheet()
Что делает: Создаёт новый пустой документ с одним рабочим листом по умолчанию.
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
echo $sheet->getTitle(); // "Worksheet"
4.2. Worksheet::setCellValue()
Сигнатура: setCellValue(string $coordinate, mixed $value): static
Что делает: Устанавливает значение в указанную ячейку. Поддерживает строки, числа, даты, формулы (начинающиеся с =).
$sheet->setCellValue('A1', 'Hello');
$sheet->setCellValue('B1', 123.45);
$sheet->setCellValue('C1', '=SUM(A1:B1)');
4.3. Worksheet::getCell()
Сигнатура: getCell(string $coordinate): Cell
Что делает: Возвращает объект ячейки для дальнейшей работы (стили, форматирование, проверка).
$cell = $sheet->getCell('A1');
$cell->getStyle()->getFont()->setBold(true);
$cell->getStyle()->getAlignment()->setHorizontal('center');
4.4. Worksheet::fromArray()
Сигнатура: fromArray(array $source, mixed $nullValue = null, string $startCell = 'A1', bool $strictNullComparison = false): static
Что делает: Заполняет лист данными из двумерного массива. Удобно для быстрой загрузки больших объёмов данных.
$data = [
['Имя', 'Возраст', 'Город'],
['Анна', 25, 'Москва'],
['Борис', 30, 'СПб'],
];
$sheet->fromArray($data, NULL, 'A1');
4.5. Worksheet::getHighestRow() и getHighestColumn()
Сигнатура: getHighestRow(): int и getHighestColumn(): string
Что делает: Возвращают номер последней строки и букву последнего столбца с данными. Полезно для итерации по листу.
$highestRow = $sheet->getHighestRow(); // 3
$highestColumn = $sheet->getHighestColumn(); // 'C'
for ($row = 1; $row <= $highestRow; $row++) {
$rowData = $sheet->rangeToArray('A' . $row . ':' . $highestColumn . $row, NULL, TRUE, FALSE);
print_r($rowData);
}
4.6. Style::applyFromArray()
Сигнатура: applyFromArray(array $styleArray): static
Что делает: Применяет к ячейке или диапазону массив стилей (шрифт, заливка, границы, выравнивание).
$sheet->getStyle('A1:C1')->applyFromArray([
'font' => ['bold' => true, 'color' => ['argb' => 'FF0000']],
'fill' => ['fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID, 'startColor' => ['argb' => 'FFFF00']],
'borders' => ['allBorders' => ['borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN]],
]);
4.7. Worksheet::setAutoFilter()
Сигнатура: setAutoFilter(string $range): static
Что делает: Включает автофильтр для указанного диапазона ячеек. Пользователь сможет сортировать и фильтровать данные в Excel.
$sheet->setAutoFilter('A1:C10');
4.8. Worksheet::freezePane()
Сигнатура: freezePane(string $pane): static
Что делает: Закрепляет область (строки и/или столбцы) при прокрутке. Обычно используется для закрепления шапки таблицы.
$sheet->freezePane('A2'); // Закрепить первую строку
4.9. IOFactory::load()
Сигнатура: IOFactory::load(string $filename): Spreadsheet
Что делает: Загружает существующий файл электронной таблицы (XLSX, ODS, CSV и др.) в объект Spreadsheet для чтения или редактирования.
$spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load('report.xlsx');
$sheet = $spreadsheet->getActiveSheet();
echo $sheet->getCell('A1')->getValue();
4.10. Worksheet::setTitle()
Сигнатура: setTitle(string $title): static
Что делает: Переименовывает рабочий лист. Имя должно быть уникальным и не длиннее 31 символа.
$sheet->setTitle('Продажи 2024');
5. Реальный практический пример (100-200 строк кода)
Создадим скрипт, который генерирует отчёт по продажам: считывает данные из CSV, форматирует таблицу, добавляет формулы и выводит в XLSX.
getActiveSheet();
$sheet->setTitle('Продажи');
// 3. Заполняем данные
$sheet->fromArray($salesData, NULL, 'A1');
// 4. Вычисляем сумму для каждой строки (формула)
$highestRow = $sheet->getHighestRow(); // 5
for ($row = 2; $row <= $highestRow; $row++) {
$sheet->setCellValue('D' . $row, '=B' . $row . '*C' . $row);
}
// 5. Итоговая строка
$totalRow = $highestRow + 1;
$sheet->setCellValue('A' . $totalRow, 'Итого');
$sheet->setCellValue('D' . $totalRow, '=SUM(D2:D' . $highestRow . ')');
// 6. Стилизация заголовков
$headerStyle = [
'font' => ['bold' => true, 'size' => 12, 'color' => ['argb' => 'FFFFFFFF']],
'fill' => ['fillType' => Fill::FILL_SOLID, 'startColor' => ['argb' => 'FF4472C4']],
'alignment' => ['horizontal' => Alignment::HORIZONTAL_CENTER],
'borders' => ['allBorders' => ['borderStyle' => Border::BORDER_THIN]],
];
$sheet->getStyle('A1:D1')->applyFromArray($headerStyle);
// 7. Стили для данных
$dataStyle = [
'borders' => ['allBorders' => ['borderStyle' => Border::BORDER_THIN]],
'alignment' => ['horizontal' => Alignment::HORIZONTAL_CENTER],
];
$sheet->getStyle('A2:D' . $totalRow)->applyFromArray($dataStyle);
// 8. Формат чисел для столбца "Цена" и "Сумма"
$sheet->getStyle('C2:D' . $totalRow)->getNumberFormat()->setFormatCode('#,##0.00');
// 9. Автоширина столбцов
foreach (range('A', 'D') as $col) {
$sheet->getColumnDimension($col)->setAutoSize(true);
}
// 10. Закрепляем шапку
$sheet->freezePane('A2');
// 11. Вывод на скачивание
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment;filename="sales_report.xlsx"');
header('Cache-Control: max-age=0');
$writer = new Xlsx($spreadsheet);
$writer->save('php://output');
exit;
Этот скрипт создаёт профессионально оформленный отчёт с формулами, стилями, автофильтром (можно добавить) и закреплённой шапкой. Вы можете легко адаптировать его под свои данные.
6. Советы по производительности и типичные ошибки
Советы по производительности:
- Используйте
fromArray()вместо множественныхsetCellValue(): Загрузка массива данных работает значительно быстрее, чем установка ячеек по одной. - Отключайте кэширование ячеек для больших файлов
Также в библиотеке
HTTP-клиент для Go (Golang): топ библиотек для работы с сетью
vcpkg для C++: полное руководство с примерами
conditional-type-checks для TypeScript: полное руководство с примерами
Геолокация и карты в Kotlin: обзор библиотек и инструментов