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年前 自动加精
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 124

有合并单元格么?

4年前 评论
just

导出文件中文标题不显示咋办 :sob:

3年前 评论

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

file

file

file

4年前 评论
123wild (作者) 4年前

file

单独写aftersheet应该不好使。单独写event4.txt 生成不了。要写就成对的写否则不好使。
花了一天的时间 才解决这个问题。应该多看看包的源码。问别人的有时候没什么用。

4年前 评论

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

4年前 评论
GitPush (楼主) 4年前
QJAutumn 4年前
datangkang123 (作者) 4年前
猪猪 4年前
datangkang123 (作者) 4年前
此时此刻 3年前

请问一下大佬 如果是导出数据量很大报内存超限了 有什么好的办法解决吗

3年前 评论
CrazyZard 3年前
CrazyZard 3年前
cccdz (作者) 3年前
w0rdyyp 3年前
w0rdyyp 3年前
cccdz (作者) 3年前

大神 相同列合并怎么解决? :smile:

3年前 评论
xuri

推荐一个功能丰富、兼容性好、高性能的 Excel 文档基础库:github.com/xuri/excelize

3年前 评论
风吹过有夏天的味道 3年前

进程导出报错:

file

3年前 评论

大佬 自动适应单元格宽度不行呢

3年前 评论
slpi1 3年前

file 合并单元格后,“营业收入”下载表格内没有,请问业务代码内return的数据是什么形式,如果我横向纵向合并单元格都有,数据列表要弄成什么样子呢?感谢!

3年前 评论
风吹过有夏天的味道 3年前
lesstrap (作者) 3年前

分块查询 后导出 xlsx,导出的数据都是最后一次导入的数据,有没有什么办法可以顺接上一次的数据导到末尾?

3年前 评论
Leisen 3年前
最後的我們 2年前
w0rdyyp

excel 导入的时候 有公式 不能识别 直接被识别成=SUM(C2:AB2)这种怎么处理 谁遇到过

3年前 评论

这是下载到本地调整样式的部分,下载到服务器指定文件夹下怎么写呢 比如storage_path() 毕竟excel2.0以前的方法都废弃了

3年前 评论
GitPush (楼主) 3年前

请问下, 需要 导出 图片 和 其他 文本 内容 , 但是 导出图片 只能写在 drawings 方法中, 想导出 类似 这样的结果

file

3年前 评论
巴啦啦小仙女 3年前

我想问下,如何生成文件流 返回前台呢?

3年前 评论

在导出的执行导出的是偶报了,Unable to resolve NULL driver for [Maatwebsite\Excel\Transactions\TransactionManager].谁有好的解决方式方法。

3年前 评论

大佬 ,问下laravel8使用这个架子出现

file这种情况怎么办啊,说是超时,但是我设置了那些所谓的php ini里面的超时参数也没用,测试数据不存在大数据量的情况啊,就几条数据,外包单子需求量根本不大,为什么本地调试总是这样的呢,就这一个接口出现这个问题,其他的导出就没有这个问题出现,能不能帮忙看下,红包感谢 :sob:

3年前 评论

关于导出图片问题:远程图片怎么导出?

3年前 评论
巴啦啦小仙女 3年前

请问怎么直接把excel输出到浏览器?

3年前 评论

大佬,请问 怎么大数据导出吗

3年前 评论

请问,使用队列导出怎么同时导出两张表的数据?

3年前 评论
playmaker

导出 pdf 可以吗?有具体文档吗

3年前 评论
巴啦啦小仙女 3年前

laravel6.1 laravel-excel3.1, 尝试了单元格合并无法生效, 不知道哪里的姿势不对=.= php72 xls 格式导出乱码 csv格式合并单元格无法生效 php73 csv格式合并单元格不生效

2年前 评论

这个导入类里面 手动报异常,好像之前插入的数据都会滚回,请问是里面的机制就做了回滚吗?

2年前 评论

@hldh214 你这么设置起作用了不,我的 按照文档写的,没起作用

2年前 评论

$event->sheet->getDelegate()->mergeCells('A1:A2') 有人试过合并行吗?相当诡异的结果 :joy:

2年前 评论

3的版本,怎么读取excel内容?

2年前 评论

单元格预设值怎么搞呢,就是单元格给他几个选项

2年前 评论

可以使用 WithHeadings 设置表头

file

2年前 评论

想问一下如果用了官网提供的query分块导出,然后用map赋值的,怎么在查询的数据导出后再新增一条合计记录有什么好的方法吗

2年前 评论

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

全局事件监听器

如果要对应用程序中的所有导出执行相同的操作,也可以全局配置事件侦听器。您可以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...

4年前 评论

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

$event->sheet->getDelegate()->mergeCells('A1:B1');
4年前 评论
此时此刻 4年前
Carrick__ 2年前

laravel-admin 中怎么使用呢

4年前 评论
GitPush (楼主) 4年前
foobar

谢谢分享

4年前 评论

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

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

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

4年前 评论
猪猪

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

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

设置某列列宽怎么设置呢

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

挺不错的,mark一下

4年前 评论

可以设置单元格备注么

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

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

4年前 评论
GitPush (楼主) 4年前
xiaopi 4年前
wanghan (作者) 4年前
wanghan (作者) 4年前

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

4年前 评论
GitPush (楼主) 4年前
wanle (作者) 4年前
ThinkQ

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

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

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

怎么设置自动换行

4年前 评论

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

4年前 评论
GitPush (楼主) 4年前
yotoai 4年前
会飞的蜗牛 3年前
巴啦啦小仙女 3年前

大量数据导出内存溢出(10万条左右),也是用了队列,有好的解决方案吗

3年前 评论

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

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

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

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

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

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

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

4年前 评论
GitPush (楼主) 4年前
renweimian (作者) 4年前
GitPush (楼主) 4年前
巴啦啦小仙女 3年前

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

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

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

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

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

4年前 评论
GitPush (楼主) 4年前
会飞的蜗牛 3年前

设置作者应该是 $event->writer->getProperties()->setCreator('Addnewer');
事件应该是 beforeExport

4年前 评论

使用这个包导出数据,数据量大一些就会导致内存溢出,请问一下 lz 知道怎么解决吗?

4年前 评论
风吹过有夏天的味道 3年前
jasonjiang123

我按照流程使用,lumen5.5, 3.1的excel ,在使用导出中抱着个错误 "Class filesystem does not exist"

4年前 评论
jiangxiulong 3年前

感谢大佬, 刚好有需求需要做导出表格

4年前 评论

大佬,csv格式文件能导出多sheet吗,我尝试导出,只能有一个sheet

4年前 评论

如何把 两个不一样的数组的数据 左右呈现

3年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!