当前位置: 首页 > 工具软件 > Laravel-Excel > 使用案例 >

laravel-excel合并行导入

巢承安
2023-12-01
<?php

namespace App\Excels\Imports\BasicInformation;

use Maatwebsite\Excel\Concerns\WithBatchInserts;
use Maatwebsite\Excel\Concerns\WithCalculatedFormulas;
use Maatwebsite\Excel\Concerns\WithChunkReading;
use Maatwebsite\Excel\Concerns\WithMapping;
use Maatwebsite\Excel\Concerns\WithStartRow;
use Maatwebsite\Excel\Events\BeforeImport;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
use Maatwebsite\Excel\Concerns\ToArray;
use Maatwebsite\Excel\Concerns\WithEvents;
//合并行的数据导入拆分详解
class StoreSiteImportExcel implements WithBatchInserts, WithMapping, WithEvents, WithStartRow, WithCalculatedFormulas, WithChunkReading
{

    public $mergeCells = [];
    public $filePath;

    public function __construct($filePath = '')
    {
        $this->filePath = $filePath;
    }

    protected $header = [
        0 => 'account',
        1 => 'primary_account',
        2 => 'platform',
        3 => 'site',
        4 => 'remark',
    ];

    protected $chunk_size = 1000;

    // 批量导入10000条
    public function batchSize(): int
    {
        return 10000;
    }

    // 以1000条数据基准切割数据
    public function chunkSize(): int
    {
        return $this->chunk_size;
    }

    public function startRow(): int
    {
        return 2;
    }

    public function map($row): array
    {
        $mapped = [];
        foreach ($this->header as $key => $value) {
            if ($value) {
                $val = preg_replace("/^[\s\v" . chr(194) . chr(160) . "]+/", "", $row[$key]);
                $mapped[$value] = preg_replace("/[\s\v" . chr(194) . chr(160) . "]+$/", "", $val);
            }
        }
        return $mapped;
    }

    //做合并行的数据恢复操作,也就是将合并行的数据恢复到未合并行数据
    public function array(array $array): array
    {
        if ($this->mergeCells) {
            $startRow = 2;
            foreach ($this->mergeCells as $key => $mergeCells) {
                if ($mergeCells && is_array($mergeCells)) {
                    foreach ($mergeCells as $mergeCell) {
                        [$begin, $end] = Coordinate::getRangeBoundaries($mergeCell);
                        //要和数组对应行列保持一直 数据对应: $array[$key][$row][$col],所以要进行行数据 - startRow ;列数据 - 1
                        $beginRow = $begin[1] - $startRow;
                        $beginCol = Coordinate::columnIndexFromString($begin[0]) - 1;//代表列,赋值后,直接用字段来替代
                        $endRow = $end[1] - $startRow;
                        $endCol = Coordinate::columnIndexFromString($end[0]) - 1;//代表列,赋值后,直接用字段来替代
//                        dd($begin,$end,$beginRow,$beginCol,$endRow,$endCol,$array);
                        $value = $array[$key][$beginRow][$this->header[$beginCol]];
                        for ($intCol = $beginCol; $intCol <= $endCol; $intCol++) {
                            for ($intRow = $beginRow; $intRow <= $endRow; $intRow++) {
                                $array[$key][$intRow][$this->header[$intCol]] = $value;
                            }
                        }
                    }
                }
            }
        }
        return $array;
    }

    public function registerEvents(): array
    {
        return [
            //这里做合并行数据收集
            BeforeImport::class => function (BeforeImport $event) {
                //因为无法设置laravel-excel中的setReadDataOnly 为false,所以在原生iof中设置setReadDataOnly 为false,获取合并数据
                $iofReader = $event->reader->getPhpSpreadsheetReader();
                $iofReader->setReadDataOnly(false);
                $iofLoad = $iofReader->load($event->getConcernable()->filePath);
                $mergeCells = [];
                foreach ($iofLoad->getAllSheets() as $key => $item) {
                    $mergeCells[$key] = $item->getMergeCells();
                }
                $event->getConcernable()->mergeCells = $mergeCells;
            },
        ];
    }
}

 类似资料: