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

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

导入功能请期待下篇。

本作品采用《CC 协议》,转载必须注明作者和本文链接
本帖由系统于 4个月前 自动加精
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
讨论数量: 25

有合并单元格么?

5个月前 评论

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

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

laravel-admin 中怎么使用呢

4个月前 评论
GitPush (楼主) 4个月前
phperShine

谢谢分享

4个月前 评论

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

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

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

4个月前 评论

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

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

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

3个月前 评论
datangkang123 (作者) 3个月前
猪猪 3个月前
GitPush (楼主) 3个月前
datangkang123 (作者) 3个月前
QJAutumn 3周前

设置某列列宽怎么设置呢

3个月前 评论
风吹过有夏天的味道 (作者) 3个月前
GitPush (楼主) 3个月前
犯二青年

挺不错的,mark一下

3个月前 评论

可以设置单元格备注么

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

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

3个月前 评论
GitPush (楼主) 3个月前
xiaopi 3个月前
wanghan (作者) 3个月前
wanghan (作者) 3个月前

请问,怎么修改工作表sheet的名称

2个月前 评论
GitPush (楼主) 2个月前
wanle (作者) 2个月前
ThinkCsly

导入时候,如果存在 怎么跳过呢?

导入是批量导入excel的 ,这个时候怎么检查呢?

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

怎么设置自动换行

2个月前 评论

你好,图片导出只能导出本地的图片么,图片存放在阿里云.只有一个地址,如何导出来呢

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

感谢分享,我也正好在做这块。

全局事件监听器

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

Writer::listen(BeforeExport::class, function () {
//
});
Writer::listen(BeforeWriting::class, function () {
//
});
Sheet::listen(BeforeSheet::class, function () {
//
});
Sheet::listen(AfterSheet::class, function () {
//
});

原文地址: https://docs.laravel-excel.com/3.1/exports...

2个月前 评论

导出.csv格式时,registerEvents事件里设置的合并单元格等设置失效怎么解决

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

怎么把导出的文件直接保存在服务器上指定的路径下?

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

请问这个拓展包支持用Excel文件模板导出吗?我这有设计好的模板 ,但是用这个不知道 怎么往里填数据啊?

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

老哥为啥我导出的没有数据??? 但是return 有数据 导出来就控白

file

file

file

1个月前 评论
123wild (作者) 1个月前

请问单元格里面加链接,如何加?

1个月前 评论
GitPush (楼主) 1个月前
renweimian (作者) 1个月前
GitPush (楼主) 4周前

请问一下大神,如何设置excel整个表的字体大小呢,默认好像是11,太小了~

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

请问下,如果图片存储在 oss ,怎么导出?

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

请问一开始我按照楼主的那样做了,导出调用时报Class 'App\Exports\Collection' not found该怎么破?

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

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