| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 |
- <?php
- namespace App\Exports;
- use Maatwebsite\Excel\Concerns\FromCollection;
- use Maatwebsite\Excel\Concerns\WithEvents;
- use Maatwebsite\Excel\Concerns\WithTitle;
- use Maatwebsite\Excel\Concerns\WithCustomStartCell;
- use Maatwebsite\Excel\Events\AfterSheet;
- use PhpOffice\PhpSpreadsheet\Style\Alignment;
- use PhpOffice\PhpSpreadsheet\Style\Border;
- use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
- class ItemSalaryFTSheetExport implements FromCollection, WithEvents, WithCustomStartCell, WithTitle
- {
- protected $month;
- protected $data;
- protected $projects;
- protected $company;
- public function __construct(string $month, array $data, array $projects, $company = '')
- {
- $this->month = $month;
- $this->data = $data;
- $this->projects = $projects;
- $this->company = $company;
- }
- public function title(): string { return $this->month; }
- 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();
- $projectCount = count($this->projects);
- // 总列数计算:4(基础) + 项目数 + 1(合计工时) + 项目数 + 1(总计工资)
- $totalColNum = 4 + ($projectCount + 1) + ($projectCount + 1);
- $highestColumn = Coordinate::stringFromColumnIndex($totalColNum);
- $highestRow = $sheet->getHighestRow();
- // 保证即便数据少,也画出至少 10 行的格子,显得美观
- $renderToRow = max($highestRow, 10);
- // --- 1. 第一行:主标题 ---
- $sheet->mergeCells("A1:{$highestColumn}1");
- $sheet->setCellValue('A1', "{$this->month}研发工资分摊表");
- $sheet->getStyle('A1')->getFont()->setSize(16)->setBold(true);
- // --- 2. 第二行:单位名称 ---
- $sheet->mergeCells("A2:{$highestColumn}2");
- $sheet->setCellValue('A2', "单位:{$this->company}");
- $sheet->getStyle('A2')->getFont()->setSize(12);
- // --- 3. 第三、四行:复合表头 ---
- // 垂直合并基础列
- foreach (['A', 'B', 'C', 'D'] as $col) { $sheet->mergeCells("{$col}3:{$col}4"); }
- $sheet->setCellValue('A3', '序号');
- $sheet->setCellValue('B3', '技术人员');
- $sheet->setCellValue('C3', '工资');
- $sheet->setCellValue('D3', '月总工时');
- // A. 月工时区域 (E列开始)
- $workHourStartCol = 5;
- $workHourEndCol = $workHourStartCol + $projectCount;
- $workHourStartLetter = Coordinate::stringFromColumnIndex($workHourStartCol);
- $workHourEndLetter = Coordinate::stringFromColumnIndex($workHourEndCol);
- $sheet->mergeCells("{$workHourStartLetter}3:{$workHourEndLetter}3");
- $sheet->setCellValue("{$workHourStartLetter}3", '月 工 时');
- foreach ($this->projects as $idx => $code) {
- $sheet->setCellValue(Coordinate::stringFromColumnIndex($workHourStartCol + $idx) . '4', $code);
- }
- $sheet->setCellValue($workHourEndLetter . '4', '合计工时');
- // B. 金额区域
- $moneyStartCol = $workHourEndCol + 1;
- $moneyEndCol = $moneyStartCol + $projectCount;
- $moneyStartLetter = Coordinate::stringFromColumnIndex($moneyStartCol);
- $moneyEndLetter = Coordinate::stringFromColumnIndex($moneyEndCol);
- $sheet->mergeCells("{$moneyStartLetter}3:{$moneyEndLetter}3");
- $sheet->setCellValue("{$moneyStartLetter}3", '项目应计工资金额');
- foreach ($this->projects as $idx => $code) {
- $sheet->setCellValue(Coordinate::stringFromColumnIndex($moneyStartCol + $idx) . '4', $code);
- }
- $sheet->setCellValue($moneyEndLetter . '4', '总计工资');
- // --- 4. 样式美化 ---
- // 仅对表格主体(3行开始)加边框
- $tableRange = "A3:{$highestColumn}{$renderToRow}";
- $sheet->getStyle($tableRange)->applyFromArray([
- 'borders' => ['allBorders' => ['borderStyle' => Border::BORDER_THIN]],
- 'alignment' => [
- 'vertical' => Alignment::VERTICAL_CENTER,
- 'horizontal' => Alignment::HORIZONTAL_CENTER,
- ],
- 'font' => ['name' => '宋体', 'size' => 10],
- ]);
- // 标题和单位行样式
- $sheet->getStyle("A1:A2")->getAlignment()->setHorizontal(Alignment::HORIZONTAL_LEFT);
- $sheet->getStyle("A1")->getAlignment()->setHorizontal(Alignment::HORIZONTAL_CENTER);
- $sheet->getStyle("A3:{$highestColumn}4")->getFont()->setBold(true);
- // 格式化金额(解决 0.02 问题)
- $sheet->getStyle("C5:C{$renderToRow}")->getNumberFormat()->setFormatCode('#,##0.00');
- $sheet->getStyle("{$moneyStartLetter}5:{$highestColumn}{$renderToRow}")->getNumberFormat()->setFormatCode('#,##0.00');
- // 设置列宽
- $sheet->getColumnDimension('A')->setWidth(6);
- $sheet->getColumnDimension('B')->setWidth(12);
- for ($i = 3; $i <= $totalColNum; $i++) {
- $sheet->getColumnDimension(Coordinate::stringFromColumnIndex($i))->setWidth(13);
- }
- },
- ];
- }
- }
|