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

Yii2中如何生成含两个工作表的Excel文件并作为邮件附件?

嘿,这个问题我太懂了!因为CSV格式本身就不支持多工作表,所以咱们得换个思路——生成真正的Excel文件(比如XLSX格式),把两组数据分别放到不同的工作表里,再作为附件用SwiftMailer发送。下面给你一步步实现:

步骤1:安装PhpSpreadsheet库

Yii2本身没有内置多工作表Excel生成工具,咱们用PhpSpreadsheet(PHPExcel的官方替代,功能更完善)。在项目根目录执行composer命令安装:

composer require phpoffice/phpspreadsheet
步骤2:编写生成多工作表Excel的函数

替换原来的getAttachment函数,改成生成包含两个工作表的XLSX文件:

use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
use yii\helpers\ArrayHelper;

/**
 * 生成带双工作表的Excel附件
 * @param array|object $data1 3-Phase类型数据(支持ActiveRecord集合或二维数组)
 * @param array|object $data2 L.T.TOU类型数据(支持ActiveRecord集合或二维数组)
 * @param array $headers 共用表头数组
 * @return \Swift_Attachment
 */
public function getDualSheetExcelAttachment($data1, $data2, $headers)
{
    // 把ActiveRecord对象转成二维数组(如果你的查询结果是对象集合的话)
    $data1 = ArrayHelper::toArray($data1);
    $data2 = ArrayHelper::toArray($data2);

    // 创建Excel实例
    $spreadsheet = new Spreadsheet();
    
    // 第一个工作表:3-Phase
    $sheet1 = $spreadsheet->getActiveSheet();
    $sheet1->setTitle('3-Phase');
    
    // 设置表头并美化样式
    $col = 'A';
    foreach ($headers as $header) {
        $sheet1->setCellValue($col . '1', $header);
        $sheet1->getStyle($col . '1')->getFont()->setBold(true);
        $sheet1->getStyle($col . '1')->getAlignment()->setHorizontal(Alignment::HORIZONTAL_CENTER);
        $col++;
    }
    
    // 填充3-Phase数据
    $row = 2;
    foreach ($data1 as $item) {
        $col = 'A';
        foreach ($item as $value) {
            $sheet1->setCellValue($col . $row, $value);
            $col++;
        }
        $row++;
    }
    
    // 添加第二个工作表:L.T.TOU
    $sheet2 = $spreadsheet->createSheet();
    $sheet2->setTitle('L.T.TOU');
    
    // 复用表头设置
    $col = 'A';
    foreach ($headers as $header) {
        $sheet2->setCellValue($col . '1', $header);
        $sheet2->getStyle($col . '1')->getFont()->setBold(true);
        $sheet2->getStyle($col . '1')->getAlignment()->setHorizontal(Alignment::HORIZONTAL_CENTER);
        $col++;
    }
    
    // 填充L.T.TOU数据
    $row = 2;
    foreach ($data2 as $item) {
        $col = 'A';
        foreach ($item as $value) {
            $sheet2->setCellValue($col . $row, $value);
            $col++;
        }
        $row++;
    }
    
    // 自动调整列宽(提升用户体验)
    foreach ([$sheet1, $sheet2] as $sheet) {
        foreach (range('A', $sheet->getHighestColumn()) as $column) {
            $sheet->getColumnDimension($column)->setAutoSize(true);
        }
    }
    
    // 生成临时文件(避免占用服务器永久存储)
    $tempFile = tempnam(sys_get_temp_dir(), 'report_');
    $writer = new Xlsx($spreadsheet);
    $writer->save($tempFile);
    
    // 创建SwiftMailer附件对象
    $attachment = \Swift_Attachment::fromPath($tempFile)
        ->setFilename('data_report.xlsx') // 收件人看到的附件名
        ->setContentType('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
    
    // 释放Excel资源
    $spreadsheet->disconnectWorksheets();
    unset($spreadsheet);
    
    // 邮件发送后自动删除临时文件(防止垃圾文件堆积)
    \Yii::$app->mailer->on(\yii\swiftmailer\Mailer::EVENT_AFTER_SEND, function ($event) use ($tempFile) {
        if (file_exists($tempFile)) {
            unlink($tempFile);
        }
    });
    
    return $attachment;
}
步骤3:在邮件发送逻辑中调用函数

把生成的附件添加到邮件里发送:

// 替换成你实际的表头数组
$headers = ['ID', '名称', '数值1', '数值2', '时间'];

// 你的SQL查询结果:3-Phase和L.T.TOU数据
$result = // 3-Phase类型数据集合/数组
$result_set = // L.T.TOU类型数据集合/数组

// 生成双工作表Excel附件
$attachment = $this->getDualSheetExcelAttachment($result, $result_set, $headers);

// 发送邮件
\Yii::$app->mailer->compose()
    ->setTo('user@example.com')
    ->setSubject('双工作表数据报告')
    ->setTextBody('您好,附件包含3-Phase和L.T.TOU两组数据,分别在两个工作表中。')
    ->attach($attachment)
    ->send();
注意事项
  • 如果你的SQL查询结果是ActiveRecord对象集合,ArrayHelper::toArray()会自动把对象转成键值对数组,完美匹配表头列。
  • 临时文件用系统临时目录存储,发送后自动删除,不会占用服务器空间。
  • ContentType设置为XLSX的标准类型,确保邮箱客户端能正确识别文件格式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:56:05