laravel:7.6 excel:3.1 本文章只涉及部分操作,更多操作請參考Excel官方文檔
- Excel GitHub官方 地址:https://github.com/maatwebsite/Laravel-Excel
- Excel官方文檔地址:https://docs.laravel-excel.com/3.1/getting-started/
安裝要求:
- PHP: ^7.0
- Laravel: ^5.5
- PhpSpreadsheet: ^1.6
- php_zip啓用PHP擴展
- php_xml啓用PHP擴展
- php_gd2啓用PHP擴展
安裝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. 導出文件代碼:
<?php
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' );
}
至此導出功能完成