Laravel-excel: [QUESTION] Using filename as part of import

Created on 27 Feb 2019  路  3Comments  路  Source: Maatwebsite/Laravel-Excel

Versions

  • PHP version: 7.2
  • Laravel version: 5.7
  • Package version: 3.1

Description

I have a process which loads multiple CSV files at a time, and may need to ignore these CSV files on subsequent runs (I don't control deletion of the files). As such I have a need to have a 'file' model to know when a file has been processed, and (the important bit!) I also need to store the related filename alongside each line of data as part of my import.

Was wondering if the filename for the import (passed in as the second param!) gets exposed in any way to the import class in App\Imports?

question

Most helpful comment

I am doing something similar like this, hope it helps.

class StageStockImport extends DefaultValueBinder implements ToModel, WithHeadingRow, WithCustomValueBinder, WithChunkReading, WithBatchInserts
{
    protected $dataProviderCode;
    protected $dataProviderName;
    protected $fileName;

    public function fromDataProvider(string $dpCode, string $dpName)
    {
        $this->dataProviderCode = $dpCode;
        $this->dataProviderName = $dpName;
        return $this;
    }

    public function fromFile(string $fileName)
    {
        $this->fileName = $fileName;
        return $this;
    }

    /**
    * @param array $row
    *
    * @return \Illuminate\Database\Eloquent\Model|null
    */
    public function model(array $row)
    {
        return new StageStock([
            'dp_code' => $this->dataProviderCode,
            'dp_name' => $this->dataProviderName,
            'stock_date' => (isset($row['date']) ? $this->transformDate(trim($row['date'])) : null),
            'product_id' => (isset($row['product_id']) ? trim($row['product_id']) : null),
            'product_description' => (isset($row['product_description']) ? trim($row['product_description']) : null),
            'stock_qty' => (isset($row['stock']) ? trim($row['stock']) : 0),
            'batch_number' => (isset($row['batch_number']) ? trim($row['batch_number']) : null),
            'expire_date' => (isset($row['exp_date']) ? $this->transformDate(trim($row['exp_date'])) : null),
            'file_name' => $this->fileName
        ]);
    }

    public function batchSize(): int
    {
        return 500;
    }

    public function chunkSize(): int
    {
        return 500;
    }    
}

Then I have a scheduled Console command doing this:

$allFiles = File::allFiles(storage_path('path/to/files'));

foreach ($allFiles as $file) {
    $fileName = $file->getFilename();
    $this->info(date('h:i:s') . ' Processing ' . $fileName);
    StageStock::where('dp_code', '1010')->where('file_name', $fileName)->delete();
    $import = (new StageStockImport())
        ->fromDataProvider('1010', 'DUMMY DATA PROVIDER')
        ->fromFile($fileName);
    Excel::import($import, "path/to/files/$fileName", 'local', \Maatwebsite\Excel\Excel::XLSX);
}

All 3 comments

If it doesn't get exposed, you could always pass the filename as a param to the import.
See this comment for an example.

I am doing something similar like this, hope it helps.

class StageStockImport extends DefaultValueBinder implements ToModel, WithHeadingRow, WithCustomValueBinder, WithChunkReading, WithBatchInserts
{
    protected $dataProviderCode;
    protected $dataProviderName;
    protected $fileName;

    public function fromDataProvider(string $dpCode, string $dpName)
    {
        $this->dataProviderCode = $dpCode;
        $this->dataProviderName = $dpName;
        return $this;
    }

    public function fromFile(string $fileName)
    {
        $this->fileName = $fileName;
        return $this;
    }

    /**
    * @param array $row
    *
    * @return \Illuminate\Database\Eloquent\Model|null
    */
    public function model(array $row)
    {
        return new StageStock([
            'dp_code' => $this->dataProviderCode,
            'dp_name' => $this->dataProviderName,
            'stock_date' => (isset($row['date']) ? $this->transformDate(trim($row['date'])) : null),
            'product_id' => (isset($row['product_id']) ? trim($row['product_id']) : null),
            'product_description' => (isset($row['product_description']) ? trim($row['product_description']) : null),
            'stock_qty' => (isset($row['stock']) ? trim($row['stock']) : 0),
            'batch_number' => (isset($row['batch_number']) ? trim($row['batch_number']) : null),
            'expire_date' => (isset($row['exp_date']) ? $this->transformDate(trim($row['exp_date'])) : null),
            'file_name' => $this->fileName
        ]);
    }

    public function batchSize(): int
    {
        return 500;
    }

    public function chunkSize(): int
    {
        return 500;
    }    
}

Then I have a scheduled Console command doing this:

$allFiles = File::allFiles(storage_path('path/to/files'));

foreach ($allFiles as $file) {
    $fileName = $file->getFilename();
    $this->info(date('h:i:s') . ' Processing ' . $fileName);
    StageStock::where('dp_code', '1010')->where('file_name', $fileName)->delete();
    $import = (new StageStockImport())
        ->fromDataProvider('1010', 'DUMMY DATA PROVIDER')
        ->fromFile($fileName);
    Excel::import($import, "path/to/files/$fileName", 'local', \Maatwebsite\Excel\Excel::XLSX);
}

Thanks guys for the quick response and working solutions!

Was this page helpful?
0 / 5 - 0 ratings