Maatwebsite / Laravel-Excel 扩展包导入导出数据

文档 https://laravel-excel.maatwebsite.nl/3.1/getting-started/

github https://github.com/Maatwebsite/Laravel-Excel

环境要求

  • PHP: ^7.0
  • Laravel: ^5.5
  • PhpSpreadsheet: ^1.4
  • PHP扩展已php_zip启用
  • PHP扩展已php_xml启用
  • PHP扩展已php_gd2启用

安装

composer require maatwebsite/excel

laravel5.5已下版本手动添加ServiceProvider config/app.php

'providers' => [
    /*
     * Package Service Providers...
     */
    Maatwebsite\Excel\ExcelServiceProvider::class,
]

添加Facade config/app.php

'aliases' => [
    ...
    'Excel' => Maatwebsite\Excel\Facades\Excel::class,
]

发布配置

php artisan vendor:publish --provider="Maatwebsite\Excel\ExcelServiceProvider" --tag=config
或者
php artisan vendor:publish 然后手动选择

生成config/excel.php配置文件

导出

创建导出类

php artisan make:export UsersExport --model=App/User

导出格式

https://laravel-excel.maatwebsite.nl/3.1/exports/export-formats.html

导出方式

1.直接响应下载文件

use App\Exports\UsersExport;
use Maatwebsite\Excel\Facades\Excel;
use App\Http\Controllers\Controller;

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

2.存储到磁盘

public function storeExcel() 
{
    // Store on default disk
    Excel::store(new InvoicesExport(2018), 'invoices.xlsx');
    
    // Store on a different disk (e.g. s3)
    Excel::store(new InvoicesExport(2018), 'invoices.xlsx', 's3');
    
    // Store on a different disk with a defined writer type. 
    Excel::store(new InvoicesExport(2018), 'invoices.xlsx', 's3', Excel::XLSX);
}
  • 参数1为导出类
  • 参数2为文件名
  • 参数3为laravel存储的磁盘
  • 参数4为导出格式 详情看配置文件

从集合导出

<?php

namespace App\Exports;

use App\User;
use Maatwebsite\Excel\Concerns\FromCollection;

class UsersExport implements FromCollection
{
    public function collection()
    {
        return User::all();
    }
}
  • 实现 FromCollection 接口 的collection方法
  • collection方法内可以是任何Eloquent ORM的查询 get() first() all() pluck()等方法的返回结果(collection)也可以是通过构造方法传入的collection

从查询导出

namespace App\Exports;

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

class InvoicesExport implements FromQuery
{
    use Exportable;

    public function query()
    {
        return Invoice::query();
    }
}
  • 实现Maatwebsite\Excel\Concerns\FromQuery 的 query方法
  • query 方法内return任何Laravel Eloquent ORM的查询构造器的方法,除了获取集合的get() first() all() pluck()等方法

从视图导出

将html表格转换成excel表格,不推荐使用,不灵活,此功能对html结构有要求

队列导出

支持 FromCollection 和 FromQuery

namespace App\Exports;

use App\User;
use Maatwebsite\Excel\Concerns\FromCollection;
use Illuminate\Contracts\Queue\ShouldQueue;

class UsersExport implements FromCollection, ShouldQueue
{
    /**
     * @return \Illuminate\Support\Collection
     */
    public function collection()
    {
        return User::all();
    }
}

队列直接下载导出 控制器代码

 public function export(Request $request, Excel $excel)
 {
    return $excel->download(new UsersExport(), 'users.xlsx');
 }

队列导出存储到磁盘

public function store(Request $request)
{
   ini_set('memory_limit', '1024M');
   $result = Excel::store(new UsersExport(), 'users_store'.date('YmdHis').'.xlsx', 'public');
}
  • 数据量大时,有时会超出内存限制需要设置内存,后来没复现,没找到原因
  • 从 collection导出的方式,成功后没有发现导出excel文件,后来没复现,没有找到原因

设置表头

class InvoicesExport implements WithHeadings
{   
    public function headings(): array
    {
        return [
            '对应ExcelA列',
            '对应ExcelB列',
            ...
        ];
    }
}

要实现Maatwebsite\Excel\Concerns\WithHeadings的headings方法

每行字段值映射

public function map($code): array
{
    return [
       $A,
       (string) $B,
       0 == $C ? '未使用' : '使用',
    ];
}

要实现 Maatwebsite\Excel\Concerns\WithMapping的map方法

可以对具体值做处理

字段格式化

https://docs.laravel-excel.com/3.1/exports/column-formatting.html

namespace App\Exports;

use PhpOffice\PhpSpreadsheet\Shared\Date;//处理时间格式的类,
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;//处理数字格式
use Maatwebsite\Excel\Concerns\WithColumnFormatting;
use Maatwebsite\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(): array
    {
        return [
            'B' => NumberFormat::FORMAT_DATE_DDMMYYYY, 
            'C' => NumberFormat::FORMAT_CURRENCY_EUR_SIMPLE,
             //I为列头标识格式化成文本常用的比如手机号或订单号会转为科学计数法,这样可以解决
            'I' => NumberFormat::FORMAT_TEXT,
        ];
    }
}

处理日期时,建议在映射中PhpOffice\PhpSpreadsheet\Shared\Date 使用以确保正确解析日期。

设置列宽度

自动设置尺寸

namespace App\Exports;

use Maatwebsite\Excel\Concerns\ShouldAutoSize;

class InvoicesExport implements ShouldAutoSize
{
    ...
}

自定义宽度

namespace App\Exports;

use Maatwebsite\Excel\Concerns\WithColumnWidths;

class InvoicesExport implements WithColumnWidths
{
    public function columnWidths(): array
    {
        //A B 是列的标识头
        return [
            'A' => 55,
            'B' => 45,            
        ];
    }
}

常用配置修改

 /*
  |--------------------------------------------------------------------------
    Heading Row Formatter
  |--------------------------------------------------------------------------
  |
  | Configure the heading row formatter. 
  | Available options: none|slug|custom
  |
  */
  'heading_row' => [
      'formatter' => 'none',//不格式化,这样可以导入中文标题头excel
  ],

   /*
    |--------------------------------------------------------------------------
    | Transaction Handler
    |--------------------------------------------------------------------------
    |
    | By default the import is wrapped in a transaction. This is useful
    | for when an import may fail and you want to retry it. With the
    | transactions, the previous import gets rolled-back.
    |
    | You can disable the transaction handler by setting this to null.
    | Or you can choose a custom made transaction handler here.
    |
    | Supported handlers: null|db
    |
    */
    'transactions' => [
        'handler' => 'null', //取消事物,不回滚,成功导入的数据不会被回滚
    ],