maatwebsite/Excel 3.1 使用教程 (导出篇)

官方文档

https://docs.laravel-excel.com/3.1/getting...

GIT 地址

https://github.com/maatwebsite/Laravel-Exc...

作为一个和 laravel 契合度很高的 excel 工具包,大家应该都是用过这个工具。特别是 2.x 版本几乎是用laravel框架都接触过,3.x 基本上全部重构,全网几乎找不到比较完善的教程,我就先抛砖引玉,大概把我用到的功能使用方式列一下,欢迎大家补充。

环境要求

PHP: ^7.0
Laravel: ^5.5

安装方式
composer require maatwebsite/excel

因为目前 3.1 只支持 Laravel 5.5 以上,所以会自动注册。

excel 导出

新建导出文件,导入导出业务代码尽量不要和原来业务耦合。我们拿官网 user 模块举例

php artisan make:export UsersExport --model=User

会在 app 目录下创建 Exports 目录

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

UsersExport.php 代码内容

<?php

namespace App\Exports;

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

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

业务控制器中调用

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');
    }
}

很方便简单是不是。这样可以把 user 表中所有内容都导入 excel 。很显然你的业务不会如此简单,那就继续。

Laravel Excel 支持查询语句导出、数组导出、视图表格导出,这些可以具体查看文档。

我们通常情况下需要组装业务数据,集合导出可以作为通用的导出方案。

<?php

namespace App\Exports;

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

class UsersExport implements FromCollection
{
    protected $data;

    //构造函数传值
    public function __construct($data)
    {
        $this->data = $data;
    }
    //数组转集合
    public function collection()
    {
        return new Collection($this->createData());
    }
    //业务代码
    public function createData()
    {
      //todo 业务
    }
}

createData 方法返回的数据格式如下

return [
            ['编号', '姓名', '年龄']
            [1, '小明', '18岁'],
            [4, '小红', '17岁']
       ];

需要注意的是,这里组装了 excel 的表头,这也是比较方便的地方。
如此,简单的业务导出就完成了,应该可以满足80%需求,接下来我们继续,比如单元格格式化、自动适应、设置宽高、导出图片、多 sheet 表等功能。

单元格格式化

有时候我们需要对单元格处理文本、数字、日期、金额等格式。

<?php

namespace App\Exports;

use App\User;
use Maatwebsite\Excel\Concerns\FromCollection;
//新增两个 use
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
use Maatwebsite\Excel\Concerns\WithColumnFormatting;

//新增 WithColumnFormatting
class UsersExport implements FromCollection, WithColumnFormatting
{
    public function collection()
    {
        return User::all();
    }
}

 /**
   * @return array
   */
public function columnFormats(): array
{
    return [
        'B' => NumberFormat::FORMAT_DATE_DDMMYYYY, //日期
        'C' => NumberFormat::FORMAT_NUMBER_00, //金额保留两位小数
    ];
}

自动适应单元格宽

<?php

namespace App\Exports;

use App\User;
use Maatwebsite\Excel\Concerns\FromCollection;
//新增
use Maatwebsite\Excel\Concerns\ShouldAutoSize;

//新增 ShouldAutoSize
class UsersExport implements FromCollection, ShouldAutoSize
{
    public function collection()
    {
        return User::all();
    }
}

导出多 sheet

多表导出需要做两步操作,第一组装 sheet,第二生成对应的 sheet 表

<?php

namespace App\Exports;

use App\User;
//新增
use Maatwebsite\Excel\Concerns\Exportable;
use Maatwebsite\Excel\Concerns\WithMultipleSheets;

//新增 WithMultipleSheets
class UsersExport implements WithMultipleSheets
{
    use Exportable;

    protected $year;

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

    /**
     * @return array
     */
    public function sheets(): array
    {
        $sheets = [];

        for ($month = 1; $month <= 12; $month++) {
            //不同的数据可以调用不同的方法
            $sheets[] = new UserPerMonthSheet($this->year, $month);
        }

        return $sheets;
    }
}

然后新建 UserPerMonthSheet 类

namespace App\Exports;

use Maatwebsite\Excel\Concerns\FromQuery;
use Maatwebsite\Excel\Concerns\WithTitle;

class UserPerMonthSheet implements FromQuery, WithTitle
{
    private $month;
    private $year;

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

    /**
     * @return Builder
     */
    public function query()
    {
        return User
            ::query()
            ->whereYear('created_at', $this->year)
            ->whereMonth('created_at', $this->month);
    }

    /**
     * sheet 表名称
     * @return string
     */
    public function title(): string
    {
        return 'Month ' . $this->month;
    }
}

设置单元格高度以及垂直居中,字体颜色、背景色等

这里需要用到 Laravel Excel 的事件模块

提供多种事件 BeforeExport、BeforeWriting、BeforeSheet,AfterSheet等等,也就是导出功能的生命周期,具体查看文档即可。修改单元格高度我们这里使用 AfterSheet

namespace App\Exports;

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

class UserExport implements WithEvents
{
    /**
     * 注册事件
     * @return array
     */
    public function registerEvents(): array
    {
        return [
            AfterSheet::class  => function(AfterSheet $event) {
                //设置作者
                $event->writer->setCreator('Patrick');
                //设置列宽
                $event->sheet->getDelegate()->getColumnDimension('A')->setWidth(50);
                //设置行高,$i为数据行数
                for ($i = 0; $i<=1265; $i++) {
                    $event->sheet->getDelegate()->getRowDimension($i)->setRowHeight(50);
                }
                //设置区域单元格垂直居中
                $event->sheet->getDelegate()->getStyle('A1:K1265')->getAlignment()->setVertical('center');
                //设置区域单元格字体、颜色、背景等,其他设置请查看 applyFromArray 方法,提供了注释
                $event->sheet->getDelegate()->getStyle('A1:K6')->applyFromArray([
                    'font' => [
                        'name' => 'Arial',
                        'bold' => true,
                        'italic' => false,
                        'strikethrough' => false,
                        'color' => [
                            'rgb' => '808080'
                        ]
                    ],
                    'fill' => [
                        'fillType' => 'linear', //线性填充,类似渐变
                        'rotation' => 45, //渐变角度
                        'startColor' => [
                            'rgb' => '000000' //初始颜色
                        ],
                        //结束颜色,如果需要单一背景色,请和初始颜色保持一致
                        'endColor' => [
                            'argb' => 'FFFFFF'
                        ]
                    ]
                ]);
                //合并单元格
                $event->sheet->getDelegate()->mergeCells('A1:B1');
            }
        ];
    }
}

我没找到能全局处理的方式,如果你们知道请告诉我,万分感谢。

导出图片

<?php

namespace App\Exports;

//新增
use Maatwebsite\Excel\Concerns\WithDrawings;
use PhpOffice\PhpSpreadsheet\Worksheet\Drawing;

class UserExport implements WithDrawings
{
    public function drawings()
    {
        $drawing = new Drawing();
        $drawing->setName('Logo');
        $drawing->setDescription('This is my logo');
        $drawing->setPath(public_path('/img/logo.jpg'));
        $drawing->setHeight(50);
        $drawing->setCoordinates('B3');

        $drawing2 = new Drawing();
        $drawing2->setName('Other image');
        $drawing2->setDescription('This is a second image');
        $drawing2->setPath(public_path('/img/other.jpg'));
        $drawing2->setHeight(120);
        $drawing2->setCoordinates('G2');

        return [$drawing, $drawing2];
    }
}

这是官方的例子,实际使用中我们不可能手写这么多方法块,我改写一下

public function drawings()
{
    //这里的数据自己组装
    $draw_arr = [1 =>'detail1.jpg', 2 => 'detail2.jpg'];
    $result = [];
    foreach ($draw_arr as $k => $v) {
      ${'drawing'.$k} = new Drawing();
      ${'drawing'.$k}->setName('Other image');
      ${'drawing'.$k}->setDescription('This is a second image');
      //图片路径
      ${'drawing'.$k}->setPath(public_path($v));
      ${'drawing'.$k}->setHeight(50);
      //设置图片列
      ${'drawing'.$k}->setCoordinates('U'.$k);
      $result[] = ${'drawing'.$k};
    }
    return $result;
}

还有其他大家需要的功能可以补充在评论中,我会添加进来。

导入功能请期待下篇。

本帖由系统于 1个月前 自动加精
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
讨论数量: 12

有合并单元格么?

1个月前 评论

@风吹过有夏天的味道 我已添加

$event->sheet->getDelegate()->mergeCells('A1:B1');
1个月前 评论

laravel-admin 中怎么使用呢

1个月前 评论
GitPush (楼主) 1个月前

一个订单中有多个商品,映射为一行 应该用什么,FromView,还是?

4周前 评论
GitPush (楼主) 4周前

不错 我选spreedsheet 毕竟花里胡哨 这个自动对齐不敢恭维

4周前 评论

drawings() 方法具体怎么在我的导出excel表里面调用呢

3周前 评论
GitPush (楼主) 2周前

导出长数字,防止变科学计数法,怎么设置呢

4天前 评论
datangkang123 (作者) 4天前
猪猪 4天前
GitPush (楼主) 4天前
datangkang123 (作者) 12小时前

设置某列列宽怎么设置呢

3天前 评论
GitPush (楼主) 3天前
风吹过有夏天的味道 (作者) 3天前

挺不错的,mark一下

3天前 评论

可以设置单元格备注么

3天前 评论
GitPush (楼主) 2天前
风吹过有夏天的味道 (作者) 2天前
wanghan

导出的时候,如果mysql中数据是0,excel中就变成空了

3天前 评论
GitPush (楼主) 2天前
xiaopi 2天前
wanghan (作者) 2天前
wanghan (作者) 2天前

请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!