环境(Environment)
- Ubuntu 18.04
-
PHP 7.2.17
-
Laravel 5.8
-
Maatwebsite/Excel 3.1
安装(Installation)
要求:
- php 7.0 及以上
-
laravle 5.5 及以上
-
开启
php-zip
,php-xml
,php-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
:
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' ]
]);
return $collection;
}
}
导出带下拉列表的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 ( AfterSheet $event ) 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 (\Exception $e) {
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 (\Exception $e) {
return [
'code' => 500,
'data' => [
'err' => 'import_failed',
'err_msg' => $e -> getMessage()
],
'msg' => '导入失败'
];
}
foreach ( $data as $row ) {
// do something for every row
}
}
}
写在最后
以上大概就是Maatwebsite/Excel
的一些常用用法,如果文章有问题请指出。
最後までご覧いただいてありがとうございます