Laravel-excel: [QUESTION] Concept of ::import and ::toArray

Created on 8 Nov 2018  路  4Comments  路  Source: Maatwebsite/Laravel-Excel

Versions
PHP version: 7.1.20-1
Laravel version: 5.6
Package version: 3.1

Description
It is not clear to me how to use the methods. If i do this

            $ts = Excel::toArray(new HImport1, $importFile);

            dd($ts);

i get an array as expected but the method "collection(Collection $collection)" in my import-class seems to be unused.

if if change it to

            $ts = Excel::import(new HImport1, $importFile);

            dd($ts);

i can dump the collection (of a tab) in the "collection"-method of my import-class. But i dont see a way to export it to my controller?

What to do?

Additional Information

Import-class:

```

namespace App\Imports;

use Illuminate\Support\Collection;
use Maatwebsite\Excel\Concerns\ToCollection;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\WithMultipleSheets;
use Maatwebsite\Excel\Imports\HeadingRowFormatter;

HeadingRowFormatter::default('none');

class HImport1 implements ToCollection, WithHeadingRow
{

public function collection(Collection $collection)
{

    dump($collection);

    return "test";

}

}```

Most helpful comment

It seems that i succesfully wrapped my mind around the new concept of laravel excel.

My problem: I need the sheet names and header row to let the user decide which sheet ist holding a specific kind of data.

With 2.1 i did this

function getSheets($EXCELFILE_READER){
    $sheetData = array(); 
    $sheetTitle = array();
    $sheets = array();
    foreach ($EXCELFILE_READER->getAllSheets() as $sheet) {
        $sheetTitle[] = $sheet->getTitle();
        $sheets[] = array('title' => $sheet->getTitle(), 'rows' => $sheet->toArray());
    }
    $sheetData = array(
        'names' => $sheetTitle,
        'data' => $sheets
    );
    return $sheetData;
}

Now i do it like this

Import Class

<?php

namespace App\Imports;

use Illuminate\Support\Collection;
use Maatwebsite\Excel\Concerns\ToCollection;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\WithMultipleSheets;
use Maatwebsite\Excel\Imports\HeadingRowFormatter;
use Maatwebsite\Excel\Concerns\WithEvents;

use Maatwebsite\Excel\Events\BeforeImport;
use Maatwebsite\Excel\Events\AfterImport;
use Maatwebsite\Excel\Events\BeforeSheet;
use Maatwebsite\Excel\Events\AfterSheet;

// 脺berschriften werden genau so 眉bernommen wie sie in der Datei angegeben wurden
HeadingRowFormatter::default('none');

class HImport1 implements ToCollection, WithHeadingRow, WithEvents
{
    public $sheetNames;
    public $sheetData;

    public function __construct(){
        $this->sheetNames = [];
    $this->sheetData = [];
    }
    public function collection(Collection $collection)
    {
        $this->sheetData[] = $collection;
    }
    public function registerEvents(): array
    {
        return [
            BeforeSheet::class => function(BeforeSheet $event) {
                $this->sheetNames[] = $event->getSheet()->getTitle();
            } 
        ];
    }

}

Controller:

$Import = new HImport1();
$ts = Excel::import($Import, $importFile);
dump($Import);

image 15

Notice that this only works by using the registerEvents method and the closures for event logic. If you try the same with RegistersEventListeners and a normal event method you cannot set the sheetname because the "beforeSheet"-method is static and "$this->sheetNames" wont be defined.

Works with "toArray" also.

<?php

namespace App\Imports;

use Maatwebsite\Excel\Concerns\ToArray;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\WithMultipleSheets;
use Maatwebsite\Excel\Imports\HeadingRowFormatter;
use Maatwebsite\Excel\Concerns\WithEvents;
use Maatwebsite\Excel\Events\BeforeSheet;

// 脺berschriften werden genau so 眉bernommen wie sie in der Datei angegeben wurden
HeadingRowFormatter::default('none');

class HImport1 implements ToArray, WithHeadingRow, WithEvents
{

    public $sheetNames;
    public $sheetData;

    public function __construct(){
        $this->sheetNames = [];
    $this->sheetData = [];
    }
    public function array(array $array)
    {
        $this->sheetData[] = $array;
    }
    public function registerEvents(): array
    {
        return [
            BeforeSheet::class => function(BeforeSheet $event) {
                $this->sheetNames[] = $event->getSheet()->getTitle();
            } 
        ];
    }

}

In one of the following steps i need a associative array with the sheet names as key for that sheets data to use my existing code with laravel excel 3.1. I did this

<?php

namespace App\Imports;

use Maatwebsite\Excel\Concerns\ToArray;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\WithMultipleSheets;
use Maatwebsite\Excel\Imports\HeadingRowFormatter;
use Maatwebsite\Excel\Concerns\WithEvents;
use Maatwebsite\Excel\Events\BeforeSheet;
use Maatwebsite\Excel\Concerns\WithChunkReading;

// 脺berschriften werden genau so 眉bernommen wie sie in der Datei angegeben wurden
HeadingRowFormatter::default('none');

class HImport2 implements ToArray, WithHeadingRow, WithEvents
{

    public $sheetNames;
    public $sheetData;

    public function __construct(){
        $this->sheetNames = [];
        $this->sheetData = [];
    }
    public function array(array $array)
    {
        $this->sheetData[$this->sheetNames[count($this->sheetNames)-1]] = $array;
    }
    public function registerEvents(): array
    {
        return [
            BeforeSheet::class => function(BeforeSheet $event) {
                $this->sheetNames[] = $event->getSheet()->getTitle();
            } 
        ];
    }
    public function chunkSize(): int
    {
        return 5;
    }
}

Output example
image 18

All 4 comments

Thanks for submitting the ticket. Unfortunately the information you provided is incomplete. We need to know which version you use and how to reproduce it. Please include code examples. Before we can pick it up, please check (https://github.com/Maatwebsite/Laravel-Excel/blob/3.1/.github/ISSUE_TEMPLATE.md) and add the missing information. To make processing of this ticket a lot easier, please make sure to check (https://laravel-excel.maatwebsite.nl/docs/3.1/getting-started/contributing) and double-check if you have filled in the issue template correctly. This will allow us to pick up your ticket more efficiently. Issues that follow the guidelines correctly will get priority over other issues.

It seems that i succesfully wrapped my mind around the new concept of laravel excel.

My problem: I need the sheet names and header row to let the user decide which sheet ist holding a specific kind of data.

With 2.1 i did this

function getSheets($EXCELFILE_READER){
    $sheetData = array(); 
    $sheetTitle = array();
    $sheets = array();
    foreach ($EXCELFILE_READER->getAllSheets() as $sheet) {
        $sheetTitle[] = $sheet->getTitle();
        $sheets[] = array('title' => $sheet->getTitle(), 'rows' => $sheet->toArray());
    }
    $sheetData = array(
        'names' => $sheetTitle,
        'data' => $sheets
    );
    return $sheetData;
}

Now i do it like this

Import Class

<?php

namespace App\Imports;

use Illuminate\Support\Collection;
use Maatwebsite\Excel\Concerns\ToCollection;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\WithMultipleSheets;
use Maatwebsite\Excel\Imports\HeadingRowFormatter;
use Maatwebsite\Excel\Concerns\WithEvents;

use Maatwebsite\Excel\Events\BeforeImport;
use Maatwebsite\Excel\Events\AfterImport;
use Maatwebsite\Excel\Events\BeforeSheet;
use Maatwebsite\Excel\Events\AfterSheet;

// 脺berschriften werden genau so 眉bernommen wie sie in der Datei angegeben wurden
HeadingRowFormatter::default('none');

class HImport1 implements ToCollection, WithHeadingRow, WithEvents
{
    public $sheetNames;
    public $sheetData;

    public function __construct(){
        $this->sheetNames = [];
    $this->sheetData = [];
    }
    public function collection(Collection $collection)
    {
        $this->sheetData[] = $collection;
    }
    public function registerEvents(): array
    {
        return [
            BeforeSheet::class => function(BeforeSheet $event) {
                $this->sheetNames[] = $event->getSheet()->getTitle();
            } 
        ];
    }

}

Controller:

$Import = new HImport1();
$ts = Excel::import($Import, $importFile);
dump($Import);

image 15

Notice that this only works by using the registerEvents method and the closures for event logic. If you try the same with RegistersEventListeners and a normal event method you cannot set the sheetname because the "beforeSheet"-method is static and "$this->sheetNames" wont be defined.

Works with "toArray" also.

<?php

namespace App\Imports;

use Maatwebsite\Excel\Concerns\ToArray;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\WithMultipleSheets;
use Maatwebsite\Excel\Imports\HeadingRowFormatter;
use Maatwebsite\Excel\Concerns\WithEvents;
use Maatwebsite\Excel\Events\BeforeSheet;

// 脺berschriften werden genau so 眉bernommen wie sie in der Datei angegeben wurden
HeadingRowFormatter::default('none');

class HImport1 implements ToArray, WithHeadingRow, WithEvents
{

    public $sheetNames;
    public $sheetData;

    public function __construct(){
        $this->sheetNames = [];
    $this->sheetData = [];
    }
    public function array(array $array)
    {
        $this->sheetData[] = $array;
    }
    public function registerEvents(): array
    {
        return [
            BeforeSheet::class => function(BeforeSheet $event) {
                $this->sheetNames[] = $event->getSheet()->getTitle();
            } 
        ];
    }

}

In one of the following steps i need a associative array with the sheet names as key for that sheets data to use my existing code with laravel excel 3.1. I did this

<?php

namespace App\Imports;

use Maatwebsite\Excel\Concerns\ToArray;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\WithMultipleSheets;
use Maatwebsite\Excel\Imports\HeadingRowFormatter;
use Maatwebsite\Excel\Concerns\WithEvents;
use Maatwebsite\Excel\Events\BeforeSheet;
use Maatwebsite\Excel\Concerns\WithChunkReading;

// 脺berschriften werden genau so 眉bernommen wie sie in der Datei angegeben wurden
HeadingRowFormatter::default('none');

class HImport2 implements ToArray, WithHeadingRow, WithEvents
{

    public $sheetNames;
    public $sheetData;

    public function __construct(){
        $this->sheetNames = [];
        $this->sheetData = [];
    }
    public function array(array $array)
    {
        $this->sheetData[$this->sheetNames[count($this->sheetNames)-1]] = $array;
    }
    public function registerEvents(): array
    {
        return [
            BeforeSheet::class => function(BeforeSheet $event) {
                $this->sheetNames[] = $event->getSheet()->getTitle();
            } 
        ];
    }
    public function chunkSize(): int
    {
        return 5;
    }
}

Output example
image 18

^ Above way is the correct way for your user case then, yes.

@CaptainCannabis Thanks, it's working perfect

Was this page helpful?
0 / 5 - 0 ratings