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;
 | 
						|
    }
 | 
						|
} 
 |