You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel Maatwebsite Excel 3.1:如何添加自定义表头与合计页脚?

搞定Laravel Excel(maatwebsite 3.1):自定义表头+金额合计页脚实现方案

我来帮你解决这个需求,正好对maatwebsite Excel 3.1版本的玩法很熟。你的现有代码已经能导出销售明细,但要加自定义表头和合计页脚,我们可以通过事件监听+PhpSpreadsheet底层操作来实现,下面一步步来:

先修正现有代码的小坑

先把你代码里的几个小问题补了,不然容易报错:

  1. 补上RegistersEventListeners的命名空间引入(你之前漏了)
  2. 把控制器的导出方法从Export类里挪出来——它本来就属于控制器(比如SalesLogController),别混在Export类里

一、添加开头的自定义表头

这里的自定义表头指的是那种大标题(比如“XX飞机销售日志明细”),放在现有列头的上方。我们用AfterSheet事件来实现:

  • 在数据列头上方插入新行
  • 合并单元格放标题,再设置加粗、居中之类的样式

二、添加金额合计页脚

要做合计,得先算出所有明细的金额总和,然后在数据最后一行下面插合计行:

  • 在Export类里存一个合计金额的属性
  • 执行查询后计算总和
  • 同样用AfterSheet事件找到最后一行,插入合计行并设置样式

完整修改后的代码

1. SalesExport类(核心)

<?php

namespace App\Exports;

use App\SalesLog;
use Maatwebsite\Excel\Concerns\FromQuery;
use Maatwebsite\Excel\Concerns\Exportable;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
use Maatwebsite\Excel\Concerns\WithEvents;
use Maatwebsite\Excel\Concerns\RegistersEventListeners;
use Maatwebsite\Excel\Events\AfterSheet;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
use PhpOffice\PhpSpreadsheet\Style\Font;

class SalesExport implements FromQuery, WithHeadings, ShouldAutoSize, WithEvents
{
    use Exportable, RegistersEventListeners;

    protected $logId;
    protected $aircraftName;
    protected $totalAmount = 0;

    public function __construct($log_id, $aircraft_name)
    {
        $this->logId = $log_id;
        $this->aircraftName = $aircraft_name;
    }

    public function headings(): array
    {
        return [
            '#No',
            'Item Description',
            'Unit Type',
            'Item Price',
        ];
    }

    public function query()
    {
        // 构建查询
        $query = SalesLog::query()
            ->join('sales_log_items', 'sales_logs.id', '=', 'sales_log_items.sales_log_id')
            ->where('sales_log_items.sales_log_id', $this->logId)
            ->select(
                'sales_log_items.product_id',
                'sales_log_items.name',
                'sales_log_items.unit_type',
                'sales_log_items.price'
            );

        // 计算总金额:先执行查询拿到集合,再求和
        $this->totalAmount = $query->get()->sum('price');

        return $query;
    }

    public function registerEvents(): array
    {
        return [
            AfterSheet::class => function (AfterSheet $event) {
                $sheet = $event->sheet->getDelegate();

                // --- 1. 添加自定义大表头 ---
                // 在第1行插入新行(原来的列头会往下移)
                $sheet->insertNewRowBefore(1, 1);
                // 合并A1到D1的单元格,放大标题
                $sheet->mergeCells('A1:D1');
                $sheet->setCellValue('A1', "{$this->aircraftName} 销售日志明细");
                // 设置大标题样式:加粗、居中、字体放大
                $sheet->getStyle('A1')->applyFromArray([
                    'font' => [
                        'bold' => true,
                        'size' => 16,
                    ],
                    'alignment' => [
                        'horizontal' => Alignment::HORIZONTAL_CENTER,
                    ],
                ]);

                // --- 2. 添加金额合计行 ---
                // 获取当前Excel的最后一行(包含自定义表头、列头、数据)
                $lastRow = $sheet->getHighestRow();
                // 在最后一行下面插一行放合计
                $sheet->insertNewRowAfter($lastRow, 1);
                // 设置合计内容
                $sheet->setCellValue('A' . ($lastRow + 1), '合计');
                $sheet->mergeCells('A' . ($lastRow + 1) . ':C' . ($lastRow + 1));
                $sheet->setCellValue('D' . ($lastRow + 1), $this->totalAmount);
                // 设置合计行样式:加粗,金额列右对齐
                $sheet->getStyle('A' . ($lastRow + 1) . ':D' . ($lastRow + 1))->applyFromArray([
                    'font' => [
                        'bold' => true,
                    ],
                    'alignment' => [
                        'horizontal' => Alignment::HORIZONTAL_RIGHT,
                    ],
                ]);
                // 单独把“合计”文字改成左对齐,更美观
                $sheet->getStyle('A' . ($lastRow + 1))->getAlignment()->setHorizontal(Alignment::HORIZONTAL_LEFT);
            },
        ];
    }
}

2. 控制器中的导出方法(比如SalesLogController)

public function exportSalesLog($log_id)
{
    // 用findOrFail替代find,避免找不到日志时报错
    $salesLog = SalesLog::findOrFail($log_id);
    $date = date('y-m-d');
    // 文件名可以加航班号,更易识别
    $excelTitle = "sales_log_{$date}_{$salesLog->flight_number_one}";

    return (new SalesExport($log_id, $salesLog->aircraft_name))->download("{$excelTitle}.xlsx");
}

关键点解释

  • 自定义表头:通过PhpSpreadsheet的insertNewRowBefore插入行,mergeCells合并单元格,再用样式API美化标题
  • 金额合计:先通过查询集合的sum方法计算总金额,再找到数据最后一行插入合计行
  • WithEvents:maatwebsite 3.1依赖事件监听来操作底层的PhpSpreadsheet对象,这是实现自定义Excel操作的核心方式

内容的提问来源于stack exchange,提问作者testerr testeerr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 08:22:31