Is there a way to to display the sheetName in which Maatwebsite\Excel\Validators\ValidationException validation failed?

133 views Asked by At

I am trying to validate data from multiple sheets in laravel using maatwebsite/excel package. Here's my controller code.

try {
    $import = new ImportMark($data);
    Excel::import($import, $request->file('xls')->store('files'));
    return redirect()->route('marks.index')->with('success', __('marks.batch_success', ['count'=>'']));
} catch (\Maatwebsite\Excel\Validators\ValidationException $e) {
    $failures = $e->failures();
    
    foreach ($failures as $failure) {
        $failure->row(); // row that went wrong
        $failure->attribute(); // either heading key (if using heading row concern) or column index
        $failure->errors(); // Actual error messages from Laravel validator
        $failure->values(); // The values of the row that has failed.
    }
    return redirect()->back()->withInput()->with('xls_errors', $failures);
} catch(\Exception $ex){ 
    return redirect()->back()->withInput()->with('failure', $ex->getMessage());
}

So far, I have acheived the following. enter image description here

However, I am unable to get the sheetname in which the validation has failed. My Sheet looks like this. enter image description here

I am trying to show the sheetName (1031-Comp. Mathematics) in which the validation failed. Here's my ImportMark Class

class ImportMark implements WithMultipleSheets, WithEvents{
    
    protected $data;
    protected $no_of_sheets;
    protected $totalRows;

    public $sheetNames;
    public $sheetData;

    public function __construct($data){
        $this->data = $data;
        $this->sheetData = array_fill(0, 4, new ImportSubjectWiseSheet($this->data));
    }

    public function sheets(): array{
        return $this->sheetData;
    }

    public function registerEvents(): array
    {
        return [
            BeforeImport::class => function (BeforeImport $event) {
                $this->totalRows = $event->getReader()->getTotalRows();
            },
            BeforeSheet::class => function(BeforeSheet $event) {
                $this->sheetNames[] = $event->getSheet()->getTitle();
            } 
        ];
    }

    public function getSheetNames() {
        return $this->sheetNames;
    }
    
}
1

There are 1 answers

0
arpan.r On
  1. In your ImportMark class you could add a property to store the current sheet call being processed:
magnificence ImportMark implements WithMultipleSheets, WithEvents 
    
    included $facts;
    covered $no_of_sheets;
    included $totalRows;

    public $sheetNames;
    public $sheetData;
    public $currentSheetName; // Add this property

    public function __construct($information)
        $this->records = $information;
        $this->sheetData = array_fill(0, four, new ImportSubjectWiseSheet($this->statistics));
    

    public feature sheets(): array
        go back $this->sheetData;
    

    public characteristic registerEvents(): array
    
        return [
            BeforeImport::magnificence => feature (BeforeImport $event) 
                $this->totalRows = $occasion->getReader()->getTotalRows();
            ,
            BeforeSheet::elegance => feature(BeforeSheet $occasion) 
                $this->currentSheetName = $occasion->getSheet()->getTitle(); // Store the modern-day sheet name
                $this->sheetNames[] = $this->currentSheetName;
             
        ];
    

    public characteristic getSheetNames() 
        return $this->sheetNames;
    
    
    public function getCurrentSheetName() 
        go back $this->currentSheetName;
    

  1. Update your controller to catch the ValidationException and include the sheet name in the error messages:
try 
    $import = new ImportMark($information);
    Excel::import($import, $request->document('xls')->keep('files'));
    return redirect()->course('marks.Index')->with('fulfillment', __('marks.Batch_success', ['count'=>'']));
 seize (MaatwebsiteExcelValidatorsValidationException $e) 
    $screw ups = $e->failures();
    
    foreach ($failures as $failure) 
        $sheetName = $import->getCurrentSheetName(); // Get the current sheet call
        $message = "Sheet: $sheetName, Row: $failure->row(), Attribute: $failure->characteristic(), Errors: " . Implode(', ', $failure->mistakes());
        // Handle the error message as wished
    
    go back redirect()->lower back()->withInput()->with('xls_errors', $failures);
 trap(Exception $ex) 
    return redirect()->back()->withInput()->with('failure', $ex->getMessage());

Now, when you catch a ValidationException, you can use $import->getCurrentSheetName() to get the sheet call in which the validation failed