我如何以传统方式排队Laravel Excel进口,并在第一次阅读后再次派遣工作

发布于 2025-01-23 16:24:39 字数 6352 浏览 3 评论 0原文

我的代码:(控制器)

public function formatCSV(Request $request){
    $filename = $request->input('filename');
    $exported_filename = pathinfo($filename, PATHINFO_FILENAME).".csv";
    $export_filepath = 'files/scrubber/output/'.$exported_filename;
    $data = [
        'file_name'       => $filename,
        'header_row'      => 10,
        'start_row'       => 10,
        'unit_sqft_col'   => null,
        'file_path'       => storage_path('app/files/scrubber/') . $filename,
        'export_path'     => $export_filepath,
    ];

    $scrubberJob = (new ScrubberJob($data))->delay(Carbon::now()->addSeconds(3));
    dispatch($scrubberJob);

    return redirect()->route('scrubbers.index')->with('toast.success','Scrubber job is put into queue, please wait for a while..');
}

在上面的控制器上,我正在派遣scrubberjob

scrubberjob

<?php

namespace App\Jobs;

use App\Imports\ChunkScrubberImport;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Excel;

class ScrubberJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    protected $data;

    /**
     * Create a new job instance.
     *
     * @return void
     */
    public function __construct($data)
    {
        $this->data = $data;
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        $import = new ChunkScrubberImport($this->data);
        Excel::import($import, $this->data['file_path']);
    }
}

此作业触发chunkscrubberimport

chunkscrubberimport

<?php

namespace App\Imports;

use App\Exports\ChunkScrubberExport;
use Illuminate\Support\Collection;
use Maatwebsite\Excel\Concerns\ToArray;
use Maatwebsite\Excel\Concerns\ToCollection;
use Maatwebsite\Excel\Concerns\WithStartRow;
use Maatwebsite\Excel\Concerns\WithLimit;
use Maatwebsite\Excel\Concerns\WithStrictNullComparison;
use Illuminate\Support\Facades\Storage;

use Excel;


class ChunkScrubberImport implements ToArray, WithLimit, WithStartRow, WithStrictNullComparison
{
    protected $data;
    public $scrubbed_data;

    public function __construct($data, $scrubbed_data = [])
    {
        $this->data = $data;
        $this->scrubbed_data = $scrubbed_data;
    }

    public function array(Array $rows)
    {
        $this->scrubbed_data = $rows;
        return Excel::store(new ChunkScrubberExport($this->data,$this->scrubbed_data), $this->data['export_path']);
    }

    public function startRow(): int
    {
        return $this->data['start_row'];
    }

    public function limit(): int
    {
        return 1000;
    }
}

现在,此导入是触发

chunkscrubberexport

<?php

namespace App\Exports;

use App\Helpers\APRHelper;
use App\Models\Scrubber;
use Maatwebsite\Excel\Concerns\FromArray;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\RegistersEventListeners;
use Maatwebsite\Excel\Events\AfterSheet;
use Maatwebsite\Excel\Concerns\WithStrictNullComparison;


class ChunkScrubberExport implements FromArray,WithStrictNullComparison
{
    use RegistersEventListeners;
    protected $data;
    protected $scrubbed_data;

    public function __construct($data, $scrubbed_data = [])
    {
        $this->data = $data;
        $this->scrubbed_data = $scrubbed_data;
    }
    public function array(): array
    {
        $arr = $this->scrubbed_data;


        $rec_arr = $empty_col = array();
        $empty_col_checked = false;
        foreach ($arr as $ak => $av){
            //only if row is not empty (or filled with null), will get inside if condition
            if(count(array_filter($av)) != 0){
                if(!$empty_col_checked){
                    foreach($av as $k => $v){
                        if($v == ''){
                            $empty_col[] = $k;
                        }
                    }
                    $empty_col_checked = true;
                }
                $rec_arr[] = $av;
            }
        }

        foreach($empty_col as $ek => $ev){
            //get all values from a columns, which don't have value in header row
            //and check if all the values from this particular column is empty
            //if empty unset the columns
            if(empty( array_filter(array_column($rec_arr,$ev))) )
            {
                //unset array keys from whole array
                foreach($rec_arr as &$item) {
                    unset($item[$ev]);
                }
                unset($item);
            }
        }


        foreach ($rec_arr as $ak => $av) {

            foreach ($av as $k => $v) {

                //other stuff

            } //end foreach $av

        } //endforeach $rec_arr



        return $rec_arr;
    }
    public static function afterSheet(AfterSheet $event)
    {
        $active_sheet = $event->sheet->getDelegate();
        $centered_text = [
            'alignment' => [
                'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER, 'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER
            ]
        ];
        $active_sheet->getParent()->getDefaultStyle()->applyFromArray($centered_text);

    }
}

这对于1个周期或提取都很好,现在我有以下问题。

  1. 第一个周期之后,我想将start_row更新为$ data ['start_row'] + 1000,因为1000是限制,但是,我不知道会有什么成为放这个的最佳场所。 1个周期后,我想触发,在下面写下scrubberjob 但是随着更新的start_row
 $scrubberJob = (new ScrubberJob($data))->delay(Carbon::now()->addSeconds(3));
 dispatch($scrubberJob);
  1. ,因为在第一个周期时,由于我已经知道文件名,该文件已存储在$ data ['export_path'] 。因此,我不想覆盖旧文件,而是想将行附加到第二个周期中已经存在的文件。

  2. 如何检测文件的末尾,因此不再派遣scrubberjob。

顺便说一句,我还看到了文档中有关syredqueue的信息,但是我不确定它是否可以提供我在此处提到的所有需求。还是我只是使事情复杂化,应该使用syredqueue?但是,这仍然可能需要我的问题编号2的解决方案

My code: (controller)

public function formatCSV(Request $request){
    $filename = $request->input('filename');
    $exported_filename = pathinfo($filename, PATHINFO_FILENAME).".csv";
    $export_filepath = 'files/scrubber/output/'.$exported_filename;
    $data = [
        'file_name'       => $filename,
        'header_row'      => 10,
        'start_row'       => 10,
        'unit_sqft_col'   => null,
        'file_path'       => storage_path('app/files/scrubber/') . $filename,
        'export_path'     => $export_filepath,
    ];

    $scrubberJob = (new ScrubberJob($data))->delay(Carbon::now()->addSeconds(3));
    dispatch($scrubberJob);

    return redirect()->route('scrubbers.index')->with('toast.success','Scrubber job is put into queue, please wait for a while..');
}

On the above controller, I am dispatching ScrubberJob.

ScrubberJob

<?php

namespace App\Jobs;

use App\Imports\ChunkScrubberImport;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Excel;

class ScrubberJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    protected $data;

    /**
     * Create a new job instance.
     *
     * @return void
     */
    public function __construct($data)
    {
        $this->data = $data;
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        $import = new ChunkScrubberImport($this->data);
        Excel::import($import, $this->data['file_path']);
    }
}

This job is triggering ChunkScrubberImport

ChunkScrubberImport

<?php

namespace App\Imports;

use App\Exports\ChunkScrubberExport;
use Illuminate\Support\Collection;
use Maatwebsite\Excel\Concerns\ToArray;
use Maatwebsite\Excel\Concerns\ToCollection;
use Maatwebsite\Excel\Concerns\WithStartRow;
use Maatwebsite\Excel\Concerns\WithLimit;
use Maatwebsite\Excel\Concerns\WithStrictNullComparison;
use Illuminate\Support\Facades\Storage;

use Excel;


class ChunkScrubberImport implements ToArray, WithLimit, WithStartRow, WithStrictNullComparison
{
    protected $data;
    public $scrubbed_data;

    public function __construct($data, $scrubbed_data = [])
    {
        $this->data = $data;
        $this->scrubbed_data = $scrubbed_data;
    }

    public function array(Array $rows)
    {
        $this->scrubbed_data = $rows;
        return Excel::store(new ChunkScrubberExport($this->data,$this->scrubbed_data), $this->data['export_path']);
    }

    public function startRow(): int
    {
        return $this->data['start_row'];
    }

    public function limit(): int
    {
        return 1000;
    }
}

Now, this import is triggering ChunkScrubberExport

ChunkScrubberExport

<?php

namespace App\Exports;

use App\Helpers\APRHelper;
use App\Models\Scrubber;
use Maatwebsite\Excel\Concerns\FromArray;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\RegistersEventListeners;
use Maatwebsite\Excel\Events\AfterSheet;
use Maatwebsite\Excel\Concerns\WithStrictNullComparison;


class ChunkScrubberExport implements FromArray,WithStrictNullComparison
{
    use RegistersEventListeners;
    protected $data;
    protected $scrubbed_data;

    public function __construct($data, $scrubbed_data = [])
    {
        $this->data = $data;
        $this->scrubbed_data = $scrubbed_data;
    }
    public function array(): array
    {
        $arr = $this->scrubbed_data;


        $rec_arr = $empty_col = array();
        $empty_col_checked = false;
        foreach ($arr as $ak => $av){
            //only if row is not empty (or filled with null), will get inside if condition
            if(count(array_filter($av)) != 0){
                if(!$empty_col_checked){
                    foreach($av as $k => $v){
                        if($v == ''){
                            $empty_col[] = $k;
                        }
                    }
                    $empty_col_checked = true;
                }
                $rec_arr[] = $av;
            }
        }

        foreach($empty_col as $ek => $ev){
            //get all values from a columns, which don't have value in header row
            //and check if all the values from this particular column is empty
            //if empty unset the columns
            if(empty( array_filter(array_column($rec_arr,$ev))) )
            {
                //unset array keys from whole array
                foreach($rec_arr as &$item) {
                    unset($item[$ev]);
                }
                unset($item);
            }
        }


        foreach ($rec_arr as $ak => $av) {

            foreach ($av as $k => $v) {

                //other stuff

            } //end foreach $av

        } //endforeach $rec_arr



        return $rec_arr;
    }
    public static function afterSheet(AfterSheet $event)
    {
        $active_sheet = $event->sheet->getDelegate();
        $centered_text = [
            'alignment' => [
                'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER, 'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER
            ]
        ];
        $active_sheet->getParent()->getDefaultStyle()->applyFromArray($centered_text);

    }
}

this is working fine for 1 cycle or fetch, now I have the following questions.

  1. After the first cycle, I want to update the start_row to $data['start_row'] + 1000 since 1000 is the limit, but, I don't know what might be the best place to put this one. After 1 cycle I want to trigger, scrubberjob written below
    but with updated start_row
 $scrubberJob = (new ScrubberJob($data))->delay(Carbon::now()->addSeconds(3));
 dispatch($scrubberJob);
  1. Since, on first cycle, the file would already be created since I already know the filename, which is stored in $data['export_path']. So, instead of overwriting the old file, I want to append rows to the already existing file from the second cycle.

  2. How to detect the end of the file, so that no more ScrubberJob is dispatched.

By the way, I have also seen about ShouldQueue in docs but I am not sure if it could provide all the needs I have mentioned here. Or am I just complicating things and should go with shouldQueue instead? But still, that might need the solution of my question number 2

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文