ManagementSystem/BACKEND/app/Exports/LeaveManagementExport.php

194 lines
7.0 KiB
PHP

<?php
namespace App\Exports;
use Carbon\Carbon;
use Maatwebsite\Excel\Concerns\FromArray;
use Maatwebsite\Excel\Concerns\WithEvents;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithStyles;
use Maatwebsite\Excel\Events\AfterSheet;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
use PhpOffice\PhpSpreadsheet\Style\Border;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
class LeaveManagementExport implements FromArray, WithHeadings, WithStyles, WithEvents
{
protected $data;
protected $year;
public function __construct($data)
{
$this->data = $data;
$this->year = Carbon::now()->year;
}
public function headings(): array
{
$months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
return array_merge(
['No.', 'User'],
$months,
['Total', 'Off', 'Remaining', 'Notes']
);
}
public function array(): array
{
$headers = $this->headings(); // Lấy tiêu đề
$rows = [];
$stt = 0;
foreach ($this->data as $index => $user) {
$totalDayOff = 0;
$totalDayLeave = $user['leaveDay']['ld_day_total'] + $user['leaveDay']['ld_date_additional'];
// Tính tổng ngày nghỉ theo tháng
$monthlyLeaves = array_fill(1, 12, 0);
foreach ($user['monthlyLeaveDays'] as $leaveDay) {
$monthlyLeaves[$leaveDay['month']] += $leaveDay['leave_days'];
$totalDayOff += $leaveDay['leave_days'];
}
// Tạo dòng dữ liệu
$row = [
$stt + 1,
$user['user']['name']
];
// Thêm dữ liệu các tháng
for ($month = 1; $month <= 12; $month++) {
$row[] = $monthlyLeaves[$month] ?: '';
}
// Thêm tổng số ngày
$row[] = $totalDayLeave;
$row[] = $totalDayOff;
$row[] = $totalDayLeave - $totalDayOff;
$row[] = $user['leaveDay']['ld_note'] ?? '';
$rows[] = $row;
$stt++;
}
return array_merge([$headers], $rows); // Thêm tiêu đề vào đầu mảng
}
public function registerEvents(): array
{
return [
AfterSheet::class => function(AfterSheet $event) {
$sheet = $event->sheet->getDelegate();
$lastRow = count($this->data) + 2;
$noteColumn = 'R'; // Cột Notes
// Xử lý đặc biệt cho cột Notes
$sheet->getStyle("{$noteColumn}3:{$noteColumn}{$lastRow}")
->getAlignment()
->setWrapText(true)
->setVertical(Alignment::VERTICAL_TOP)
->setHorizontal(Alignment::HORIZONTAL_LEFT);
// Tắt auto-size cho cột Notes và set độ rộng cố định
$sheet->getColumnDimension($noteColumn)
->setAutoSize(false)
->setWidth(60);
// Tự động điều chỉnh chiều cao cho từng dòng có nội dung
for ($row = 3; $row <= $lastRow; $row++) {
$cellValue = $sheet->getCell($noteColumn . $row)->getValue();
if (!empty($cellValue)) {
// Tính toán chiều cao dựa trên nội dung
$sheet->getRowDimension($row)->setRowHeight(-1);
// Tính toán lại chiều cao dựa trên số dòng trong nội dung
$lineCount = substr_count($cellValue, "\n") + 1;
$minHeight = max(30, $lineCount * 15); // 15 pixels cho mỗi dòng
// Lấy chiều cao hiện tại sau khi auto-size
$currentHeight = $sheet->getRowDimension($row)->getRowHeight();
// Nếu chiều cao tự động nhỏ hơn chiều cao tối thiểu, sử dụng chiều cao tối thiểu
if ($currentHeight < $minHeight) {
$sheet->getRowDimension($row)->setRowHeight($minHeight);
}
} else {
$sheet->getRowDimension($row)->setRowHeight(30);
}
}
// Refresh các tính toán của Excel
$sheet->calculateColumnWidths();
},
];
}
public function styles(Worksheet $sheet)
{
$lastRow = count($this->data) + 2;
$lastColumn = 'R';
// Thêm và style title
$sheet->mergeCells("A1:{$lastColumn}1");
$sheet->setCellValue('A1', "DANH SÁCH NGÀY NGHỈ NĂM {$this->year}");
$sheet->getStyle("A1:{$lastColumn}1")->applyFromArray([
'font' => [
'bold' => true,
'size' => 14
],
'alignment' => [
'horizontal' => Alignment::HORIZONTAL_CENTER,
'vertical' => Alignment::VERTICAL_CENTER
]
]);
// Style cho header (dời xuống row 2)
$sheet->getStyle("A2:{$lastColumn}2")->applyFromArray([
'font' => ['bold' => true],
'alignment' => [
'horizontal' => Alignment::HORIZONTAL_CENTER,
'vertical' => Alignment::VERTICAL_CENTER
]
]);
// Style cho toàn bộ bảng (bắt đầu từ row 1)
$sheet->getStyle("A1:{$lastColumn}{$lastRow}")->applyFromArray([
'borders' => [
'allBorders' => [
'borderStyle' => Border::BORDER_THIN
]
],
'alignment' => [
'vertical' => Alignment::VERTICAL_CENTER
]
]);
// Căn giữa cho các cột số liệu (điều chỉnh range bắt đầu từ row 3)
for ($col = 'C'; $col <= 'P'; $col++) {
$sheet->getStyle("{$col}3:{$col}{$lastRow}")
->getAlignment()
->setHorizontal(Alignment::HORIZONTAL_CENTER);
}
// Set độ rộng cột
$sheet->getColumnDimension('A')->setWidth(5); // No.
$sheet->getColumnDimension('B')->setWidth(30); // User
// Các tháng
for ($i = 'C'; $i <= 'N'; $i++) {
$sheet->getColumnDimension($i)->setWidth(8);
}
$sheet->getColumnDimension('O')->setWidth(8); // Total
$sheet->getColumnDimension('P')->setWidth(8); // Off
$sheet->getColumnDimension('Q')->setWidth(12); // Remaining
$sheet->getColumnDimension('R')->setWidth(30); // Notes
// Điều chỉnh style cho cột Notes
$sheet->getStyle("R3:R{$lastRow}")
->getAlignment()
->setHorizontal(Alignment::HORIZONTAL_LEFT)
->setVertical(Alignment::VERTICAL_TOP)
->setWrapText(true);
return $sheet;
}
}