Laravel Excel导出合并列表头实现求助
Laravel Excel 合并列表头实现方案
所有逻辑完全在Export类中处理,控制器仅负责传递参数和触发导出操作。以下是具体实现步骤:
1. Export类核心实现
先引入必要依赖,通过构造函数接收前端下拉框数据,再通过BeforeSheet事件完成表头合并、内容填充和样式设置:
<?php namespace App\Exports; use Maatwebsite\Excel\Concerns\FromCollection; use Maatwebsite\Excel\Concerns\WithHeadings; use Maatwebsite\Excel\Concerns\WithEvents; use Maatwebsite\Excel\Events\BeforeSheet; use PhpOffice\PhpSpreadsheet\Cell\Coordinate; use PhpOffice\PhpSpreadsheet\Style\Alignment; use App\Models\Month; class YourExport implements FromCollection, WithHeadings, WithEvents { protected $dropdownData; // 接收前端下拉框数据 public function __construct($dropdownData) { $this->dropdownData = $dropdownData; } // 原有数据集合(你的业务数据) public function collection() { return \App\Models\YourModel::all(); } // 原有A-Z列的基础表头 public function headings(): array { return ['列A', '列B', '列C', ..., '列Z']; } // 注册Excel事件处理表头逻辑 public function registerEvents(): array { return [ BeforeSheet::class => function(BeforeSheet $event) { $sheet = $event->sheet; $months = Month::pluck('name')->toArray(); // 从数据库取月份数据 $dropdownItems = $this->dropdownData; // 插入2行空白行,避免覆盖原有A-Z2行及下方数据 $sheet->insertNewRowBefore(1, 2); // 第一行:合并单元格的月份表头(从D1开始) $startCol = 'D'; $currentCol = $startCol; foreach ($months as $month) { // 计算当前月份对应的12列结束位置 $currentColIndex = Coordinate::columnIndexFromString($currentCol); $endColIndex = $currentColIndex + 11; $endCol = Coordinate::stringFromColumnIndex($endColIndex); // 合并单元格 $sheet->mergeCells("{$currentCol}1:{$endCol}1"); // 设置月份名称 $sheet->setCellValue("{$currentCol}1", $month); // 设置样式:居中+加粗 $sheet->getStyle("{$currentCol}1:{$endCol}1")->applyFromArray([ 'alignment' => [ 'horizontal' => Alignment::HORIZONTAL_CENTER, 'vertical' => Alignment::VERTICAL_CENTER, ], 'font' => [ 'bold' => true, 'size' => 12, ], ]); // 切换到下一个月份的起始列 $currentCol = Coordinate::stringFromColumnIndex($endColIndex + 1); } // 第二行:下拉框数据循环12次填充(从D2开始) $currentCol = $startCol; foreach ($dropdownItems as $item) { for ($i = 0; $i < 12; $i++) { $sheet->setCellValue("{$currentCol}2", $item); // 设置样式:居中+加粗 $sheet->getStyle("{$currentCol}2")->applyFromArray([ 'alignment' => [ 'horizontal' => Alignment::HORIZONTAL_CENTER, ], 'font' => [ 'bold' => true, ], ]); // 切换到下一列 $currentCol = Coordinate::stringFromColumnIndex(Coordinate::columnIndexFromString($currentCol) + 1); } } // 设置列宽,适配内容 $totalColumns = count($months) * 12; $startColIndex = Coordinate::columnIndexFromString($startCol); for ($i = $startColIndex; $i < $startColIndex + $totalColumns; $i++) { $sheet->getColumnDimension(Coordinate::stringFromColumnIndex($i))->setWidth(10); } }, ]; } }
2. 控制器调用
控制器只需接收前端下拉框数据,传递给Export类并触发导出:
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use Maatwebsite\Excel\Facades\Excel; use App\Exports\YourExport; class ExportController extends Controller { public function export(Request $request) { // 获取前端下拉框提交的数据(假设表单name为dropdown_items) $dropdownData = $request->input('dropdown_items'); return Excel::download(new YourExport($dropdownData), 'report.xlsx'); } }
关键说明
- 合并单元格逻辑依赖
PhpSpreadsheet的Coordinate类,用于计算列的起始/结束位置 - 通过
insertNewRowBefore插入空白行,确保原有数据不被覆盖 - 样式可根据需求调整,比如字体大小、背景色等
内容的提问来源于stack exchange,提问作者Muhd Hakimi
相关产品推荐
相关产品推荐

