ResearchProjectDetailSheetExport.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  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. class ResearchProjectDetailSheetExport implements WithEvents, WithTitle
  9. {
  10. protected $project;
  11. protected $year;
  12. protected $taxInfo;
  13. public function __construct($year, array $project, array $taxInfo = []) {
  14. $this->year = $year;
  15. $this->project = $project;
  16. $this->taxInfo = $taxInfo;
  17. }
  18. public function title(): string {
  19. return $this->project['project_no'] ?? '项目明细';
  20. }
  21. public function registerEvents(): array {
  22. return [
  23. AfterSheet::class => function (AfterSheet $event) {
  24. $sheet = $event->sheet->getDelegate();
  25. $lastCol = 'AO';
  26. $dataCount = count($this->project['details']);
  27. $lastRow = 7 + $dataCount;
  28. // --- 1. 第一行:基础信息行 ---
  29. $sheet->mergeCells('A1:D1');
  30. $sheet->setCellValue('A1', "加计扣除年度:{$this->year}年");
  31. $sheet->mergeCells('E1:L1');
  32. $sheet->setCellValue('E1', "纳税人识别号:" . ($this->taxInfo['tax_id'] ?? ''));
  33. $sheet->mergeCells('M1:AD1');
  34. $sheet->setCellValue('M1', "纳税人名称(盖章):" . ($this->taxInfo['tax_name'] ?? ''));
  35. $sheet->mergeCells('AE1:AO1');
  36. $sheet->setCellValue('AE1', "金额单位:元(列至角分)");
  37. // --- 2. 绘制全量表头 (第2-7行) ---
  38. $this->drawCorrectHeaders($sheet);
  39. // --- 3. 填充数据 (从第8行开始) ---
  40. $currentRow = 8;
  41. foreach ($this->project['details'] as $row) {
  42. $sheet->fromArray($this->mapRowData($row), null, "A{$currentRow}");
  43. $currentRow++;
  44. }
  45. // --- 4. 样式全局精修 ---
  46. $fullRange = "A1:{$lastCol}{$lastRow}";
  47. $sheet->getStyle($fullRange)->getFont()->setBold(false);
  48. $sheet->getStyle($fullRange)->getAlignment()->applyFromArray([
  49. 'vertical' => Alignment::VERTICAL_CENTER,
  50. 'horizontal' => Alignment::HORIZONTAL_CENTER,
  51. 'wrapText' => true,
  52. ]);
  53. // 信息行特殊处理:靠左
  54. $sheet->getStyle('A1:AO1')->getAlignment()->setHorizontal(Alignment::HORIZONTAL_LEFT);
  55. // --- 5. A列数据区特殊处理:合并单元格并纵向排列文字 ---
  56. if ($dataCount > 0) {
  57. $dataStartRow = 8;
  58. $sheet->mergeCells("A{$dataStartRow}:A{$lastRow}");
  59. $sheet->setCellValue("A{$dataStartRow}", "项目明细\n(填写项目贷方发生额)");
  60. // 设置文字竖排/换行对齐
  61. $sheet->getStyle("A{$dataStartRow}")->getAlignment()->setWrapText(true);
  62. }
  63. // --- 6. 设置行高与列宽 ---
  64. $sheet->getRowDimension(1)->setRowHeight(30);
  65. for ($i = 2; $i <= 6; $i++) {
  66. $sheet->getRowDimension($i)->setRowHeight(40);
  67. }
  68. $sheet->getRowDimension(7)->setRowHeight(30); // 编号行
  69. $wideCols = ['A', 'H', 'R', 'S', 'U', 'V', 'AA', 'AB', 'AC', 'AD', 'AE', 'AF', 'AG', 'AH', 'AI', 'AJ', 'AK', 'AL', 'AM', 'AN', 'AO'];
  70. foreach (range('A', 'AO') as $col) {
  71. $width = in_array($col, $wideCols) ? 25 : 12;
  72. $sheet->getColumnDimension($col)->setWidth($width);
  73. }
  74. // --- 7. 全表框线 ---
  75. $sheet->getStyle("A2:{$lastCol}{$lastRow}")->getBorders()->getAllBorders()->setBorderStyle(Border::BORDER_THIN);
  76. },
  77. ];
  78. }
  79. private function drawCorrectHeaders($sheet) {
  80. // A列特殊:2-6行合并为“项目”,7行填“行次、序号”
  81. $sheet->mergeCells("A2:A6");
  82. $sheet->setCellValue("A2", "项目");
  83. $sheet->setCellValue("A7", "行次、序号");
  84. // B-K: 其他基础项目 (垂直合并 2-7行)
  85. $headers = [
  86. 'B'=>'序号','C'=>'项目名称','D'=>'项目编号','E'=>'研发形式',
  87. 'F'=>'资本化、费用化支出选项','G'=>'项目实施状态选项',
  88. 'H'=>'委托方与受托方是否存在关联关系选项','I'=>'是否委托境外选项','J'=>'研发成果','K'=>'研发成果证书号'
  89. ];
  90. foreach ($headers as $col => $title) {
  91. $sheet->mergeCells("{$col}2:{$col}7");
  92. $sheet->setCellValue("{$col}2", $title);
  93. }
  94. // 一、人员人工
  95. $sheet->mergeCells('L2:N3'); $sheet->setCellValue('L2', '一、人员人工费用');
  96. $sheet->mergeCells('L4:M4'); $sheet->setCellValue('L4', '直接从事研发活动人员');
  97. $sheet->mergeCells('L5:L6'); $sheet->setCellValue('L5', '工资薪金'); $sheet->setCellValue('L7', '1.1');
  98. $sheet->mergeCells('M5:M6'); $sheet->setCellValue('M5', '五险一金'); $sheet->setCellValue('M7', '1.2');
  99. $sheet->mergeCells('N4:N6'); $sheet->setCellValue('N4', "外聘研发人员的\n劳务费用"); $sheet->setCellValue('N7', '1.3');
  100. // 二、直接投入
  101. $sheet->mergeCells('O2:V3'); $sheet->setCellValue('O2', '二、直接投入费用');
  102. $sheet->mergeCells('O4:Q4'); $sheet->setCellValue('O4', '研发活动直接消耗');
  103. $sheet->mergeCells('O5:O6'); $sheet->setCellValue('O5', '材料'); $sheet->setCellValue('O7', '2.1');
  104. $sheet->mergeCells('P5:P6'); $sheet->setCellValue('P5', '燃料'); $sheet->setCellValue('P7', '2.2');
  105. $sheet->mergeCells('Q5:Q6'); $sheet->setCellValue('Q5', '动力费用'); $sheet->setCellValue('Q7', '2.3');
  106. $sheet->mergeCells('R4:R6'); $sheet->setCellValue('R4', "用于中间试验和产品试制的模具、工艺装备开发及制造费"); $sheet->setCellValue('R7', '2.4');
  107. $sheet->mergeCells('S4:S6'); $sheet->setCellValue('S4', "用于不构成固定资产的样品、样机及一般测试手段购置费"); $sheet->setCellValue('S7', '2.5');
  108. $sheet->mergeCells('T4:T6'); $sheet->setCellValue('T4', '用于试制产品的检验验收费'); $sheet->setCellValue('T7', '2.6');
  109. $sheet->mergeCells('U4:U6'); $sheet->setCellValue('U4', "用于研发活动的仪器、设备的运行维护、调整、检验、维修等费用"); $sheet->setCellValue('U7', '2.7');
  110. $sheet->mergeCells('V4:V6'); $sheet->setCellValue('V4', "通过经营租赁方式租入的用于研发活动的仪器、设备租赁费"); $sheet->setCellValue('V7', '2.8');
  111. // 三、折旧
  112. $sheet->mergeCells('W2:X4'); $sheet->setCellValue('W2', '三、折旧费用');
  113. $sheet->mergeCells('W5:W6'); $sheet->setCellValue('W5', '用于研发活动的仪器、设备的折旧费'); $sheet->setCellValue('W7', '3.1');
  114. $sheet->mergeCells('X5:X6'); $sheet->setCellValue('X5', '用于研发活动的建筑物的折旧费'); $sheet->setCellValue('X7', '3.2');
  115. // 四、无形资产摊销
  116. $sheet->mergeCells('Y2:AA4'); $sheet->setCellValue('Y2', '四、无形资产摊销');
  117. $sheet->mergeCells('Y5:Y6'); $sheet->setCellValue('Y5', '用于研发活动的软件的摊销费用'); $sheet->setCellValue('Y7', '4.1');
  118. $sheet->mergeCells('Z5:Z6'); $sheet->setCellValue('Z5', '用于研发活动的专利权的摊销费用'); $sheet->setCellValue('Z7', '4.2');
  119. $sheet->mergeCells('AA5:AA6'); $sheet->setCellValue('AA5', "用于研发活动的非专利技术(包括许可证、专有技术、设计和计算方法等)的摊销费用"); $sheet->setCellValue('AA7', '4.3');
  120. // 五、新产品设计费
  121. $sheet->mergeCells('AB2:AE4'); $sheet->setCellValue('AB2', '五、新产品设计费等');
  122. $sheet->mergeCells('AB5:AB6'); $sheet->setCellValue('AB5', '新产品设计费'); $sheet->setCellValue('AB7', '5.1');
  123. $sheet->mergeCells('AC5:AC6'); $sheet->setCellValue('AC5', '新工艺规程制定费'); $sheet->setCellValue('AC7', '5.2');
  124. $sheet->mergeCells('AD5:AD6'); $sheet->setCellValue('AD5', '新药研制的临床试验费'); $sheet->setCellValue('AD7', '5.3');
  125. $sheet->mergeCells('AE5:AE6'); $sheet->setCellValue('AE5', '勘探开发技术的现场试验费'); $sheet->setCellValue('AE7', '5.4');
  126. // 六、其他相关费用
  127. $sheet->mergeCells('AF2:AJ4'); $sheet->setCellValue('AF2', '六、其他相关费用');
  128. $sheet->mergeCells('AF5:AF6'); $sheet->setCellValue('AF5', '技术图书资料费、资料翻译费等'); $sheet->setCellValue('AF7', '6.1');
  129. $sheet->mergeCells('AG5:AG6'); $sheet->setCellValue('AG5', '研发成果的检索、分析、评议等'); $sheet->setCellValue('AG7', '6.2');
  130. $sheet->mergeCells('AH5:AH6'); $sheet->setCellValue('AH5', '知识产权的申请费、注册费等'); $sheet->setCellValue('AH7', '6.3');
  131. $sheet->mergeCells('AI5:AI6'); $sheet->setCellValue('AI5', '职工福利费、补充养老保险费等'); $sheet->setCellValue('AI7', '6.4');
  132. $sheet->mergeCells('AJ5:AJ6'); $sheet->setCellValue('AJ5', '差旅费、会议费'); $sheet->setCellValue('AJ7', '6.5');
  133. // 七、委托外部
  134. $sheet->mergeCells('AK2:AK6'); $sheet->setCellValue('AK2', "七、委托外部机构或个人进行研发活动所发生的费用"); $sheet->setCellValue('AK7', '7');
  135. $sheet->mergeCells('AL2:AL6'); $sheet->setCellValue('AL2', "其中:委托境外进行研发活动所发生的费用(包括存在关联关系的委托研发"); $sheet->setCellValue('AL7', '7.1');
  136. // 八、九 汇总
  137. $sheet->mergeCells('AM2:AM6'); $sheet->setCellValue('AM2', "八、允许加计扣除的研发费用中的第1至5类费用合计"); $sheet->setCellValue('AM7', '8');
  138. $sheet->mergeCells('AN2:AN6'); $sheet->setCellValue('AN2', "其他相关费用限额=序号8×10%/(1-10%)"); $sheet->setCellValue('AN7', '8.1');
  139. $sheet->mergeCells('AO2:AO6'); $sheet->setCellValue('AO2', "九、当期费用化支出可加计扣除总额"); $sheet->setCellValue('AO7', '9');
  140. }
  141. private function mapRowData($row) {
  142. // A列在 registerEvents 中通过 mergeCells 统一填充了,所以这里返回时第一个位置留空
  143. return [
  144. '', $row['id']??'', $row['rd_name']??'', $row['rd_code']??'', $row['form']??'',
  145. $row['opt']??'', $row['status']??'', $row['rel']??'', $row['os']??'', $row['res']??'', $row['res_no']??'',
  146. $row['v1_1']??0, $row['v1_2']??0, $row['v1_3']??0,
  147. $row['v2_1']??0, $row['v2_2']??0, $row['v2_3']??0, $row['v2_4']??0, $row['v2_5']??0, $row['v2_6']??0, $row['v2_7']??0, $row['v2_8']??0,
  148. $row['v3_1']??0, $row['v3_2']??0,
  149. $row['v4_1']??0, $row['v4_2']??0, $row['v4_3']??0,
  150. $row['v5_1']??0, $row['v5_2']??0, $row['v5_3']??0, $row['v5_4']??0,
  151. $row['v6_1']??0, $row['v6_2']??0, $row['v6_3']??0, $row['v6_4']??0, $row['v6_5']??0,
  152. $row['v7']??0, $row['v7_1']??0,
  153. $row['v8']??0, $row['v8_1']??0, $row['v9']??0
  154. ];
  155. }
  156. }