Php spreadsheet
У объекта $sheet есть интересный метод fromArray().
Перым параметром передаётся набор данных, вторым параметром передаётся стартовая ячейка, от которой начинается внесение данных (по умолчанию A1).
Достаточно передать в этот метод двумерный массив данных,
метод сам внесёт данные в Xlsx файл:
Удобно отдельно хранить набор колонок, которые должны выводиться в отчёте, а отдельно данные.
Пример структуры массива, описывающего набор колонок:
$columns = [
'ID' => ['title' => 'Выводимый заголовок колонки в Excel'],
'NAME' => ['title' => 'Имя пользователя'],
];
$data = [
['ID' => 123, 'NAME' => 'Вася'],
['ID' => 456, 'NAME' => 'Петя'],
];
/**
* Получение значения из вложенного ассоциативного массива по цепочке ключей, разделённых точкой:
* getDotNotationValue($users, 'USER.NAME') -> $users['USER']['NAME']
*/
getDotNotationValue(array $data, string $key, $default = '')
{
return '';
}
Перед вызовом шаблона собёрем массив для быстрого формирования xlsx файла
class UsersXlsxReportComponent extends CBitrixComponent
{
public function executeComponent()
{
$data = $this->getData(); // получение необходимых данных
// дополнение, форматирование, ещё какие-либо манипуляции с данными
$columns = $this->getColumns();
$report = $this->getReport($columns, $data);
$this->arResult = [
'report' => $report,
];
$this->includeComponentTemplate();
}
/**
* Получение данных
*/
public function getData()
{
return [
['ID' => 4321, 'NAME' => 'Вася'],
['ID' => 4321, 'NAME' => 'Вася'],
];
}
/**
* Набор колонок для вывода в Excel
*/
private function getColumns(): array
{
return [
'ID' => ['title' => 'User Id'],
'NAME' => ['title' => 'User name'],
];
}
/**
* Формирование отчёта в удобном для быстрого формирования Excel виде
*/
private function getReport(array $columns, array $data): array
{
$report = [];
$report[] = array_column($columns, 'title');
foreach ($data as $dataItem) {
$row = [];
foreach ($columns as $column) {
$row[] = $this->$getDotNotationValue($dataItem, $column, '');
}
$report[] = $row;
}
return $report;
}
/**
* Получение значения в dot-нотификации
*/
private function getDotNotationValue(array $data, string $key, $default = '')
{
}
}
Пример содержимого template.php:
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
$highestColumn = Coordinate::stringFromColumnIndex(count($arResult['headers']));
$pCellRange = sprintf('A1:%s1', $highestColumn);
// оформление заголовочной строки
$sheet->getStyle($pCellRange)->applyFromArray([
'font' => ['bold' => true],
'alignment' => ['horizontal' => Alignment::HORIZONTAL_CENTER],
]);
// автоширина по содержимому
for ($i = 'A'; $i <= $highestColumn; $i++) {
$sheet->getColumnDimension($i)->setAutoSize(true);
}
// фиксация заголовочной строки. Дублирование - чтоб корректно отработал setSelectedCell();
$sheet->freezePane('A2', 'A2');
$sheet
->fromArray($arResult['headers']);
->fromArray($arResult['rows'], null, 'A2')
->setSelectedCell('A2') // выбранная ячейка. При открытии Excel на этой ячейке будет фокус
;
global $APPLICATION;
$APPLICATION->RestartBuffer();
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; charset=utf-8');
header('Content-Disposition: attachment;filename="Название файла.xlsx"');
$xlsx = new Xlsx($spreadsheet);
$xlsx->save('php://output');