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. 导出文件代码:



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

至此导出功能完成

你可能感兴趣的:(laravel)