refactor: introduce BaseExcelExport class to standardize spreadsheet styling, formatting, and event handling across all exports

This commit is contained in:
Yoga Pangestu 2026-04-09 13:51:36 +07:00
parent d858a47023
commit 711aedcf2b
5 changed files with 153 additions and 220 deletions

View File

@ -0,0 +1,122 @@
<?php
namespace App\Filament\Exports;
use Maatwebsite\Excel\Concerns\WithEvents;
use Maatwebsite\Excel\Concerns\WithStyles;
use Maatwebsite\Excel\Events\AfterSheet;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
use PhpOffice\PhpSpreadsheet\Style\Border;
use PhpOffice\PhpSpreadsheet\Style\Fill;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
use pxlrbt\FilamentExcel\Exports\ExcelExport;
abstract class BaseExcelExport extends ExcelExport implements WithEvents, WithStyles
{
abstract protected function getTitle(): string;
/**
* Define column widths for specific columns.
* Example: ['A' => 40, 'B' => 30]
*/
public function getColumnWidths(): array
{
return [];
}
public function setUp()
{
$this->withFilename(fn ($resource) => $resource::getModelLabel().'-'.date('Y-m-d'));
$this->fromTable()
->except(['index']);
}
public function headings(): array
{
return [
[$this->getTitle()],
$this->getHeadings(),
];
}
public function styles(Worksheet $sheet)
{
return [
1 => [
'font' => ['bold' => true, 'size' => 14],
'alignment' => ['horizontal' => Alignment::HORIZONTAL_CENTER],
],
2 => [
'font' => ['bold' => true],
'alignment' => [
'horizontal' => Alignment::HORIZONTAL_CENTER,
'vertical' => Alignment::VERTICAL_CENTER,
],
'fill' => [
'fillType' => Fill::FILL_SOLID,
'startColor' => ['rgb' => 'E2E8F0'],
],
],
];
}
public function registerEvents(): array
{
return [
AfterSheet::class => function (AfterSheet $event) {
$sheet = $event->sheet->getDelegate();
$lastColumn = $sheet->getHighestColumn();
$lastRow = $sheet->getHighestRow();
// Merge main title
$sheet->mergeCells("A1:{$lastColumn}1");
// Style for all data cells
$sheet->getStyle("A2:{$lastColumn}{$lastRow}")
->getAlignment()
->setVertical(Alignment::VERTICAL_TOP)
->setWrapText(true);
// Set column widths
$columnWidths = $this->getColumnWidths();
foreach (range('A', $lastColumn) as $columnID) {
if (isset($columnWidths[$columnID])) {
$sheet->getColumnDimension($columnID)->setAutoSize(false);
$sheet->getColumnDimension($columnID)->setWidth($columnWidths[$columnID]);
} else {
$sheet->getColumnDimension($columnID)->setAutoSize(true);
}
}
// Add borders to the table
$sheet->getStyle("A2:{$lastColumn}{$lastRow}")->applyFromArray([
'borders' => [
'allBorders' => [
'borderStyle' => Border::BORDER_THIN,
'color' => ['rgb' => 'CBD5E0'],
],
],
]);
// Replace <br> with newlines and ensure wrapping
foreach ($sheet->getRowIterator(3) as $row) {
$cellIterator = $row->getCellIterator();
$cellIterator->setIterateOnlyExistingCells(false);
foreach ($cellIterator as $cell) {
$value = $cell->getValue();
if (is_string($value) && (str_contains($value, '<br>') || str_contains($value, '<br/>') || str_contains($value, '<br />'))) {
$cell->setValue(str_replace(['<br>', '<br/>', '<br />'], "\n", $value));
}
}
}
// Set row height to auto for data rows
for ($i = 3; $i <= $lastRow; $i++) {
$sheet->getRowDimension($i)->setRowHeight(-1);
}
},
];
}
}

View File

@ -2,67 +2,18 @@
namespace App\Filament\Exports;
use Maatwebsite\Excel\Concerns\WithEvents;
use Maatwebsite\Excel\Concerns\WithStyles;
use Maatwebsite\Excel\Events\AfterSheet;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
use pxlrbt\FilamentExcel\Exports\ExcelExport;
class ContentRecapExcelExport extends ExcelExport implements WithEvents, WithStyles
class ContentRecapExcelExport extends BaseExcelExport
{
public function setUp()
protected function getTitle(): string
{
$this->withFilename(fn ($resource) => $resource::getModelLabel().'-'.date('Y-m-d'));
$this->fromTable()
->except(['index']);
return 'Data Rekap Konten';
}
public function headings(): array
public function getColumnWidths(): array
{
return [
['Data Rekap Konten'],
$this->getHeadings(),
];
}
public function styles(Worksheet $sheet)
{
return [
1 => [
'font' => ['bold' => true, 'size' => 14],
'alignment' => ['horizontal' => Alignment::HORIZONTAL_CENTER],
],
2 => [
'font' => ['bold' => true],
'alignment' => ['horizontal' => Alignment::HORIZONTAL_CENTER, 'vertical' => Alignment::VERTICAL_CENTER],
],
];
}
public function registerEvents(): array
{
return [
AfterSheet::class => function (AfterSheet $event) {
$sheet = $event->sheet->getDelegate();
$lastColumn = $sheet->getHighestColumn();
$sheet->mergeCells("A1:{$lastColumn}1");
$sheet->getStyle("A2:{$lastColumn}".$sheet->getHighestRow())
->getAlignment()
->setVertical(Alignment::VERTICAL_TOP)
->setWrapText(true);
for ($i = 3; $i <= $sheet->getHighestRow(); $i++) {
$sheet->getRowDimension($i)->setRowHeight(-1);
}
foreach (range('A', $lastColumn) as $columnID) {
$sheet->getColumnDimension($columnID)->setAutoSize(true);
}
},
'A' => 50,
'E' => 30,
];
}
}

View File

@ -2,67 +2,20 @@
namespace App\Filament\Exports;
use Maatwebsite\Excel\Concerns\WithEvents;
use Maatwebsite\Excel\Concerns\WithStyles;
use Maatwebsite\Excel\Events\AfterSheet;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
use pxlrbt\FilamentExcel\Exports\ExcelExport;
class CooperationExcelExport extends ExcelExport implements WithEvents, WithStyles
class CooperationExcelExport extends BaseExcelExport
{
public function setUp()
protected function getTitle(): string
{
$this->withFilename(fn ($resource) => $resource::getModelLabel().'-'.date('Y-m-d'));
$this->fromTable()
->except(['index']);
return 'Data Kerja Sama';
}
public function headings(): array
public function getColumnWidths(): array
{
return [
['Data Kerja Sama'],
$this->getHeadings(),
];
}
public function styles(Worksheet $sheet)
{
return [
1 => [
'font' => ['bold' => true, 'size' => 14],
'alignment' => ['horizontal' => Alignment::HORIZONTAL_CENTER],
],
2 => [
'font' => ['bold' => true],
'alignment' => ['horizontal' => Alignment::HORIZONTAL_CENTER, 'vertical' => Alignment::VERTICAL_CENTER],
],
];
}
public function registerEvents(): array
{
return [
AfterSheet::class => function (AfterSheet $event) {
$sheet = $event->sheet->getDelegate();
$lastColumn = $sheet->getHighestColumn();
$sheet->mergeCells("A1:{$lastColumn}1");
$sheet->getStyle("A2:{$lastColumn}".$sheet->getHighestRow())
->getAlignment()
->setVertical(Alignment::VERTICAL_TOP)
->setWrapText(true);
for ($i = 3; $i <= $sheet->getHighestRow(); $i++) {
$sheet->getRowDimension($i)->setRowHeight(-1);
}
foreach (range('A', $lastColumn) as $columnID) {
$sheet->getColumnDimension($columnID)->setAutoSize(true);
}
},
'A' => 40,
'B' => 35,
'F' => 35,
'K' => 50,
];
}
}

View File

@ -2,67 +2,20 @@
namespace App\Filament\Exports;
use Maatwebsite\Excel\Concerns\WithEvents;
use Maatwebsite\Excel\Concerns\WithStyles;
use Maatwebsite\Excel\Events\AfterSheet;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
use pxlrbt\FilamentExcel\Exports\ExcelExport;
class IssueManagementExcelExport extends ExcelExport implements WithEvents, WithStyles
class IssueManagementExcelExport extends BaseExcelExport
{
public function setUp()
protected function getTitle(): string
{
$this->withFilename(fn ($resource) => $resource::getModelLabel().'-'.date('Y-m-d'));
$this->fromTable()
->except(['index']);
return 'Data Manajemen Isu';
}
public function headings(): array
public function getColumnWidths(): array
{
return [
['Data Manajemen Isu'],
$this->getHeadings(),
];
}
public function styles(Worksheet $sheet)
{
return [
1 => [
'font' => ['bold' => true, 'size' => 14],
'alignment' => ['horizontal' => Alignment::HORIZONTAL_CENTER],
],
2 => [
'font' => ['bold' => true],
'alignment' => ['horizontal' => Alignment::HORIZONTAL_CENTER, 'vertical' => Alignment::VERTICAL_CENTER],
],
];
}
public function registerEvents(): array
{
return [
AfterSheet::class => function (AfterSheet $event) {
$sheet = $event->sheet->getDelegate();
$lastColumn = $sheet->getHighestColumn();
$sheet->mergeCells("A1:{$lastColumn}1");
$sheet->getStyle("A2:{$lastColumn}".$sheet->getHighestRow())
->getAlignment()
->setVertical(Alignment::VERTICAL_TOP)
->setWrapText(true);
for ($i = 3; $i <= $sheet->getHighestRow(); $i++) {
$sheet->getRowDimension($i)->setRowHeight(-1);
}
foreach (range('A', $lastColumn) as $columnID) {
$sheet->getColumnDimension($columnID)->setAutoSize(true);
}
},
'A' => 50,
'D' => 45,
'G' => 30,
'H' => 30,
];
}
}

View File

@ -2,67 +2,21 @@
namespace App\Filament\Exports;
use Maatwebsite\Excel\Concerns\WithEvents;
use Maatwebsite\Excel\Concerns\WithStyles;
use Maatwebsite\Excel\Events\AfterSheet;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
use pxlrbt\FilamentExcel\Exports\ExcelExport;
class MediaMonitoringExcelExport extends ExcelExport implements WithEvents, WithStyles
class MediaMonitoringExcelExport extends BaseExcelExport
{
public function setUp()
protected function getTitle(): string
{
$this->withFilename(fn ($resource) => $resource::getModelLabel().'-'.date('Y-m-d'));
$this->fromTable()
->except(['index']);
return 'Data Monitoring Media';
}
public function headings(): array
public function getColumnWidths(): array
{
return [
['Data Monitoring Media'],
$this->getHeadings(),
];
}
public function styles(Worksheet $sheet)
{
return [
1 => [
'font' => ['bold' => true, 'size' => 14],
'alignment' => ['horizontal' => Alignment::HORIZONTAL_CENTER],
],
2 => [
'font' => ['bold' => true],
'alignment' => ['horizontal' => Alignment::HORIZONTAL_CENTER, 'vertical' => Alignment::VERTICAL_CENTER],
],
];
}
public function registerEvents(): array
{
return [
AfterSheet::class => function (AfterSheet $event) {
$sheet = $event->sheet->getDelegate();
$lastColumn = $sheet->getHighestColumn();
$sheet->mergeCells("A1:{$lastColumn}1");
$sheet->getStyle("A2:{$lastColumn}".$sheet->getHighestRow())
->getAlignment()
->setVertical(Alignment::VERTICAL_TOP)
->setWrapText(true);
for ($i = 3; $i <= $sheet->getHighestRow(); $i++) {
$sheet->getRowDimension($i)->setRowHeight(-1);
}
foreach (range('A', $lastColumn) as $columnID) {
$sheet->getColumnDimension($columnID)->setAutoSize(true);
}
},
'B' => 30,
'C' => 50,
'F' => 40,
'H' => 30,
'I' => 30,
];
}
}