|
@@ -28,7 +28,7 @@ class ResearchExpenseSheetExport implements FromCollection, WithEvents, WithStyl
|
|
|
$this->data = $data;
|
|
$this->data = $data;
|
|
|
$this->projectInfo = $projectInfo;
|
|
$this->projectInfo = $projectInfo;
|
|
|
$this->year = $year;
|
|
$this->year = $year;
|
|
|
- $this->dynamicHeaders = $dynamicHeaders;
|
|
|
|
|
|
|
+ $this->dynamicHeaders = $dynamicHeaders; // 此时这里已经包含了排好序的 人员、折旧 及所有动态科目
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public function title(): string { return $this->sheetTitle; }
|
|
public function title(): string { return $this->sheetTitle; }
|
|
@@ -41,10 +41,10 @@ class ResearchExpenseSheetExport implements FromCollection, WithEvents, WithStyl
|
|
|
AfterSheet::class => function(AfterSheet $event) {
|
|
AfterSheet::class => function(AfterSheet $event) {
|
|
|
$sheet = $event->sheet->getDelegate();
|
|
$sheet = $event->sheet->getDelegate();
|
|
|
|
|
|
|
|
- // --- 1. 计算列信息 ---
|
|
|
|
|
- $baseColumnCount = 8; // A-H (日期 到 折旧)
|
|
|
|
|
- $dynamicCount = count($this->dynamicHeaders);
|
|
|
|
|
- $totalColumnCount = $baseColumnCount + $dynamicCount + 2; // 加上委托研发2列
|
|
|
|
|
|
|
+ // --- 1. 计算精准列信息 ---
|
|
|
|
|
+ $baseColumnCount = 6; // A-F (固定前 6 列:从 日期 到 税法规定的归集金额)
|
|
|
|
|
+ $dynamicCount = count($this->dynamicHeaders); // 包含排序后的人员、折旧与所有动态科目数
|
|
|
|
|
+ $totalColumnCount = $baseColumnCount + $dynamicCount + 2; // 再加上尾部委托研发 2 列
|
|
|
$highestColumn = Coordinate::stringFromColumnIndex($totalColumnCount);
|
|
$highestColumn = Coordinate::stringFromColumnIndex($totalColumnCount);
|
|
|
$highestRow = $sheet->getHighestRow(); // 获取最后一行(合计行)
|
|
$highestRow = $sheet->getHighestRow(); // 获取最后一行(合计行)
|
|
|
|
|
|
|
@@ -87,30 +87,29 @@ class ResearchExpenseSheetExport implements FromCollection, WithEvents, WithStyl
|
|
|
$sheet->mergeCells("F4:F6");
|
|
$sheet->mergeCells("F4:F6");
|
|
|
$sheet->setCellValue('F4', "税法规定的归\n集金额");
|
|
$sheet->setCellValue('F4', "税法规定的归\n集金额");
|
|
|
|
|
|
|
|
- // G-末尾: 费用明细总标题
|
|
|
|
|
|
|
+ // G-末尾: 费用明细大总标题 (第7列到最后一列)
|
|
|
$sheet->mergeCells("G4:{$highestColumn}4");
|
|
$sheet->mergeCells("G4:{$highestColumn}4");
|
|
|
$sheet->setCellValue('G4', '费用明细(税法规定)');
|
|
$sheet->setCellValue('G4', '费用明细(税法规定)');
|
|
|
|
|
|
|
|
- // 固定明细项:人员人工(G), 折旧(H)
|
|
|
|
|
- $sheet->mergeCells("G5:G6"); $sheet->setCellValue("G5", '人员人工费用');
|
|
|
|
|
- $sheet->mergeCells("H5:H6"); $sheet->setCellValue("H5", '折旧费用');
|
|
|
|
|
-
|
|
|
|
|
- // 动态明细项 (从 I/第9列开始)
|
|
|
|
|
- $currentColIdx = 9;
|
|
|
|
|
|
|
+ // ================== 【核心调整:动态平铺所有科目】 ==================
|
|
|
|
|
+ // 从第 7 列 (G列) 开始动态输出所有排好序的科目(包含人员人工、折旧以及其他动态科目)
|
|
|
|
|
+ $currentColIdx = 7;
|
|
|
foreach ($this->dynamicHeaders as $headerText) {
|
|
foreach ($this->dynamicHeaders as $headerText) {
|
|
|
$colLetter = Coordinate::stringFromColumnIndex($currentColIdx);
|
|
$colLetter = Coordinate::stringFromColumnIndex($currentColIdx);
|
|
|
|
|
+ // 纵向合并 5 和 6 行
|
|
|
$sheet->mergeCells("{$colLetter}5:{$colLetter}6");
|
|
$sheet->mergeCells("{$colLetter}5:{$colLetter}6");
|
|
|
$sheet->setCellValue("{$colLetter}5", $headerText);
|
|
$sheet->setCellValue("{$colLetter}5", $headerText);
|
|
|
$currentColIdx++;
|
|
$currentColIdx++;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 委托研发 (最后两列)
|
|
|
|
|
|
|
+ // 委托研发 (紧跟在所有排序科目后面的最后两列)
|
|
|
$mCol = Coordinate::stringFromColumnIndex($currentColIdx);
|
|
$mCol = Coordinate::stringFromColumnIndex($currentColIdx);
|
|
|
$nCol = Coordinate::stringFromColumnIndex($currentColIdx + 1);
|
|
$nCol = Coordinate::stringFromColumnIndex($currentColIdx + 1);
|
|
|
$sheet->mergeCells("{$mCol}5:{$nCol}5");
|
|
$sheet->mergeCells("{$mCol}5:{$nCol}5");
|
|
|
$sheet->setCellValue("{$mCol}5", '委托研发费用');
|
|
$sheet->setCellValue("{$mCol}5", '委托研发费用');
|
|
|
$sheet->setCellValue("{$mCol}6", "委托境内研发");
|
|
$sheet->setCellValue("{$mCol}6", "委托境内研发");
|
|
|
$sheet->setCellValue("{$nCol}6", "委托境外研发");
|
|
$sheet->setCellValue("{$nCol}6", "委托境外研发");
|
|
|
|
|
+ // ====================================================================
|
|
|
|
|
|
|
|
// --- 6. 强制刷新表头样式 (边框和居中) ---
|
|
// --- 6. 强制刷新表头样式 (边框和居中) ---
|
|
|
$headerRange = "A4:{$highestColumn}6";
|
|
$headerRange = "A4:{$highestColumn}6";
|
|
@@ -126,10 +125,7 @@ class ResearchExpenseSheetExport implements FromCollection, WithEvents, WithStyl
|
|
|
]);
|
|
]);
|
|
|
|
|
|
|
|
// --- 7. 合计行特殊处理 (合并 A-D 列) ---
|
|
// --- 7. 合计行特殊处理 (合并 A-D 列) ---
|
|
|
- // 注意:由于数据从 A7 开始,且我们在 Controller 塞入了合计行,
|
|
|
|
|
- // 所以 $highestRow 对应的就是那一行。
|
|
|
|
|
$sheet->mergeCells("A{$highestRow}:D{$highestRow}");
|
|
$sheet->mergeCells("A{$highestRow}:D{$highestRow}");
|
|
|
- // 确保合计单元格样式加粗且有背景色
|
|
|
|
|
$footerRange = "A{$highestRow}:{$highestColumn}{$highestRow}";
|
|
$footerRange = "A{$highestRow}:{$highestColumn}{$highestRow}";
|
|
|
$sheet->getStyle($footerRange)->applyFromArray([
|
|
$sheet->getStyle($footerRange)->applyFromArray([
|
|
|
'fill' => [
|
|
'fill' => [
|
|
@@ -160,8 +156,8 @@ class ResearchExpenseSheetExport implements FromCollection, WithEvents, WithStyl
|
|
|
public function styles(Worksheet $sheet)
|
|
public function styles(Worksheet $sheet)
|
|
|
{
|
|
{
|
|
|
$highestRow = $sheet->getHighestRow();
|
|
$highestRow = $sheet->getHighestRow();
|
|
|
- // 样式中也需要重新动态获取列,否则 styles 的作用范围会跟不上
|
|
|
|
|
- $totalCol = 8 + count($this->dynamicHeaders) + 2;
|
|
|
|
|
|
|
+ // 这里的总列数计算也同步保持一致逻辑
|
|
|
|
|
+ $totalCol = 6 + count($this->dynamicHeaders) + 2;
|
|
|
$highestCol = Coordinate::stringFromColumnIndex($totalCol);
|
|
$highestCol = Coordinate::stringFromColumnIndex($totalCol);
|
|
|
|
|
|
|
|
// 数据区域边框 (从第7行开始)
|
|
// 数据区域边框 (从第7行开始)
|