官方文档

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

GIT 地址

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

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

环境要求

PHP: ^7.0
Laravel: ^5.5

安装方式
  1. composer require maatwebsite/excel

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

excel 导出

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

  1. php artisan make:export UsersExport --model=User

会在 app 目录下创建 Exports 目录

  1. .
  2. ├── app
  3. ├── Exports
  4. ├── UsersExport.php
  5. └── composer.json

UsersExport.php 代码内容

  1. <?php
  2. namespace App\Exports;
  3. use App\User;
  4. use Maatwebsite\Excel\Concerns\FromCollection;
  5. class UsersExport implements FromCollection
  6. {
  7. public function collection()
  8. {
  9. return User::all();
  10. }
  11. }

业务控制器中调用

  1. use App\Exports\UsersExport;
  2. use Maatwebsite\Excel\Facades\Excel;
  3. use App\Http\Controllers\Controller;
  4. class UsersController extends Controller
  5. {
  6. public function export()
  7. {
  8. return Excel::download(new UsersExport, 'users.xlsx');
  9. }
  10. }

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

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

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

  1. <?php
  2. namespace App\Exports;
  3. use App\User;
  4. use Maatwebsite\Excel\Concerns\FromCollection;
  5. class UsersExport implements FromCollection
  6. {
  7. protected $data;
  8. //构造函数传值
  9. public function __construct($data)
  10. {
  11. $this->data = $data;
  12. }
  13. //数组转集合
  14. public function collection()
  15. {
  16. return new Collection($this->createData());
  17. }
  18. //业务代码
  19. public function createData()
  20. {
  21. //todo 业务
  22. }
  23. }

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

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

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

单元格格式化

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

  1. <?php
  2. namespace App\Exports;
  3. use App\User;
  4. use Maatwebsite\Excel\Concerns\FromCollection;
  5. //新增两个 use
  6. use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
  7. use Maatwebsite\Excel\Concerns\WithColumnFormatting;
  8. //新增 WithColumnFormatting
  9. class UsersExport implements FromCollection, WithColumnFormatting
  10. {
  11. public function collection()
  12. {
  13. return User::all();
  14. }
  15. }
  16. /**
  17. * @return array
  18. */
  19. public function columnFormats(): array
  20. {
  21. return [
  22. 'B' => NumberFormat::FORMAT_DATE_DDMMYYYY, //日期
  23. 'C' => NumberFormat::FORMAT_NUMBER_00, //金额保留两位小数
  24. ];
  25. }

自动适应单元格宽

  1. <?php
  2. namespace App\Exports;
  3. use App\User;
  4. use Maatwebsite\Excel\Concerns\FromCollection;
  5. //新增
  6. use Maatwebsite\Excel\Concerns\ShouldAutoSize;
  7. //新增 ShouldAutoSize
  8. class UsersExport implements FromCollection, ShouldAutoSize
  9. {
  10. public function collection()
  11. {
  12. return User::all();
  13. }
  14. }

导出多 sheet

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

  1. <?php
  2. namespace App\Exports;
  3. use App\User;
  4. //新增
  5. use Maatwebsite\Excel\Concerns\Exportable;
  6. use Maatwebsite\Excel\Concerns\WithMultipleSheets;
  7. //新增 WithMultipleSheets
  8. class UsersExport implements WithMultipleSheets
  9. {
  10. use Exportable;
  11. protected $year;
  12. public function __construct(int $year)
  13. {
  14. $this->year = $year;
  15. }
  16. /**
  17. * @return array
  18. */
  19. public function sheets(): array
  20. {
  21. $sheets = [];
  22. for ($month = 1; $month <= 12; $month++) {
  23. //不同的数据可以调用不同的方法
  24. $sheets[] = new UserPerMonthSheet($this->year, $month);
  25. }
  26. return $sheets;
  27. }
  28. }

然后新建 UserPerMonthSheet 类

  1. namespace App\Exports;
  2. use Maatwebsite\Excel\Concerns\FromQuery;
  3. use Maatwebsite\Excel\Concerns\WithTitle;
  4. class UserPerMonthSheet implements FromQuery, WithTitle
  5. {
  6. private $month;
  7. private $year;
  8. public function __construct(int $year, int $month)
  9. {
  10. $this->month = $month;
  11. $this->year = $year;
  12. }
  13. /**
  14. * @return Builder
  15. */
  16. public function query()
  17. {
  18. return User
  19. ::query()
  20. ->whereYear('created_at', $this->year)
  21. ->whereMonth('created_at', $this->month);
  22. }
  23. /**
  24. * sheet 表名称
  25. * @return string
  26. */
  27. public function title(): string
  28. {
  29. return 'Month ' . $this->month;
  30. }
  31. }

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

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

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

  1. namespace App\Exports;
  2. use Maatwebsite\Excel\Concerns\WithEvents;
  3. use Maatwebsite\Excel\Events\BeforeExport;
  4. use Maatwebsite\Excel\Events\BeforeWriting;
  5. use Maatwebsite\Excel\Events\BeforeSheet;
  6. class UserExport implements WithEvents
  7. {
  8. /**
  9. * 注册事件
  10. * @return array
  11. */
  12. public function registerEvents(): array
  13. {
  14. return [
  15. AfterSheet::class => function(AfterSheet $event) {
  16. //设置作者
  17. $event->writer->setCreator('Patrick');
  18. //设置列宽
  19. $event->sheet->getDelegate()->getColumnDimension('A')->setWidth(50);
  20. //设置行高,$i为数据行数
  21. for ($i = 0; $i<=1265; $i++) {
  22. $event->sheet->getDelegate()->getRowDimension($i)->setRowHeight(50);
  23. }
  24. //设置区域单元格垂直居中
  25. $event->sheet->getDelegate()->getStyle('A1:K1265')->getAlignment()->setVertical('center');
  26. //设置区域单元格字体、颜色、背景等,其他设置请查看 applyFromArray 方法,提供了注释
  27. $event->sheet->getDelegate()->getStyle('A1:K6')->applyFromArray([
  28. 'font' => [
  29. 'name' => 'Arial',
  30. 'bold' => true,
  31. 'italic' => false,
  32. 'strikethrough' => false,
  33. 'color' => [
  34. 'rgb' => '808080'
  35. ]
  36. ],
  37. 'fill' => [
  38. 'fillType' => 'linear', //线性填充,类似渐变
  39. 'rotation' => 45, //渐变角度
  40. 'startColor' => [
  41. 'rgb' => '000000' //初始颜色
  42. ],
  43. //结束颜色,如果需要单一背景色,请和初始颜色保持一致
  44. 'endColor' => [
  45. 'argb' => 'FFFFFF'
  46. ]
  47. ]
  48. ]);
  49. //合并单元格
  50. $event->sheet->getDelegate()->mergeCells('A1:B1');
  51. }
  52. ];
  53. }
  54. }

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

导出图片

  1. <?php
  2. namespace App\Exports;
  3. //新增
  4. use Maatwebsite\Excel\Concerns\WithDrawings;
  5. use PhpOffice\PhpSpreadsheet\Worksheet\Drawing;
  6. class UserExport implements WithDrawings
  7. {
  8. public function drawings()
  9. {
  10. $drawing = new Drawing();
  11. $drawing->setName('Logo');
  12. $drawing->setDescription('This is my logo');
  13. $drawing->setPath(public_path('/img/logo.jpg'));
  14. $drawing->setHeight(50);
  15. $drawing->setCoordinates('B3');
  16. $drawing2 = new Drawing();
  17. $drawing2->setName('Other image');
  18. $drawing2->setDescription('This is a second image');
  19. $drawing2->setPath(public_path('/img/other.jpg'));
  20. $drawing2->setHeight(120);
  21. $drawing2->setCoordinates('G2');
  22. return [$drawing, $drawing2];
  23. }
  24. }

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

  1. public function drawings()
  2. {
  3. //这里的数据自己组装
  4. $draw_arr = [1 =>'detail1.jpg', 2 => 'detail2.jpg'];
  5. $result = [];
  6. foreach ($draw_arr as $k => $v) {
  7. ${'drawing'.$k} = new Drawing();
  8. ${'drawing'.$k}->setName('Other image');
  9. ${'drawing'.$k}->setDescription('This is a second image');
  10. //图片路径
  11. ${'drawing'.$k}->setPath(public_path($v));
  12. ${'drawing'.$k}->setHeight(50);
  13. //设置图片列
  14. ${'drawing'.$k}->setCoordinates('U'.$k);
  15. $result[] = ${'drawing'.$k};
  16. }
  17. return $result;
  18. }

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

导入功能请期待下篇。