Laravel Maatwebsite/Excel 教程

环境(Environment)

  • Ubuntu 18.04

  • PHP 7.2.17

  • Laravel 5.8

  • Maatwebsite/Excel 3.1


安装(Installation)

要求:

  • php 7.0 及以上

  • laravle 5.5 及以上

  • 开启 php-zipphp-xmlphp-gd2 模块

Composer 安装

composer require maatwebsite/excel

创建导出类和控制器类

使用php artisan make:export DemoExport可以直接创建出导出类,但是这里为了方便理解先手动创建。

创建 app/Exports/DemoExport.php

<?php

namespace App\Exports;

class DemoExport
{
    //
}

创建 app/Http/Controllers/FileController.php

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;

class FileController extends Controller
{
    public function export()
    {
        //
    }
}

使用数组格式的数据导出

最终Excel表内容:

  id     name  
1 Athena
2 Venus

DemoExport.php

<?php

namespace App\Exports;

use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\FromCollection;

class DemoExport implements WithHeadings, FromArray
{
    // 设置表头
    public function headings() : array
    {
        return [ 'id', 'name' ];
    }

    //注意返回的二维数组,数组中的每一个数组代表一行
    public function array() : array
    {
        return [
            [ '1', 'Athena' ],
            [ '2', 'Venus' ]
        ];
    }
}

FileController.php

<?php

namespace App\Http\Controllers

use App\Http\Controllers\Controller;
use App\Exports\DemoExport;

class FileController extends Controller
{
    public function export()
    {
        try {
            return Excel::download(new DemoExport, 'demo.xlsx');
        }
        catch (\Exception e) {
            return [
                'code' => 500,
                'data' => [
                    'err' => 'export_failed',
                    'err_msg' =>e -> getMessage()
                ],
                'msg' => '导出失败'
            ];
        }
    }
}

使用collection格式的数据导出

最终Excel表内容:

  id     name  
1 Athena
2 Venus

DemoExport.php

<?php

namespace App\Exports;

use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\FromCollection;

class DemoExport implements WithHeadings, FromCollection
{
    // 设置表头
    public function headings() : array
    {
        return [ 'id', 'name' ];
    }

    public function collection() 
    {
        // 这里使用 collect 方法生成 collection,通常模型取出的数据即为 collection 格式
        collection = collection([
            [ '1', 'Athena' ],
            [ '2', 'Venus' ]
        ]);
        returncollection;
    }
}

导出带下拉列表的Excel

当我们有这样的一个需求,需要导出一张Excel表作为模板,供用户填充数据,然后用户再上传导入数据库中。而这个时候,可能有一些列我们希望用户只能输入某些值,像下面的这个Excel表:

   id       name          type
1 IphoneXs     cellphone  
2 MacBook     latop  

我们希望用户在type列只能输入cellphone或者latop,再或者是从数据库中所能获取到的值,那这个时候我们该怎么做呢?这里实现的思路的是使用Excel里的下拉列表。代码的实现方法如下:

<?php

namespace App\Exports;

use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithEvents;
use Maatwebsite\Excel\Concerns\AfterSheet;
use PhpOffice\PhpSpreadsheet\Cell\DataValidation;

class DemoExport implements WithHeadings, FromArray, WithEvents
{
    public function headings(): array
    {
        return [ 'id', 'name', 'type' ];
    }

    public function Array(): array
    {
        return collect[
            [ 1, 'IphoneXs', 'cellphone' ],
            [ 2, 'MacBook', 'latop' ]
        ];
    }

    // 重点在这里
    public function registerEvents() : array
    {
        typeList           = [ 'cellphone', 'latop' ];

        // 因为要设置的参数格式要求是以逗号分隔的多个项,所以要转换为字符串typeListStr    = implode( ',', typeList );

        return [
            AfterSheet::Class => function ( AfterSheetevent ) use (typeListStr) {
                // 循环里边的所有语句都是针对一个格子的设置,这里对该列的前500个格子定义
                for (i = 0; i<500;i ++) {
                    validation =event -> sheet
                        -> getDelegate()
                        -> getCell('C' . i)
                        -> getDataValidation();validation -> setType( DataValidation::TYPE_LIST );
                    validation -> setErrorStyle( DataValidation::STYLE_WARING );validation -> setAllowBlank(false);
                    validation -> setShowInputMessage(true);validation -> setShowErrorMessage(true);
                    validation -> setErrorTitle('输入的值不合法');validation -> setError('选择的值不在列表中,请选择列表中的值');
                    validation -> setPromptTitle('从列表中选择');validation -> setPrompt('请选择下拉列表中的值');
                    validation -> setFormula1('"' .typeListStr . '"');
                }
            }
        ];
    }
}

如果对列需要有一些其他样式设置或定义,参考:《Phpspreadsheet Documentation》


导出数据库中的数据

使用collection导出的实例

数据表 gods :

  id     name  
1 Zeus
2 Hades
3 Poseidon

  • DemoExport.php:
<?php

namespace App\Exports;

use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\FromCollection;
use App\Models\God;
use Maatwebsite\Excel\Concerns\Exportable;

class DemoExport implements withHeadings, FromCollection
{
    public function headings() : array
    {
        return ['id', 'name',];
    }

    public function collection()
    {
        // 可以使用任何 Laravel 的 Model 查询语句,注意返回的结果需要是 Collection 类型的
        return God::select('id', 'name') -> get();
    }
}

从上传的文件导入

一般的需求是用户上传一个Excel表,然后后台读取Excel表的内容导入数据库中。

我这里只演示读取Excel表到数组中。

创建app/Exports/DemoImport.php文件,内容很简单,如下所示:

<?php

namespace App\Exports;

use Maatwebsite\Excel\Concerns\Importable

class DemoImport
{
    use Importable;
}

控制器FileController.php文件内容:

<?php

namespace App\Http\Controllers

use App\Http\Controllers\Controller;
use App\Exports\DemoImport;
use Illuminate\Http\Request;

class FileController extends Controller
{
    public function Import( Request request )
    {
        /**
        * 可以将 toArray 方法改为 toCollection() 来得到 Collection 格式的数据
        * 参数 file 为表单文件字段的name
        */
        try {data = (new DemoImport) -> toArray(request -> file('file'))[0];
        }
        catch (\Exceptione) {
            return [
                'code' => 500, 
                'data' => [
                    'err' => 'import_failed',
                    'err_msg' => e -> getMessage()
                ],
                'msg' => '导入失败'
            ];
        }

        foreach (data as $row ) {
            // 第一行是表头,第二行开始是数据
            // ...
        }
    }
}

从已存在的文件中导入

当你想读取已保存的Excel表格的时候,只需要对上面的方法做很小的改动

首先DemoImport.php内容同上面的导入一样

控制器FileController.php文件内容:

<?php

namespace App\Http\Controllers

use App\Http\Controllers\Controller;
use App\Exports\DemoImport;

class FileController extends Controller
{
    public function Import()
    {
        // 文件路径根据实际情况修改
        try {
            data = (new DemoImport) -> toArray('storage/demo.xlsx')[0];
        }
        catch (\Exceptione) {
            return [
                'code' => 500, 
                'data' => [
                    'err' => 'import_failed',
                    'err_msg' => e -> getMessage()
                ],
                'msg' => '导入失败'
            ];
        }

        foreach (data as $row ) {
            // do something for every row
        }
    }
}

写在最后

以上大概就是Maatwebsite/Excel的一些常用用法,如果文章有问题请指出。

最後までご覧いただいてありがとうございます

点赞

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注