| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 |
- <?php
- namespace App\Exports;
- use Maatwebsite\Excel\Concerns\FromCollection;
- use Maatwebsite\Excel\Concerns\WithEvents;
- use Maatwebsite\Excel\Concerns\WithStyles;
- use Maatwebsite\Excel\Concerns\WithCustomStartCell;
- use Maatwebsite\Excel\Events\AfterSheet;
- use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
- use PhpOffice\PhpSpreadsheet\Style\Alignment;
- use PhpOffice\PhpSpreadsheet\Style\Border;
- use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
- class ItemSalarySheetExport implements FromCollection, WithEvents, WithStyles, WithCustomStartCell
- {
- protected $projects;
- protected $data;
- protected $company;
- public function __construct(array $projects, array $data, $company)
- {
- $this->projects = $projects;
- $this->data = $data;
- $this->company = $company;
- }
- /**
- * 数据从第 5 行开始写入(1-4行留给自定义表头)
- */
- public function startCell(): string
- {
- return 'A5';
- }
- /**
- * 返回导出数据集合
- */
- public function collection()
- {
- return collect($this->data);
- }
- /**
- * 处理复杂的表头合并、列宽、固定文字
- */
- public function registerEvents(): array
- {
- return [
- AfterSheet::class => function(AfterSheet $event) {
- $sheet = $event->sheet->getDelegate();
- // 1. 计算总列数
- $projectCount = count($this->projects);
- $totalColNum = 1 + ($projectCount * 2) + 1; // 年月(1) + 每个项目2列 + 合计(1)
- $highestColumn = Coordinate::stringFromColumnIndex($totalColNum);
- // --- 2. 设置列宽 ---
- $sheet->getColumnDimension('A')->setWidth(15); // 年月列
- for ($i = 0; $i < $projectCount; $i++) {
- $startColNum = 2 + ($i * 2);
- $colLetterDays = Coordinate::stringFromColumnIndex($startColNum); // 天数
- $colLetterSalary = Coordinate::stringFromColumnIndex($startColNum + 1); // 工资
- // 设置比例:工资约为天数的 2 倍强
- $sheet->getColumnDimension($colLetterDays)->setWidth(7);
- $sheet->getColumnDimension($colLetterSalary)->setWidth(16);
- // --- 3. 第三、四行:RD项目表头设置 ---
- // 第三行项目名水平合并 (B3:C3)
- $sheet->mergeCells("{$colLetterDays}3:{$colLetterSalary}3");
- $sheet->setCellValue("{$colLetterDays}3", $this->projects[$i]);
- // 第四行子标题
- $sheet->setCellValue("{$colLetterDays}4", '天数');
- $sheet->setCellValue("{$colLetterSalary}4", '工资');
- }
- // 合计列宽度
- $sheet->getColumnDimension($highestColumn)->setWidth(18);
- // --- 4. 第一行:主标题 ---
- $sheet->mergeCells("A1:{$highestColumn}1");
- $sheet->setCellValue('A1', '研发项目工资总表');
- $sheet->getStyle('A1')->getFont()->setSize(14);
- $sheet->getStyle('A1')->getAlignment()->setHorizontal(Alignment::HORIZONTAL_CENTER);
- // --- 5. 第二行:单位名称 ---
- $sheet->mergeCells("A2:{$highestColumn}2");
- $sheet->setCellValue('A2', '单位名称:'. $this->company);
- $sheet->getStyle('A2')->getFont()->setSize(14);
- // --- 6. 垂直合并“年月”和“合计” ---
- $sheet->mergeCells('A3:A4');
- $sheet->setCellValue('A3', '年月');
- $lastColLetter = $highestColumn;
- $sheet->mergeCells("{$lastColLetter}3:{$lastColLetter}4");
- $sheet->setCellValue("{$lastColLetter}3", '合计');
- // 表头区域整体居中
- $sheet->getStyle("A3:{$highestColumn}4")->getAlignment()->setHorizontal(Alignment::HORIZONTAL_CENTER);
- },
- ];
- }
- /**
- * 设置表格基础样式和边框
- */
- public function styles(Worksheet $sheet)
- {
- $highestRow = $sheet->getHighestRow();
- $highestColumn = $sheet->getHighestColumn();
- // 定义统一的边框和对齐样式
- $commonStyle = [
- 'borders' => [
- 'allBorders' => [
- 'borderStyle' => Border::BORDER_THIN,
- 'color' => ['argb' => '000000'],
- ],
- ],
- 'alignment' => [
- 'vertical' => Alignment::VERTICAL_CENTER,
- 'horizontal' => Alignment::HORIZONTAL_CENTER,
- ],
- 'font' => [
- 'name' => '宋体',
- 'size' => 14,
- ],
- ];
- $sheet->getStyle("A1:{$highestColumn}{$highestRow}")->applyFromArray($commonStyle);
- $sheet->getStyle("A1")->getFont()->setSize(14);
- $sheet->getStyle("A2")->getAlignment()->setHorizontal(Alignment::HORIZONTAL_LEFT);
- return [];
- }
- }
|