194 lines
7.0 KiB
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'] + $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;
|
|
}
|
|
}
|