I am trying to convert an Excel file to an array using the latest version of Laravel-Excel (3.1.9)
The code below will download the file:
return Excel::download(new SalesOrderExport('columns'),'test.xlsx')
But I need to convert it to get an array only. I don’t want to store this Excel data in a database at this point.
I tried with the code below but it did not work as the load
method is not available in version 3.
Excel::load($request->file('sampledata'), function ($reader) {
return response()->json($reader);
});
Please share your thoughts on how to get an array from Excel.
Trevor Reid
3,1824 gold badges27 silver badges46 bronze badges
asked Feb 27, 2019 at 10:11
Niklesh RautNiklesh Raut
33.5k15 gold badges72 silver badges109 bronze badges
0
I and @narayan tried hard to make requested excel file into array. Now I am able to get array properly with below code
$rows = Excel::toArray(new SalesOrderImport, $request->file('sampledata'));
In my SalesOrderExport class I have default function only, which is required as abstract method.
namespace AppExports;
use AppSalesOrder;
use MaatwebsiteExcelConcernsFromCollection;
class SalesOrderExport implements FromCollection
{
public function collection()
{
return SalesOrder::all();
}
}
My Controller code
public function importTest(Request $request)
{
$rows = Excel::toArray(new SalesOrderImport, $request->file('sampledata'));
return response()->json(["rows"=>$rows]);
}
And in HTML
<input class="" type="file" name="sampledata" id="sampledata">
I already created this export by
php artisan make:import SalesOrder
Attaching related images
answered Feb 27, 2019 at 13:23
Niklesh RautNiklesh Raut
33.5k15 gold badges72 silver badges109 bronze badges
1
I’m adding it on hope that someone could get another types of solution for this.
Version — "maatwebsite/excel": "^3.1"
In Controller
$data = Excel::toArray(new UsersImport(), $request->file);
In UsersImport
<?php
namespace AppImports;
use IlluminateSupportCollection;
use MaatwebsiteExcelConcernsToCollection;
class UsersImport implements ToCollection
{
public function collection(Collection $rows)
{
}
}
Json Array Result
array:2 [▼
0 => array:2 [▼
0 => "+126785XXXXX"
1 => "Jhon"
]
1 => array:2 [▼
0 => "+126784XXXXX"
1 => "Doe"
]
]
And One Bonus,
Now suppose you just need the phone numbers, then make a custom array from that in controller-
$data = Excel::toArray(new UsersImport(), $request->file);
$phoneNumbersData= [];
foreach ($data[0] as $key => $value) {
$phoneNumbersData[] = $value[0];
}
return $phoneNumbersData;
Hope, this will help someone.
answered Oct 6, 2020 at 21:17
0
Here are some working examples based on importing a csv file using the usual file input element. In my case, once uploaded, the file is accessible through the request object as ‘csv_file’.
public function importCSV(Request $request)
{
// Get the csv rows as an array
$theArray = Excel::toArray(new stdClass(), $request->file('csv_file'));
// Get the csv rows as a collection
$theCollection = Excel::toCollection(collect([]), $request->file('csv_file'));
//etc
}
answered Mar 26, 2021 at 15:56
I tried something like this and it worked perfectly;
in your import file do this
use IlluminateSupportCollection;
use MaatwebsiteExcelConcernsToCollection;
public function collection(Collection $row)
{
return $row;
}
Then in the controller, do this;
$row = Excel::toCollection(new CourseImport, request()->file('course'));
answered Apr 20, 2021 at 16:42
2
Here is how I achieved this:
In my UsersImport class:
namespace AppImports;
use AppUser;
use MaatwebsiteExcelConcernsToModel;
use MaatwebsiteExcelConcernsImportable;
class UsersImport implements ToModel
{
use Importable;
public function model(array $row)
{
return new User([
'id' => $row[0]
]);
}
}
And in controller:
$imported_users = (new UsersImport)->toArray(request()->file('excel_file'))[0];
I hope it helps you.
answered Mar 13, 2019 at 12:34
You should try this:
$data = Excel::load($request->file('sampledata'), function ($reader) use($table) {
$data = $reader->toArray();
//here data has all excel data in array.
});
answered Feb 27, 2019 at 10:36
7
-
Create Import File using below command.
php artisan make:import TestImport
-
Inside TestImport make changes like this:
namespace AppImports;
use AppUser;
use IlluminateSupportCollection;
use MaatwebsiteExcelConcernsToCollection;class TestImport implements ToCollection
{
public function collection(Collection $rows)
{
return $rows;
}
} -
In Controller make changes like this:
// original code: $rows = Excel::import(new TestImport, ‘test.xlsx’);
$rows = Excel::toCollection(new TestImport, ‘test.xlsx’);
answered Feb 27, 2019 at 10:15
narayansharma91narayansharma91
2,2731 gold badge12 silver badges20 bronze badges
8
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 AppImports;
use IlluminateSupportCollection;
use MaatwebsiteExcelConcernsToCollection;
use MaatwebsiteExcelConcernsWithHeadingRow;
use MaatwebsiteExcelConcernsWithMultipleSheets;
use MaatwebsiteExcelImportsHeadingRowFormatter;
use MaatwebsiteExcelConcernsWithEvents;
use MaatwebsiteExcelEventsBeforeImport;
use MaatwebsiteExcelEventsAfterImport;
use MaatwebsiteExcelEventsBeforeSheet;
use MaatwebsiteExcelEventsAfterSheet;
// Ü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);
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 AppImports;
use MaatwebsiteExcelConcernsToArray;
use MaatwebsiteExcelConcernsWithHeadingRow;
use MaatwebsiteExcelConcernsWithMultipleSheets;
use MaatwebsiteExcelImportsHeadingRowFormatter;
use MaatwebsiteExcelConcernsWithEvents;
use MaatwebsiteExcelEventsBeforeSheet;
// Ü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 AppImports;
use MaatwebsiteExcelConcernsToArray;
use MaatwebsiteExcelConcernsWithHeadingRow;
use MaatwebsiteExcelConcernsWithMultipleSheets;
use MaatwebsiteExcelImportsHeadingRowFormatter;
use MaatwebsiteExcelConcernsWithEvents;
use MaatwebsiteExcelEventsBeforeSheet;
use MaatwebsiteExcelConcernsWithChunkReading;
// Ü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
I and @narayan tried hard to make requested excel file into array. Now I am able to get array properly with below code
$rows = Excel::toArray(new SalesOrderImport, $request->file('sampledata'));
In my SalesOrderExport class I have default function only, which is required as abstract method.
namespace AppExports;
use AppSalesOrder;
use MaatwebsiteExcelConcernsFromCollection;
class SalesOrderExport implements FromCollection
{
public function collection()
{
return SalesOrder::all();
}
}
My Controller code
public function importTest(Request $request)
{
$rows = Excel::toArray(new SalesOrderImport, $request->file('sampledata'));
return response()->json(["rows"=>$rows]);
}
And in HTML
<input class="" type="file" name="sampledata" id="sampledata">
I already created this export by
php artisan make:import SalesOrder
Attaching related images
Tags:
Excel
Laravel
Laravel Excel
Maatwebsite Excel
Related
Recently popular package Laravel-Excel released a new version 3.0, which was a pretty radical change from previous versions. I needed to do a simple Excel export and noticed that their documentation covers only export from Laravel Collections but not from some custom structure. So I will show you a «workaround».
First, this is how documentation describes the basic workflow:
namespace AppExports; use MaatwebsiteExcelConcernsFromCollection; class InvoicesExport implements FromCollection { public function collection() { return Invoice::all(); } }
You need to create a separate class for export (similar how Laravel Notifications work) and you can define a collection to export.
There are also other ways to export the data:
From Eloquent query:
class InvoicesExport implements FromQuery { use Exportable; public function query() { return Invoice::query(); } }
Or, from View HTML table:
class InvoicesExport implements FromView { public function view(): View { return view('exports.invoices', [ 'invoices' => Invoice::all() ]); } }
But still, the problem is that all examples are based on Eloquent. What if I need Excel from some custom structure like array?
Imagine that I have this array:
[ [ 'name' => 'Povilas', 'surname' => 'Korop', 'email' => 'povilas@laraveldaily.com', 'twitter' => '@povilaskorop' ], [ 'name' => 'Taylor', 'surname' => 'Otwell', 'email' => 'taylor@laravel.com', 'twitter' => '@taylorotwell' ] ]
How do I export that into Excel, so that keys would be columns, and values would be rows?
There are two ways.
Option 1. Turn your Array into a Collection and add Headings
This is how the Export class would look:
namespace AppExports; use MaatwebsiteExcelConcernsFromCollection; use MaatwebsiteExcelConcernsExportable; use MaatwebsiteExcelConcernsWithHeadings; class CollectionExport implements FromCollection, WithHeadings { use Exportable; public function collection() { return collect([ [ 'name' => 'Povilas', 'surname' => 'Korop', 'email' => 'povilas@laraveldaily.com', 'twitter' => '@povilaskorop' ], [ 'name' => 'Taylor', 'surname' => 'Otwell', 'email' => 'taylor@laravel.com', 'twitter' => '@taylorotwell' ] ]); } public function headings(): array { return [ 'Name', 'Surname', 'Email', 'Twitter', ]; } }
You need to implement collection() method by using Laravel’s collect() method and passing array to it. Also, you need to implement headings() to add a header row.
Finally, in Controller you will have this row at the end of the method:
return Excel::download(new CollectionExport(), 'export.xlsx');
Then you would have this as downloaded result:
Option 2. Pass Array into View
Alternatively, you can build this resources/views/exports/xml.blade.php:
<table>
<thead>
<tr>
@foreach($data[0] as $key => $value)
<th>{{ ucfirst($key) }}</th>
@endforeach
</tr>
</thead>
<tbody>
@foreach($data as $row)
<tr>
@foreach ($row as $value)
<td>{{ $value }}</td>
@endforeach
</tr>
@endforeach
</tbody>
</table>
And then have this in your Export class:
namespace AppExports; use IlluminateContractsViewView; use MaatwebsiteExcelConcernsFromView; class BladeExport implements FromView { public function view(): View { return view('exports.xml', [ 'data' => [ [ 'name' => 'Povilas', 'surname' => 'Korop', 'email' => 'povilas@laraveldaily.com', 'twitter' => '@povilaskorop' ], [ 'name' => 'Taylor', 'surname' => 'Otwell', 'email' => 'taylor@laravel.com', 'twitter' => '@taylorotwell' ] ] ]); } }
Controller stays the same, just different class name:
return Excel::download(new BladeExport(), 'export.xlsx');
Wait, but how to pass data into Export class?
Both of our examples have one flaw — the data is formed in the class itself. Actually, it shouldn’t even know about the data, it should accept it as a parameter. But how do we do that, if view() or collection() methods have no parameters?
We will pass it through __construct() method into a private variable. You could call it a dependency injection, although there are much better examples of dependency injection, look it up on Google.
class BladeExport implements FromView { private $data; public function __construct($data) { $this->data = $data; } public function view(): View { return view('exports.xml', [ 'data' => $this->data ]); } }
So we’re accepting $data as a parameter now. Then, in our Controller we can have this:
$data = [ [ 'name' => 'Povilas', 'surname' => 'Korop', 'email' => 'povilas@laraveldaily.com', 'twitter' => '@povilaskorop' ], [ 'name' => 'Taylor', 'surname' => 'Otwell', 'email' => 'taylor@laravel.com', 'twitter' => '@taylorotwell' ] ]; return Excel::download(new BladeExport($data), 'export.xlsx');
I hope that’s helpful. Check out other examples in official documentation of the package.