ManMonthlyWorkHourSheetExport.php 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. <?php
  2. namespace App\Exports;
  3. use Maatwebsite\Excel\Concerns\WithEvents;
  4. use Maatwebsite\Excel\Concerns\WithTitle;
  5. use Maatwebsite\Excel\Events\AfterSheet;
  6. use PhpOffice\PhpSpreadsheet\Style\Alignment;
  7. use PhpOffice\PhpSpreadsheet\Style\Border;
  8. use PhpOffice\PhpSpreadsheet\Style\Borders;
  9. use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
  10. use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
  11. class ManMonthlyWorkHourSheetExport implements WithEvents, WithTitle
  12. {
  13. protected $monthName;
  14. protected $data;
  15. protected $daysInMonth;
  16. protected $company_name;
  17. public function __construct(string $monthName, array $data, int $daysInMonth, string $company_name)
  18. {
  19. $this->monthName = $monthName;
  20. $this->data = $data;
  21. $this->daysInMonth = $daysInMonth;
  22. $this->company_name = $company_name;
  23. }
  24. public function title(): string
  25. {
  26. return $this->monthName;
  27. }
  28. /**
  29. * 【核心新增】:设置 Excel 单元格显示格式
  30. * 将 C 列至 AH 列(即 1 号到 31 号)设置为显示 2 位小数
  31. */
  32. public function columnFormats(): array
  33. {
  34. return [
  35. 'C:AH' => NumberFormat::FORMAT_NUMBER_00,
  36. ];
  37. }
  38. public function registerEvents(): array
  39. {
  40. return [
  41. AfterSheet::class => function (AfterSheet $event) {
  42. $sheet = $event->sheet->getDelegate();
  43. // 计算最大列(项目B + 姓名C + 天数)
  44. $totalColNum = 2 + $this->daysInMonth;
  45. $highestColumn = Coordinate::stringFromColumnIndex($totalColNum);
  46. // --- 1. 第一行:主标题 ---
  47. $sheet->mergeCells("A1:{$highestColumn}1");
  48. $sheet->setCellValue('A1', "{$this->monthName}研发人员工时统计表");
  49. $sheet->getStyle('A1')->getFont()->setSize(14);
  50. $sheet->getStyle('A1')->getAlignment()->setHorizontal(Alignment::HORIZONTAL_CENTER);
  51. // --- 2. 第二行:单位行 ---
  52. $sheet->mergeCells("A2:{$highestColumn}2");
  53. $sheet->setCellValue('A2', "单位:" . $this->company_name);
  54. $sheet->getStyle('A2')->getAlignment()->setHorizontal(Alignment::HORIZONTAL_LEFT);
  55. // --- 3. 第三行表头设置 ---
  56. // (1) A3: 项目名称 (独立单元格)
  57. $sheet->setCellValue('A3', "项目名称");
  58. $sheet->getColumnDimension('A')->setWidth(14);
  59. // (2) B3: 人员名称/日期 (斜线分割单元格)
  60. $sheet->setCellValue('B3', " 日期 \n人员名称");
  61. $sheet->getStyle('B3')->getAlignment()->setWrapText(true);
  62. $sheet->getStyle('B3')->getAlignment()->setVertical(Alignment::VERTICAL_CENTER);
  63. $sheet->getStyle('B3')->getAlignment()->setHorizontal(Alignment::HORIZONTAL_LEFT);
  64. $sheet->getColumnDimension('B')->setWidth(16);
  65. // 绘制 B3 斜线
  66. $sheet->getStyle('B3')->getBorders()->applyFromArray([
  67. 'diagonal' => [
  68. 'borderStyle' => Border::BORDER_THIN,
  69. 'color' => ['rgb' => '000000'],
  70. ],
  71. ]);
  72. $sheet->getStyle('B3')->getBorders()->setDiagonalDirection(Borders::DIAGONAL_DOWN);
  73. // (3) C3 往后: 动态日期 (1, 2, 3...)
  74. for ($day = 1; $day <= $this->daysInMonth; $day++) {
  75. $colLetter = Coordinate::stringFromColumnIndex($day + 2); // 从 C 列开始
  76. $sheet->setCellValue($colLetter . '3', $day);
  77. $sheet->getColumnDimension($colLetter)->setWidth(8);
  78. }
  79. // 设置第三行行高
  80. $sheet->getRowDimension(3)->setRowHeight(50);
  81. // --- 4. 写入数据行 (从第4行开始) ---
  82. $dataStartRow = 4;
  83. if (!empty($this->data)) {
  84. foreach ($this->data as $rowIndex => $row) {
  85. $currentRow = $dataStartRow + $rowIndex;
  86. foreach ($row as $colIndex => $cellValue) {
  87. $colLetter = Coordinate::stringFromColumnIndex($colIndex + 1);
  88. $sheet->setCellValue($colLetter . $currentRow, $cellValue);
  89. }
  90. }
  91. }
  92. // --- 5. 全局样式微调 ---
  93. $highestRow = $sheet->getHighestRow();
  94. // 1. 设置工时数据区域的格式为数字,并保留两位小数
  95. $dataRange = "C4:{$highestColumn}{$highestRow}";
  96. $sheet->getStyle($dataRange)->getNumberFormat()->setFormatCode('#,##0.00');
  97. // 或者用 NumberFormat::FORMAT_NUMBER_00
  98. // 所有单元格垂直居中
  99. $sheet->getStyle("A1:{$highestColumn}{$highestRow}")->getAlignment()->setVertical(Alignment::VERTICAL_CENTER);
  100. // 表头及日期数据水平居中 (排除 A3 和 B3)
  101. $sheet->getStyle("A3:{$highestColumn}{$highestRow}")->getAlignment()->setHorizontal(Alignment::HORIZONTAL_CENTER);
  102. $sheet->getStyle('B3')->getAlignment()->setHorizontal(Alignment::HORIZONTAL_LEFT); // 斜线格保持左对齐
  103. // 添加表格边框 (从 A3 开始)
  104. $sheet->getStyle("A3:{$highestColumn}{$highestRow}")->applyFromArray([
  105. 'borders' => [
  106. 'allBorders' => [
  107. 'borderStyle' => Border::BORDER_THIN,
  108. ],
  109. ],
  110. ]);
  111. },
  112. ];
  113. }
  114. }