PhpSpreadsheet. Быстрый старт. Таблица с картинками

Йо! Часто нам нужно выгрузить что-то в excel. Например каталог с картинками и его свойствами. Это вполне тривиальная задача, но я помню, что меня пугала работа с картинками и изучение библиотеки PhpSpreadsheet. Однажды мне пришлось этим заняться, когда пришёл заказ на создание его выгрузки из Bitirix’а (конечно пришлось поработать ещё и с кодировкой для правильной работы). По результатам работы я написал статью. А сегодня расскажу как создать и выгрузить таблицу с картинками в PHP c помощью PhpSpreadsheet.

Установка

Подключаемся по ssh к нашему серверу и устанавливаем композер в папку с проектом:

php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"

php -r "if (hash_file('sha384', 'composer-setup.php') === '8a6138e2a05a8c28539c9f0fb361159823655d7ad2deecb371b04a83966c61223adc522b0189079e3e9e277cd72b8897') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"

php composer-setup.php

php -r "unlink('composer-setup.php');"

Далее ставим PhpSpreadsheet:

composer require phpoffice/phpspreadsheet

Установили!)

Создание структуры документа

Создаём файл __ВАШЕ__НАЗВАНИЕ__.php в удобном месте и заходим в него. Там подключаем библиотеку и нужные юзам namespases:

<?php
require '__ПУТЬ_ДО_ПАПКИ_С_БИБЛИОТЕКОЙ__/vendor/autoload.php';

use PhpOffice\PhpSpreadsheet\Spreadsheet; // Работа со структурой документа
use PhpOffice\PhpSpreadsheet\Writer\Xlsx; // Запись в нужный формат. Если мы говорим только об excel то там может быть ещё Xls
use PhpOffice\PhpSpreadsheet\Worksheet\Drawing; // Встроенные методы для работы с картинками.

И так… мы подключили. Теперь нам нужно создать новый экземпляр «документа», выбрать текущую вкладку и добавить в неё заголовки:

$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();  

// Структура документа
$sheet->setCellValue('A1', 'Картинка');  
$sheet->setCellValue('B1', 'Название');  
$sheet->setCellValue('C1', 'Количество');
$sheet->setCellValue('D1', 'Остаток');
$sheet->setCellValue('E1', 'Цена');
$sheet->setCellValue('F1', 'Сумма');
$sheet->setCellValue('G1', 'Код');

Вы наверное уже поняли какая будет таблица и структура массива, из которого мы будем её строить. Но на всякий случай я покажу вам тот самый массив:

$data = [
    [
        img=> './images/1.png', // Адрес картинки на вашем сервере
        name=> 'Текс', // Имя
        count => 'sd', // Количество
        ost=>'5', // Остаток товара
        price=> '2', // Цена
        summ=>'sd', // Сумма
        code=>'2' // Код товара
    ]
......
];

Соответственно нам нужно дальше идти по массиву и вставлять данные нужные ячейки.

$i = 2; // Начинаем с двойки, нумерациия в таблице идёт с 1-цы
foreach($data as $row){
    // Получаем данные ячеек
    $img = $row['img'];
    $name = $row['name'];
    $count = $row['count'];
    $ost = $row['ost'];
    $price = $row['price'];
    $summ = $row['summ'];
    $code = $row['code'];
    // Img
    if(!empty($img)){
        $drawing = new Drawing(); // Новый экземпляр "Рисоваки")
        $drawing->setName($name); // Имя картинки
        $drawing->setDescription($name); // Описание
        $drawing->setPath($img); // Абсолютный путь на сервере к картинке
        $drawing->setCoordinates('A'. $i); // Координаты картинки
        $drawing->getShadow()->setVisible(true); // Тень если нужно
        $drawing->setWorksheet($sheet); // Нужная вкладка
        $drawing->setHeight(100); // Высота в пикселях
        $drawing->setWidth(100); // Ширина в пикселях
    }
    // Another data
    $sheet->setCellValue('B' . $i, $name);  // Конкатинируем с $i и получаем нужную ячейку
    $sheet->setCellValue('C' . $i, $count);
    $sheet->setCellValue('D' . $i, $ost);
    $sheet->setCellValue('E' . $i, $price);
    $sheet->setCellValue('F' . $i, $summ);
    $sheet->setCellValue('G' . $i, $code);
    // Set row height
    $spreadsheet->getActiveSheet()->getRowDimension($i)->setRowHeight(100); // Выставляем высоту всей строки как у картинки
    $i++;
}

Далее нужно сделать преобразование колонкой «A» — выставить ширину по всей вкладке. И тут проблема! Ширина выставляется в единицах измерения excel’ так, что подберите свою, но кажется, что соотношение с пикселями примерно 1/5

$spreadsheet->getActiveSheet()->getColumnDimension('A')->setWidth(20);

При значении ширины колонки 20, а ширина картинки 100 получиться примерно так:

Запись на сервер

После того как мы получили все данные, осталось записать на сервер нашу excel’ку)

$writer = new Xlsx($spreadsheet);
$writer->save(_АБСОЛЮТНЫЙ_ПУТЬ_НА_СЕРВЕРЕ_ . _ИМЯ_ .xlsx');

Ещё было бы не плохо отдавать ссылку на файл, чтобы скачивать с сайта.

echo '<a target="_blank" href="__ДОМЕН__ . _ПУТЬ_ДО_ФАЙЛА">Скачать</a>';

В моём случае нужна была переиспользуемая функция и я обернул коды так:

<?php
require 'vendor/autoload.php';

use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use PhpOffice\PhpSpreadsheet\Worksheet\Drawing;

function createnGetLinkExcel($id, $data){
    $spreadsheet = new Spreadsheet();
    $sheet = $spreadsheet->getActiveSheet();  
    
    $sheet->setCellValue('A1', 'Картинка');  
    $sheet->setCellValue('B1', 'Название');  
    $sheet->setCellValue('C1', 'Количество');
    $sheet->setCellValue('D1', 'Останок');
    $sheet->setCellValue('E1', 'Цена');
    $sheet->setCellValue('F1', 'Сумма');
    $sheet->setCellValue('G1', 'Код');
    
$i = 2;
foreach($data as $row){
    $img = $row['img'];
    $name = $row['name'];
    $count = $row['count'];
    $ost = $row['ost'];
    $price = $row['price'];
    $summ = $row['summ'];
    $code = $row['code'];
    // Img
    if(!empty($img)){
        $drawing = new Drawing();
        $drawing->setName($name);
        $drawing->setDescription($name);
        $drawing->setPath($img); // put your path and image here
        $drawing->setCoordinates('A'. $i);
        $drawing->getShadow()->setVisible(true);
        $drawing->setWorksheet($sheet);
        $drawing->setHeight(100);
        $drawing->setWidth(100);
    }
    // Another data
    $sheet->setCellValue('B' . $i, $name);  
    $sheet->setCellValue('C' . $i, $count);
    $sheet->setCellValue('D' . $i, $ost);
    $sheet->setCellValue('E' . $i, $price);
    $sheet->setCellValue('F' . $i, $summ);
    $sheet->setCellValue('G' . $i, $code);
    // Set row height
    $spreadsheet->getActiveSheet()->getRowDimension($i)->setRowHeight(100);
    $i++;
}
    $spreadsheet->getActiveSheet()->getColumnDimension('A')->setWidth(20);
    $writer = new Xlsx($spreadsheet);
    $writer->save('result/order_'. $id .'.xlsx');
    echo '<a target="_blank" href="result/order_'. $id .'.xlsx">Скачать</a>';
}
// Тестовые данные
$data = [
    [
        img=> 'images/1.png',
        name=> 'Текс',
        count => 'sd',
        ost=>'5',
        price=> '2',
        summ=>'sd',
        code=>'2'
    ]
];

// Пример вызова
createnGetLinkExcel('15', $data);