laravel:7.6 excel:3.1 本文章只涉及部分操作,更多操作请参考Excel官方文档
安装要求:
安装Excel3.1类库
composer require maatwebsite/excel
或者指定3.1版本
composer require maatwebsite/excel ~3.1.0
1. 创建导入
php artisan make:import CustomerImport --model=Customer
执行后会在App下自动创建Import文件夹并自动生成一个导入文件
2. 导入文件代码:
<?php
namespace App\Imports;
use App\Model\Customer;
use App\Model\Position;
use Maatwebsite\Excel\Concerns\ToArray;
use Maatwebsite\Excel\Concerns\WithBatchInserts;
use Maatwebsite\Excel\Concerns\WithChunkReading;
//use Maatwebsite\Excel\Concerns\WithHeadingRow;
class CustomersImport implements ToArray,WithBatchInserts,WithChunkReading
{
/**
* 写入数据表
*
* @param array $array
*/
public function array(array $array)
{
# 处理表格数据
for ( $i = 1; $i <= count( $array ) -1; $i++ ) {
if( !isset( $array[$i] ) ) {
continue;
}
$data[$i-1]['***'] = $array[$i][0];
$data[$i-1]['***'] = $array[$i][4];
$data[$i-1]['***'] = $array[$i][5];
$data[$i-1]['***'] = $array[$i][6];
# 数据中有'#'符号需要进行转化否则写入数据时会报错
$data[$i-1]['***'] = str_replace( '#' , '-' , $array[$i][2] );
}
# 将表格数据放入集合并转为对象类型
$data = collect( $data );
# 指定下标去重
$data = $data->unique( '****' );
$data = json_decode( json_encode( $data ) , 256 );
# 重置数组下标
$data = array_values( $data );
$customer_data = Customer::getAllCustomer();
$customer_data = json_decode( json_encode( $customer_data ) , 256 );
# 数据再次去重
for ( $j = 0; $j <= count( $customer_data ) -1; $j++ ) {
foreach ( $data as $k => $v ) {
if( $data[$k]['***'] == $customer_data[$j]['***'] ) {
unset( $data[$k] );
}
}
}
# 批量插入数据
$res = Customer::insertCustomerData( $data );
return $res;
}
/**
* 写入数据表
* 此方法不完善(仅供参考)
* @param array $row
*
* @return \Illuminate\Database\Eloquent\Model|null
*/
public function model(array $row)
{
// print_r( $row );exit;
$data = Customer::getAllCustomer();
$data = json_decode( json_encode( $data ) , 256 );
# 处理数据
$repeat = 0;
foreach ( $data as $k => $v ) {
if( $data[$k]['***'] == $row['****'] ) {
$repeat++;
}
}
if( $repeat == 0 ) {
$res = new Customer([
'name' => $row['***'],
'mobile' => $row['****'],
'wechat' => $row['****'],
'qq' => $row['****'],
]);
return $res;
}
}
/**
* 一次插入多少数据
*
* @return int
*/
public function batchSize(): int
{
return 1000;
}
/**
* 每次处理多少行
*
* @return int
*/
public function chunkSize(): int
{
return 1000;
}
}
3. 导入控制器调用
# 导入数据
public function importCustomerData( Request $request ) {
# 文件
$file = $request->file( 'file' );
# 文件是否有错误
if( $file->getError() == 1 ) {
return $this->fail( 400 , '文件超出PHP上传文件大小设置' );
} elseif ( $file->getError() == 2 ) {
return $this->fail( 400 , '文件超出表单上传文件大小设置' );
} elseif ( $file->getError() == 3 ) {
return $this->fail( 400 , '文件上传不完整,请重新上传' );
} elseif ( $file->getError() == 4 ) {
return $this->fail( 400 , '没有文件被上传' );
} elseif ( $file->getError() == 6 ) {
return $this->fail( 400 , '找不到临时文件夹' );
} elseif ( $file->getError() == 7 ) {
return $this->fail( 400 , '文件写入失败' );
}
# 文件临时绝对路径
$path = $file->getRealPath();
# 文件后缀名
if( $file->getClientOriginalExtension() != 'xlsx' && $file->getClientOriginalExtension() != 'xls' ) {
return $this->fail( 400 , '文件类型错误' );
}
Excel::import(new CustomersImport() , $path , null , \Maatwebsite\Excel\Excel::XLSX );
return $this->success( '已执行导入,请自行检查数据是否导入成功' );
}
至此导入功能完成
4. 创建导出
php artisan make:export CustomerExport --model=Customer
5. 导出文件代码:
namespace App\Exports;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithEvents;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Events\AfterSheet;
use phpDocumentor\Reflection\Types\Collection;
class CustomerExport implements FromCollection,WithHeadings,WithEvents
{
// 要导出的数据
protected $data;
public function __construct( array $data )
{
return $this->data = $data;
}
/**
* 导出数据
*
* @return Collection
*/
public function collection()
{
if (!empty($this->data)) {
// 对应的业务和数据处理,此处省略
foreach ($this->data as $key => $vo) {
// 对于长数字字符串导出excel会变成科学计数,请在字符串后面加上 " ",例如:$str = $str . ' ';
$this->data[$key]['****'] = $vo['***'] . ' ';
$this->data[$key]['time'] = date( 'Y-m-d H:i:s' , $vo['time'] ) . ' ';
}
}
// print_r( $this->data );exit;
return collect( $this->data );
}
/**
* 设置导出文件的表头,如果不设置,只会导出数据库中的记录而不清楚每一项的含义
*
* @return array
*/
public function headings(): array
{
return [
'名称',
'手机号',
'微信',
'QQ',
];
}
/**
* registerEvents.
* 事件监听
* @return array
*/
public function registerEvents(): array
{
return [
// 生成表单元后处理事件
AfterSheet::class => function (AfterSheet $event) {
// 合并单元格
// $event->sheet->getDelegate()->setMergeCells(['A2:L2', 'B11:E11', 'A12:L12']);
// 设置单元格内容居中
// $event->sheet->getDelegate()->getStyle('A2:L2')->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
// $event->sheet->getDelegate()->getStyle('A3:L3')->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
// 定义列宽度
$widths = ['A' => 10, 'B' => 15, 'C' => 30, 'D' => 12, 'E' => 14, 'F' => 14, 'G' => 14, 'H' => 10, 'I' => 18, 'J' => 14, 'K' => 10];
foreach ($widths as $k => $v) {
// 设置列宽度
$event->sheet->getDelegate()->getColumnDimension($k)->setWidth($v);
}
},
];
}
}
6. 导出控制器调用:
# 导出数据
public function exportCustomerData() {
$data = Customer::getAllCustomer();
$data = $this->jsonToArray( $data );
if( empty( $data ) ) {
return $this->fail( 404 , '未找到数据' );
}
return Excel::download( new CustomerExport( $data ) , '资料.xlsx' );
}
至此导出功能完成