Laravel-excel: [QUESTION] How to skip sheets which may only have a heading and no rows

Created on 11 Mar 2020  路  3Comments  路  Source: Maatwebsite/Laravel-Excel

Prerequisites

Versions

  • PHP version: v7.3.13
  • Laravel version: 6.18
  • Package version: 3.1.19

So I have the following importer:

<?php

namespace App\Health\Core\Excel\Imports;

use Maatwebsite\Excel\Concerns\WithMultipleSheets;
use App\Health\Core\Excel\Imports\Sheets\FormsSheetImport;
use App\Health\Core\Excel\Imports\Sheets\FieldsSheetImport;
use App\Health\Core\Excel\Imports\Sheets\ChoicesSheetImport;
use App\Health\Core\Excel\Imports\Sheets\DictionariesSheetImport;
use App\Health\Core\Excel\Imports\Sheets\ValidationsSheetImport;
use App\Health\Core\Excel\Imports\Sheets\DependenciesSheetImport;
use App\Health\Core\Excel\Imports\Sheets\BaseLineChecksSheetImport;
use App\Health\Core\Excel\Imports\Sheets\AttributesSheetImport;
use App\Health\Core\Excel\Imports\Sheets\AutoCalculatesSheetImport;
use App\Health\Core\Excel\Imports\Sheets\HelpBlocksSheetImport;

class DatasetImport implements WithMultipleSheets  {
    public function sheets(): array
    {
        return [
            'Forms'           => new FormsSheetImport(),
            'Fields'          => new FieldsSheetImport(),
            'Choices'         => new ChoicesSheetImport(),
            'Dictionary'      => new DictionariesSheetImport(),
            'Validations'     => new ValidationsSheetImport(),
            'Dependencies'    => new DependenciesSheetImport(),
            'Baseline Checks' => new BaseLineChecksSheetImport(),
            'Attributes'      => new AttributesSheetImport(),
            'Auto Calculates' => new AutoCalculatesSheetImport(),
            'Help Blocks'     => new HelpBlocksSheetImport(),
        ];
    }
}

The one I want to focus on is Help Blocks, as that can be an empty sheet with just a heading, so lets look at that import class:

<?php

namespace App\Health\Core\Excel\Imports\Sheets;

use Maatwebsite\Excel\Concerns\ToModel;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use App\Health\Core\Excel\Exceptions\FieldNotFoundException;
use App\Health\Datasets\Models\Field;
use App\Health\Datasets\Models\FieldHelpBlock;

class HelpBlocksSheetImport implements ToModel, WithHeadingRow {

    public function model(array $row)
    {
        return new FieldHelpBlock([
            'field_id' => $this->fetchFieldId($row),
            'text'     => $row['text'],
        ]);
    }

    /**
     * Fetches the Field id.
     *
     * If the field cannot be found based on the label, we throw an exception.
     * If the field can be found, we return the id of the field.
     *
     * @param array $row
     * @return mixed
     */
    protected function fetchFieldId(array $row) {
        $field = Field::where('label', '=', $row['belongs_to_field'])->first();

        if (is_null($field)) {
            throw new FieldNotFoundException($row['belongs_to_field'] . ' Was not found as a valid field. Is the spelling correct?');
        }

        return $field->id;
    }
}

The issue here is that because this sheet can be empty with just a header, I keep getting: Start row (2) is beyond highest row (1) which makes sense, theres only the heading here.

Is there a way, that wasn't documented, to skip sheets if they are empty? This is a trivial example because I know this particular sheet might actually always be empty, but other sheets can be as well, so I am looking for more a "if this sheet is empty skip it" then a "if this specific sheet is empty ..." solution.

I have seen hackie solutions, I am wondering if there is something inside the

I do know they have validation, but I am not sure that would work in this case.

Thoughts?

question

All 3 comments

@AdamKyle I have the same problem. Did you find any solution?

@michszym95 yes I did, the solution was (if you only have a header for that tab), add null to the first header. So for example:

| id | product | description |
| ------------- |:-------------:| -----:|
| | | |

would become:

| id | product | description |
| ------------- |:-------------:| -----:|
|null | | |

and then you check if is_null($row['id']). if so return.

That was my solution and it works for my use cases.

@michszym95 yes I did, the solution was (if you only have a header for that tab), add null to the first header. So for example:
id product description

would become:
id product description
null

and then you check if is_null($row['id']). if so return.

That was my solution and it works for my use cases.

Not workit with OnEachRow interface.

Was this page helpful?
0 / 5 - 0 ratings