Rapport-Laravel/app/Exports/RevesmartLaunchDriveExport.php

175 lines
6.2 KiB
PHP

<?php
namespace App\Exports;
use Maatwebsite\Excel\Concerns\FromArray;
use Maatwebsite\Excel\Concerns\WithEvents;
use Maatwebsite\Excel\Concerns\WithTitle;
use Maatwebsite\Excel\Events\AfterSheet;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
use PhpOffice\PhpSpreadsheet\Style\Border;
use PhpOffice\PhpSpreadsheet\Style\Fill;
class RevesmartLaunchDriveExport implements FromArray, WithEvents, WithTitle
{
/** @var array<int, array<int, mixed>> */
protected $rows;
/** @var array<int, array{type:string}> */
protected $rowMeta;
protected $showYesterday;
protected $statusCols = 4;
protected $dayCols = 8;
protected $mtdCols = 8;
protected $chestCols = 7;
protected $title;
/** @var array<int, string> */
protected $merges;
/**
* @param array<int, array<int, mixed>> $rows
* @param array<int, array{type:string}> $rowMeta
* @param array<int, string> $merges
*/
public function __construct(array $rows, array $rowMeta, bool $showYesterday, string $title = 'Revesmart-Launch-Drive', array $merges = [])
{
$this->rows = $rows;
$this->rowMeta = $rowMeta;
$this->showYesterday = $showYesterday;
$this->title = $title;
$this->merges = $merges;
}
public function array(): array
{
return $this->rows;
}
public function title(): string
{
return mb_substr(preg_replace('/\.xlsx$/i', '', $this->title), 0, 31);
}
public function registerEvents(): array
{
return [
AfterSheet::class => function (AfterSheet $event) {
$sheet = $event->sheet->getDelegate();
$colCount = $this->statusCols
+ ($this->showYesterday ? $this->dayCols : 0)
+ $this->mtdCols
+ $this->chestCols;
$lastCol = Coordinate::stringFromColumnIndex($colCount);
$lastRow = max(1, count($this->rows));
foreach ($this->merges as $range) {
if (is_string($range) && strpos($range, ':') !== false) {
$sheet->mergeCells($range);
}
}
$sheet->getStyle("A1:{$lastCol}{$lastRow}")->applyFromArray([
'borders' => [
'allBorders' => [
'borderStyle' => Border::BORDER_THIN,
'color' => ['rgb' => 'C5C9CE'],
],
],
'alignment' => [
'horizontal' => Alignment::HORIZONTAL_CENTER,
'vertical' => Alignment::VERTICAL_CENTER,
'wrapText' => true,
],
'font' => [
'size' => 10,
],
]);
// Left-align name column
$sheet->getStyle("A1:A{$lastRow}")->getAlignment()->setHorizontal(Alignment::HORIZONTAL_LEFT);
// Group header row (row 1)
$col = 1;
$this->fillRange($sheet, $col, 1, $this->statusCols, 'C8E6C9', true);
$col += $this->statusCols;
if ($this->showYesterday) {
$this->fillRange($sheet, $col, 1, $this->dayCols, 'FFE0B2', true);
$col += $this->dayCols;
}
$this->fillRange($sheet, $col, 1, $this->mtdCols, 'C8E6C9', true);
$col += $this->mtdCols;
$this->fillRange($sheet, $col, 1, $this->chestCols, 'BBDEFB', true);
// Sub-header row (row 2)
if ($lastRow >= 2) {
$sheet->getStyle("A2:{$lastCol}2")->applyFromArray([
'font' => ['bold' => true],
'fill' => [
'fillType' => Fill::FILL_SOLID,
'startColor' => ['rgb' => 'EEF1F4'],
],
]);
}
// Data rows
foreach ($this->rowMeta as $index => $meta) {
$excelRow = $index + 1;
$type = $meta['type'] ?? 'data';
if ($type === 'group' || $type === 'sub') {
continue;
}
if ($type === 'zbm') {
$sheet->getStyle("A{$excelRow}:{$lastCol}{$excelRow}")->applyFromArray([
'font' => ['bold' => true],
'fill' => [
'fillType' => Fill::FILL_SOLID,
'startColor' => ['rgb' => 'E8F5E9'],
],
]);
} elseif ($type === 'grand') {
$sheet->getStyle("A{$excelRow}:{$lastCol}{$excelRow}")->applyFromArray([
'font' => ['bold' => true, 'color' => ['rgb' => 'FFFFFF']],
'fill' => [
'fillType' => Fill::FILL_SOLID,
'startColor' => ['rgb' => '2E7D32'],
],
]);
}
}
for ($i = 1; $i <= $colCount; $i++) {
$letter = Coordinate::stringFromColumnIndex($i);
$sheet->getColumnDimension($letter)->setAutoSize(true);
}
$sheet->getColumnDimension('A')->setWidth(22);
$sheet->getRowDimension(1)->setRowHeight(28);
$sheet->getRowDimension(2)->setRowHeight(36);
},
];
}
protected function fillRange($sheet, int $startCol, int $row, int $span, string $rgb, bool $bold = false): void
{
if ($span <= 0) {
return;
}
$start = Coordinate::stringFromColumnIndex($startCol) . $row;
$end = Coordinate::stringFromColumnIndex($startCol + $span - 1) . $row;
$sheet->getStyle("{$start}:{$end}")->applyFromArray([
'font' => ['bold' => $bold],
'fill' => [
'fillType' => Fill::FILL_SOLID,
'startColor' => ['rgb' => $rgb],
],
]);
}
}