Skip to content
carlin-rj edited this page Nov 3, 2023 · 1 revision

快速启动

该文件可以在以下位置找到app/Exports:

.
├── app
│   ├── Exports
│   │   ├── UsersExport.php
│ 
└── composer.json

您可以在app/Exports中创建以下内容

<?php

namespace App\Exports;

use App\Models\User;
use Mckue\Excel\Concerns\FromCollection;

class UsersExport implements FromCollection
{
    public function collection()
    {
        return User::all();
    }
}

在您的控制器中,您现在可以调用此导出:

<?php

namespace App\Http\Controllers;

use App\Exports\UsersExport;
use Mckue\Excel\Facades\Excel;

class UsersController extends Controller 
{
    public function export() 
    {
        return Excel::download(new UsersExport, 'users.xlsx');
    }
}
Route::get('users/export/', [UsersController::class, 'export']);

在您的下载文件夹中找到您的users.xlsx!

导出到 collections

开始导出的最简单方法是创建自定义导出类。我们将使用发票导出作为示例。 InvoicesExport创建一个名为的新类app/Exports:

namespace App\Exports;

use App\Invoice;
use Muckue\Excel\Concerns\FromCollection;

class InvoicesExport implements FromCollection
{
    public function collection()
    {
        return Invoice::all();
    }
}

在您的控制器中,我们现在可以下载此导出:

public function export() 
{
    return Excel::download(new InvoicesExport, 'invoices.xlsx');
}

您可以选择传入是否输出标头和自定义响应标头:

public function export() 
{
    return Excel::download(new InvoicesExport, 'invoices.xlsx', true, ['X-Vapor-Base64-Encode' => 'True']);
}

或者将其存储在磁盘上(例如 s3):

public function storeExcel() 
{
    return Excel::store(new InvoicesExport, 'invoices.xlsx', 's3');
}

使用自定义结构

如果您不使用 Eloquent 或有其他数据源(例如 API、MongoDB、缓存等),您还可以返回自定义集合:

namespace App\Exports;

use App\Invoice;
use Mckue\Excel\Concerns\FromCollection;

class InvoicesExport implements FromCollection
{
    public function collection()
    {
        return new Collection([
            [1, 2, 3],
            [4, 5, 6]
        ]);
    }
}

使用数组

如果您更喜欢使用普通数组而不是集合,则可以使用以下FromArray问题:

namespace App\Exports;

use App\Invoice;
use Mckue\Excel\Concerns\FromArray;

class InvoicesExport implements FromArray
{
    public function array(): array
    {
        return [
            [1, 2, 3],
            [4, 5, 6]
        ];
    }
}

如果需要将数据从控制器传递到导出,可以使用构造函数来执行此操作:

namespace App\Exports;

use App\Invoice;
use Mckue\Excel\Concerns\FromArray;

class InvoicesExport implements FromArray
{
    protected $invoices;

    public function __construct(array $invoices)
    {
        $this->invoices = $invoices;
    }

    public function array(): array
    {
        return $this->invoices;
    }
}

在您的控制器中,您现在可以使用导出类的构造函数:

public function export() 
{
    $export = new InvoicesExport([
        [1, 2, 3],
        [4, 5, 6]
    ]);

    return Excel::download($export, 'invoices.xlsx');
}

依赖注入

如果您的导出需要依赖项,您可以注入导出类:

namespace App\Exports;

use Mckue\Excel\Concerns\FromCollection;

class InvoicesExport implements FromCollection
{
    public function __construct(InvoicesRepository $invoices)
    {
        $this->invoices = $invoices;
    }

    public function collection()
    {
        return $this->invoices->all();
    }
}
public function export(Excel $excel, InvoicesExport $export) 
{
    return $excel->download($export, 'invoices.xlsx');
}

存储原始内容

如果您想接收导出文件的原始内容,可以使用以下raw()方法:

$contents = Excel::raw(new InvoicesExport);

Collection macros

该包为 Laravel 的集合类提供了一些宏,以轻松下载或存储集合。

User::all()->downloadExcel(
    $filePath,
    $writerType = null,
    $headings = false
)
(new Collection([[1, 2, 3], [1, 2, 3]]))->downloadExcel(
    $filePath,
    $writerType = null,
    $headings = false
)
User::all()->storeExcel(
    $filePath,
    $disk = null,
    $writerType = null,
    $headings = false
)

将导出存储在磁盘上

默认磁盘

public function storeExcel() 
{
    // Store on default disk
    Excel::store(new InvoicesExport(2018), 'invoices.xlsx');
}

定制磁盘

public function storeExcel() 
{
    // Store on a different disk (e.g. s3)
    Excel::store(new InvoicesExport(2018), 'invoices.xlsx', 's3');
}

磁盘选项

public function storeExcel() 
{
    Excel::store(new InvoicesExport(2018), 'invoices.xlsx', 's3', null, [
        'visibility' => 'private',
    ]);
}

Laravel私有文件的快捷方式:

public function storeExcel() 
{
    Excel::store(new InvoicesExport(2018), 'invoices.xlsx', 's3', null, 'private');
}

导出格式(只支持xlsx)

return Excel::download(new InvoicesExport, 'invoices.xlsx', \Mckue\Excel\Excel::XLSX);

Exportables

在前面的示例中,我们使用Excel::download 门面来启动导出。 Laravel Excel 还提供了一个Mckue\Excel\Concerns\Exportable特征,使导出类可导出。

namespace App\Exports;

use App\Invoice;
use Mckue\Excel\Concerns\FromCollection;
use Mckue\Excel\Concerns\Exportable;

class InvoicesExport implements FromCollection
{
    use Exportable;

    public function collection()
    {
        return Invoice::all();
    }
}

我们现在可以下载导出而无需门面:

return (new InvoicesExport)->download('invoices.xlsx');

或者将其存储在磁盘上:

return (new InvoicesExport)->store('invoices.xlsx', 's3');

如果您愿意,还可以将选项传递到磁盘:

return (new InvoicesExport)->store('invoices.xlsx', 's3', null, 'private');

通过查询导出

在前面的示例中,我们在导出类中进行了查询。虽然这对于小型出口来说是一个很好的解决方案,但对于较大的出口来说,这将付出高昂的性能代价。

通过使用FromQuery关注点,我们可以准备导出查询。该查询在幕后以块的形式执行。

在InvoicesExport类中,添加FromQuery关注点并返回查询。一定不要 ->get()结果!

namespace App\Exports;

use App\Invoice;
use Mckue\Excel\Concerns\FromQuery;
use Mckue\Excel\Concerns\Exportable;

class InvoicesExport implements FromQuery
{
    use Exportable;

    public function query()
    {
        return Invoice::query();
    }
}

我们仍然可以用同样的方式下载导出

return (new InvoicesExport)->download('invoices.xlsx');

自定义查询

通过将自定义参数作为依赖项传递给导出类,可以轻松地将自定义参数传递给查询。

namespace App\Exports;

use App\Invoice;
use Mckue\Excel\Concerns\FromQuery;
use Mckue\Excel\Concerns\Exportable;

class InvoicesExport implements FromQuery
{
    use Exportable;

    public function __construct(int $year)
    {
        $this->year = $year;
    }

    public function query()
    {
        return Invoice::query()->whereYear('created_at', $this->year);
    }
}

现在可以将年份作为导出类的依赖项传递:

return (new InvoicesExport(2018))->download('invoices.xlsx');

我们也可以使用以下方法调整年份forYear:

namespace App\Exports;

use App\Invoice;
use Mckue\Excel\Concerns\FromQuery;
use Mckue\Excel\Concerns\Exportable;

class InvoicesExport implements FromQuery
{
    use Exportable;

    public function forYear(int $year)
    {
        $this->year = $year;
        
        return $this;
    }

    public function query()
    {
        return Invoice::query()->whereYear('created_at', $this->year);
    }
}
return (new InvoicesExport)->forYear(2018)->download('invoices.xlsx');

编排数据

编排行

通过添加,WithMapping您可以映射需要添加为行的数据。这样您就可以控制每列的​​实际来源。如果使用 Eloquent 查询生成器:

use Mckue\Excel\Concerns\FromQuery;
use Mckue\Excel\Concerns\WithMapping;

class InvoicesExport implements FromQuery, WithMapping
{    
    /**
    * @var Invoice $invoice
    */
    public function map($invoice): array
    {
        return [
            $invoice->invoice_number,
            $invoice->user->name,
            Date::dateTimeToExcel($invoice->created_at),
        ];
    }
}

多行

您还可以在映射函数内返回多行:

use Mckue\Excel\Concerns\FromQuery;
use Mckue\Excel\Concerns\WithMapping;

class InvoicesExport implements FromQuery, WithMapping
{    
    /**
    * @var Invoice $invoice
    */
    public function map($invoice): array
    {
        // This example will return 3 rows.
        // First row will have 2 column, the next 2 will have 1 column
        return [
            [
                $invoice->invoice_number,
                Date::dateTimeToExcel($invoice->created_at),
            ],
            [
                $invoice->lines->first()->description,
            ],
            [
                $invoice->lines->last()->description,
            ]
        ];
    }
}

添加标题行

通过添加,WithHeadings。标题行将添加为工作表的第一行。

use Mckue\Excel\Concerns\FromQuery;
use Mckue\Excel\Concerns\WithHeadings;

class InvoicesExport implements FromQuery, WithHeadings
{   
    public function headings(): array
    {
        return [
            '#',
            'User',
            'Date',
        ];
    }
}

如果您需要有多个标题行,您可以从该headings()方法返回多行:

use Mckue\Excel\Concerns\FromQuery;
use Mckue\Excel\Concerns\WithHeadings;

class InvoicesExport implements FromQuery, WithHeadings
{   
    public function headings(): array
    {
        return [
           ['First row', 'First row'],
           ['Second row', 'Second row'],
        ];
    }
}

Prepare rows

如果您需要在将这些行附加到工作表之前准备行,您可以将方法添加prepareRows到导出类中。在查询输出并调用map()之前将调用此方法。

use Mckue\Excel\Concerns\FromQuery;
use Mckue\Excel\Concerns\WithHeadings;

class UsersExport implements FromQuery, WithHeadings
{   
    public function prepareRows($rows): array
    {
        return [....]
    }
}

自定义列格式

自定义列

您可以使用 轻松格式化整列WithColumnFormatting

<?php 
use Mckue\Excel\Concerns\WithColumnFormatting;
use Mckue\Excel\Concerns\WithMapping;


class InvoicesExport implements WithColumnFormatting, WithMapping
{
    public function map($invoice): array
    {
        return [
            $invoice->invoice_number,
            Date::dateTimeToExcel($invoice->created_at),
            $invoice->total
        ];
    }
    
    public function columnFormats(Excel $worksheet)
    {
        //例如设置a列加粗:
        $format    = new \Vtiful\Kernel\Format($worksheet->getHandle());
        $boldStyle = $format->bold()->toResource()

        $worksheet->setColumn('A:A', 200, $boldStyle);
    }
}

自定义行

您可以使用 轻松格式化整列WithRowFormatting

<?php 
use Mckue\Excel\Concerns\WithRowFormatting;
use Mckue\Excel\Concerns\WithMapping;

class InvoicesExport implements WithRowFormatting, WithMapping
{
    public function map($invoice): array
    {
        return [
            $invoice->invoice_number,
            Date::dateTimeToExcel($invoice->created_at),
            $invoice->total
        ];
    }
    
    public function formatRows(Excel $worksheet)
    {
        //例如设置a1列加粗:
        $format    = new \Vtiful\Kernel\Format($worksheet->getHandle());
        $boldStyle = $format->bold()->toResource()

        $worksheet->setRow('A1', 200, $boldStyle);
    }
}

导出接口实现

接口 作用
Mckue\Excel\Concerns\FromArray 使用数组来填充导出。
Mckue\Excel\Concerns\FromCollection 使用 Laravel Collection 来填充导出。
Mckue\Excel\Concerns\FromGenerator 使用生成器来填充导出。
Mckue\Excel\Concerns\FromIterator 使用迭代器来填充导出。
Mckue\Excel\Concerns\FromQuery 使用 Eloquent 查询来填充导出。
Mckue\Excel\Concerns\WithColumnFormatting 设置某些列的格式。
Mckue\Excel\Concerns\WithCustomChunkSize 允许可导出项定义其块大小。
Mckue\Excel\Concerns\WithCustomQuerySize 允许实现 FromQuery 关注点的可导出对象提供自己的自定义查询大小。
Mckue\Excel\Concerns\WithCustomStartCell 允许指定自定义起始单元。请注意,这仅支持 FromCollection 导出。
Mckue\Excel\Concerns\WithEvents 注册事件
Mckue\Excel\Concerns\WithHeadings 前置标题行。
Mckue\Excel\Concerns\WithMapping 在将行写入文件之前对其进行格式化。
Mckue\Excel\Concerns\WithMultipleSheets 启用多页支持。每张表都可以有自己的关注点(除了这张表)。
Mckue\Excel\Concerns\WithProperties 允许设置文档的属性。
Mckue\Excel\Concerns\WithStyles 允许在工作表上设置样式。
Mckue\Excel\Concerns\WithTitle 设置工作簿或工作表标题。

事件拓展

事件示例

导出过程有一些事件,您可以利用这些事件与底层类进行交互,以将自定义行为添加到导出中。

您可以使用事件挂钩到父包。如果您需要完全控制导出,则无需使用“查询”或“查看”等便捷方法。

这些事件将通过添加关注来激活WithEvents。在该registerEvents方法内部,您必须返回一个事件数组。键是事件的完全限定名称 (FQN),值是可调用的事件侦听器。这可以是闭包、可数组调用或可调用类。

namespace App\Exports;

use Mckue\Excel\Concerns\WithEvents;
use Mckue\Excel\Events\BeforeExport;
use Mckue\Excel\Events\BeforeWriting;
use Mckue\Excel\Events\BeforeSheet;

class InvoicesExport implements WithEvents
{
    /**
     * @return array
     */
    public function registerEvents(): array
    {
        return [
            // Handle by a closure.
            BeforeExport::class => function(BeforeExport $event) {
                $event->writer->getProperties()->setCreator('Patrick');
            },
            
            // Array callable, refering to a static method.
            BeforeWriting::class => [self::class, 'beforeWriting'],
            
            // Using a class with an __invoke method.
            BeforeSheet::class => new BeforeSheetHandler()
        ];
    }
    
    public static function beforeWriting(BeforeWriting $event) 
    {
        //
    }
}

自动注册事件监听器

namespace App\Exports;

use Mckue\Excel\Concerns\WithEvents;
use Mckue\Excel\Concerns\RegistersEventListeners;
use Mckue\Excel\Events\BeforeExport;
use Mckue\Excel\Events\BeforeWriting;
use Mckue\Excel\Events\BeforeSheet;
use Mckue\Excel\Events\AfterSheet;

class InvoicesExport implements WithEvents
{
    use Exportable, RegistersEventListeners;
    
    public static function beforeExport(BeforeExport $event)
    {
        //
    }

    public static function beforeWriting(BeforeWriting $event)
    {
        //
    }

    public static function beforeSheet(BeforeSheet $event)
    {
        //
    }

    public static function afterSheet(AfterSheet $event)
    {
        //
    }
}

全局事件监听器

如果您想对应用程序中的所有导出执行相同的操作,还可以全局配置事件侦听器。您可以将它们添加到例如您的方法AppServiceProvider中register()。

Writer::listen(BeforeExport::class, function () {
    //
});

Writer::listen(BeforeWriting::class, function () {
    //
});

Sheet::listen(BeforeSheet::class, function () {
    //
});

Sheet::listen(AfterSheet::class, function () {
    //
});