laravel Excel3.1 導出導入文件

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' );
    }

至此導出功能完成

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章