diff --git a/README.md b/README.md
index 6d7ff7d..7a7e832 100644
--- a/README.md
+++ b/README.md
@@ -1,85 +1,125 @@
-# Laravel Excel
+# Laravel Excel
+[![Latest Stable Version](https://poser.pugx.org/cyber-duck/laravel-excel/v/stable)](https://packagist.org/packages/cyber-duck/laravel-excel)
+[![Total Downloads](https://poser.pugx.org/cyber-duck/laravel-excel/downloads)](https://packagist.org/packages/cyber-duck/laravel-excel)
+[![License](https://poser.pugx.org/cyber-duck/laravel-excel/license)](https://raw.githubusercontent.com/Cyber-Duck/laravel-excel/master/LICENSE)
+
+Exporting and importing Excel, CSV and OpenOffice stylesheets using Eloquent Collections and Query Builders in Laravel (5.* and 4.*).
+It's based on [box/spout](https://github.com/box/spout).
+
+Author: [Simone Todaro](https://github.com/SimoTod)
+Contributors: [Clément Blanco](https://github.com/Claymm)
+Made with :heart: by [Cyber-Duck Ltd](http://www.cyber-duck.co.uk)
[Installation](#installation)
[Export Excel](#export-excel)
[Import Excel](#import-excel)
[Different formats](#different-formats)
-This package provides a way to export an Eloquent collection as an excel file and to import a Excel file as an Eloquent collection. It's based on [box/spout](https://github.com/box/spout).
+## Installation
+Use composer to download the package:
+```
+composer require cyber-duck/laravel-excel
+```
+
+### Laravel 4.x
+
+Register the service provider in `config/app.php` by adding this line to providers array.
-## Installation
-The package must be installed directly from [Composer](https://getcomposer.org/).
-Run the following command:
+```php
+'providers' => [
+ Cyberduck\LaravelExcel\ExcelLegacyServiceProvider::class,
+],
```
-$ composer require cyberduck/laravel-excel
+
+### Laravel < 5.5
+
+Register the service provider in `config/app.php` by adding this line to providers array.
+
+```php
+'providers' => [
+ Cyberduck\LaravelExcel\ExcelServiceProvider::class,
+],
```
-To make Facades available, register the service provider in config/app.php adding *Cyberduck\LaravelExcel\ExcelServiceProvider* to the provider array.
+### Laravel 5.5
-Note. If you are on Laravel 4, use *Cyberduck\LaravelExcel\ExcelLegacyServiceProvider*
+No need to register anything, since it used package auto discovery feature in Laravel 5.5.
## Export Excel
### Generate and download an excel file
-Add
+Add
```
use Exporter;
-```
+```
to your controller.
-In your action, add
+In your controler function, create a new excel file from an Eloquent collection.
```
$excel = Exporter::make('Excel');
-$excel->load($yourCollection);
-return $excel->stream($yourFileName);
-```
+$excel->load($yourCollection);
+return $excel->stream($yourFileName);
+```
-The exporter class is fluent, then you can also write
+The exporter class is fluent, so you can also write
```
return Exporter::make('Excel')->load($yourCollection)->stream($yourFileName);
```
-### Generate and save an excel file
-Add
+The exporter class supports Query builder objects as well
+```
+$query = DB:table('table')->select('col1','col2');
+$excel = Exporter::make('Excel');
+$excel->loadQuery($query);
+return $excel->stream($yourFileName);
```
-use Exporter;
-```
-to your controller.
-In your action, add
+If you deal with big tables, you can set the chunk size to minimise the memory usage
```
+$query = DB:table('table')->select('col1','col2');
$excel = Exporter::make('Excel');
-$excel->load($yourCollection);
-return $excel->save($yourFileNameWithPath);
-```
+$excel->loadQuery($query);
+$excel->setChunk(1000);
+return $excel->stream($yourFileName);
+```
-The exporter class is fluent, then you can also write
+### Generate and save an excel file
+To save the excel file on the server, use the save method.
```
-return Exporter::make('Excel')->load($yourCollection)->save($yourFileNameWithPath);
+return $excel->save($yourFileNameWithPath);
```
### Advanced usage
-By default, every element of the Collection become a row and every unprotected field of the Model become a cell. No headers row is printed.
+By default, every element of the Collection becomes a row and every unprotected field of the Model becomes a cell.
+No headers row is printed.
+
+To change this behaviour, create a class extending *Cyberduck\LaravelExcel\Contract\SerialiserInterface*, implement the methods *getHeaderRow()* and *getData(Model $data)* and set this class on the excel object usint *setSerialiser()*.
+```
+$serialiser = new CustomSerialiser();
+$excel = Exporter::make('Excel');
+$excel->load($collection);
+$excel->setSerialiser($serialiser);
+return $excel->stream($yourFileName);
+```
-To change this behaviour, create a class extending *Cyberduck\LaravelExcel\Contract\SerialiserInterface* and implement the methods *getHeaderRow()* and *getData(Model $data)*.
-*getHeaderRow()* must return an array of string, and every elements is a cell of the first row. To not print the header row, simply return a void array *[]*.
-*getData(Model $data)* must return an array of string, and every elements is a cell of rows after the header.
+*getHeaderRow()* must return an array of string where every element is a cell of the first row. To not print the header row, simply return a void array *[]*.
+*getData(Model $data)* must return an array of string, and every elements is a cell.
Example
```
-namespace App\Serialiser;
+namespace App\Serialisers;
use Illuminate\Database\Eloquent\Model;
use Cyberduck\LaravelExcel\Contract\SerialiserInterface;
class ExampleSerialiser implements SerialiserInterface
{
- public function getData(Model $data)
+ public function getData($data)
{
$row = [];
$row[] = $data->field1;
- $row[] = $data->relation->field2;
+ $row[] = $data->relationship->field2;
return $row;
}
@@ -88,14 +128,86 @@ class ExampleSerialiser implements SerialiserInterface
{
return [
'Field 1',
- 'Field 2 (from a relation)'
+ 'Field 2 (from a relationship)'
];
}
}
```
+then set the serialiser before saving the file the collection.
+```
+$collection = Exporter::make('Excel')->load($yourCollection)->setSerialiser(new ExampleSerialiser)->stream($yourFileName);
+```
## Import Excel
-Coming soon! (In development)
+Add
+```
+use Importer;
+```
+to your controller.
+
+In your controler function, import an excel file.
+```
+$excel = Importer::make('Excel');
+$excel->load($filepath);
+$collection = $excel->getCollection();
+//dd($collection)
+```
+
+The importer class is fluent, then you can also write
+```
+return Importer::make('Excel')->load($filepath)->getCollection();
+```
+
+### Advanced usage
+By default, every row of the first sheet of the excel file becomes an array and the final result is wraped in a Collection (Illuminate\Support\Collection).
+
+To import a different sheet, use *setSheet($sheet)*
+```
+$excel = Importer::make('Excel');
+$excel->load($filepath);
+$excel->setSheet($sheetNumber);
+$collection = $excel->getCollection();
+//dd($collection)
+```
+
+To import each row in an Eloquent model, create a class extending *Cyberduck\LaravelExcel\Contract\ParserInterface* and implement the methods *transform($row)*.
+
+Example
+```
+namespace App\Parsers;
+
+use App\Models\YourModel;
+use Cyberduck\LaravelExcel\Contract\ParserInterface;
+
+class ExampleParser implements ParserInterface
+{
+ public function transform($row, $header)
+ {
+ $model = new YourModel();
+ $model->field1 = $row[0];
+ $model->field2 = $row[1];
+ // We can manunipulate the data before returning the object
+ $model->field3 = new \Carbon($row[2]);
+ return $model;
+ }
+}
+```
+then set the parser before creating the collection.
+```
+$collection = Importer::make('Excel')->load($filepath)->setParser(new ExampleParser)->getCollection();
+```
## Different formats
-Coming soon!
+The package supports ODS and CSV files.
+
+### ODS
+```
+$exporter = Exporter::make('OpenOffice');
+$importer = Importer::make('OpenOffice');
+```
+
+### CSV
+```
+$exporter = Exporter::make('Csv');
+$importer = Importer::make('Csv');
+```
diff --git a/composer.json b/composer.json
index a009c4c..c881277 100644
--- a/composer.json
+++ b/composer.json
@@ -1,25 +1,47 @@
{
- "name": "cyberduck/laravel-excel",
+ "name": "cyber-duck/laravel-excel",
"type": "library",
- "description": "",
- "keywords": ["Laravel", "Excel"],
- "require": {
- "php": ">=5.4.0",
- "box/spout": "^2.4",
- "illuminate/database": "4.*|5.1",
- "illuminate/support": "4.*|5.1"
- },
+ "description": "This package provides a way to export an Eloquent collection as an excel file and to import a Excel file as an Eloquent collection.",
+ "keywords": ["laravel", "excel", "exporter", "export", "importer", "import", "eloquent", "spout"],
"license": "MIT",
"authors": [
{
"name": "Simone Todaro",
- "email": "simone@cyber-duck.co.uk",
+ "email": "simo.todaro@gmail.com",
"role": "Developer"
}
],
+ "require": {
+ "php": "^7.2.5",
+ "box/spout": "^3.1",
+ "illuminate/database": "^6.0.0|^7.0.0",
+ "illuminate/support": "^6.0.0|^7.0.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^7.0",
+ "phpspec/phpspec": "^6.1.1",
+ "laravel/laravel": "^6.0.0|^7.0.0"
+ },
"autoload": {
"psr-4": {
"Cyberduck\\LaravelExcel\\": "src"
}
- }
+ },
+ "autoload-dev": {
+ "files": [
+ "tests/TestCase.php",
+ "tests/utils/Item.php",
+ "tests/utils/Migration.php",
+ "tests/utils/DatabaseSeeder.php",
+ "tests/utils/FirstColumnOnlySerialiser.php"
+ ]
+ },
+ "extra": {
+ "laravel": {
+ "providers": [
+ "Cyberduck\\LaravelExcel\\ExcelServiceProvider"
+ ]
+ }
+ },
+ "minimum-stability": "stable"
}
diff --git a/phpunit.xml b/phpunit.xml
new file mode 100644
index 0000000..edc9687
--- /dev/null
+++ b/phpunit.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+ ./tests/
+ ./tests/views
+
+
+
\ No newline at end of file
diff --git a/src/Contract/ExporterInterface.php b/src/Contract/ExporterInterface.php
index 75e3a22..61f25bc 100644
--- a/src/Contract/ExporterInterface.php
+++ b/src/Contract/ExporterInterface.php
@@ -1,11 +1,14 @@
alias('Exporter', '\Cyberduck\LaravelExcel\ExporterFacade');
- $loader->alias('Importer', '\Cyberduck\LaravelExcel\ImporterFacade');
+ $loader->alias('Exporter', \Cyberduck\LaravelExcel\ExporterFacade::class);
+ $loader->alias('Importer', \Cyberduck\LaravelExcel\ImporterFacade::class);
}
public function register()
diff --git a/src/Exporter/AbstractSpreadsheet.php b/src/Exporter/AbstractSpreadsheet.php
index 41cbdec..d3c1118 100644
--- a/src/Exporter/AbstractSpreadsheet.php
+++ b/src/Exporter/AbstractSpreadsheet.php
@@ -1,8 +1,9 @@
data = [];
$this->type = $this->getType();
$this->serialiser = new BasicSerialiser();
+ $this->callbacks = collect([]);
}
+ public function __call($name, $args)
+ {
+ $this->callbacks->push([$name, $args]);
+ return $this;
+ }
public function load(Collection $data)
{
@@ -27,6 +36,18 @@ public function load(Collection $data)
return $this;
}
+ public function loadQuery(Builder $query)
+ {
+ $this->data = $query;
+ return $this;
+ }
+
+ public function setChunk($size)
+ {
+ $this->chunksize = $size;
+ return $this;
+ }
+
public function setSerialiser(SerialiserInterface $serialiser)
{
$this->serialiser = $serialiser;
@@ -35,6 +56,8 @@ public function setSerialiser(SerialiserInterface $serialiser)
abstract public function getType();
+ abstract public function createWriter();
+
public function save($filename)
{
$writer = $this->create();
@@ -53,18 +76,38 @@ public function stream($filename)
protected function create()
{
- return WriterFactory::create($this->type);
+ $writer = $this->createWriter();
+ $this->callbacks->each(function ($elem) use (&$writer) {
+ call_user_func_array(array($writer, $elem[0]), $elem[1]);
+ });
+ return $writer;
}
protected function makeRows($writer)
{
$headerRow = $this->serialiser->getHeaderRow();
if (!empty($headerRow)) {
- $writer->addRow($headerRow);
+ $row = WriterEntityFactory::createRowFromArray($headerRow);
+ $writer->addRow($row);
}
- foreach ($this->data as $record) {
- $writer->addRow($this->serialiser->getData($record));
+ if ($this->data instanceof Builder) {
+ if (isset($this->chuncksize)) {
+ $this->data->chunk($this->chuncksize);
+ } else {
+ $this->addRowsDataToWriter($this->data->get(), $writer);
+ }
+ } else {
+ $this->addRowsDataToWriter($this->data, $writer);
}
return $writer;
}
+
+ public function addRowsDataToWriter($data, $writer)
+ {
+ foreach ($data as $record) {
+ $recordData = $this->serialiser->getData($record);
+ $row = WriterEntityFactory::createRowFromArray($recordData);
+ $writer->addRow($row);
+ }
+ }
}
diff --git a/src/Exporter/Csv.php b/src/Exporter/Csv.php
index 6fda1a6..8fe2c18 100644
--- a/src/Exporter/Csv.php
+++ b/src/Exporter/Csv.php
@@ -2,6 +2,7 @@
namespace Cyberduck\LaravelExcel\Exporter;
use Box\Spout\Common\Type;
+use Box\Spout\Writer\Common\Creator\WriterEntityFactory;
class Csv extends AbstractSpreadsheet
{
@@ -9,4 +10,9 @@ public function getType()
{
return Type::CSV;
}
+
+ public function createWriter()
+ {
+ return WriterEntityFactory::createCSVWriter();
+ }
}
diff --git a/src/Exporter/Excel.php b/src/Exporter/Excel.php
index 0a858a0..8983e6e 100644
--- a/src/Exporter/Excel.php
+++ b/src/Exporter/Excel.php
@@ -2,6 +2,7 @@
namespace Cyberduck\LaravelExcel\Exporter;
use Box\Spout\Common\Type;
+use Box\Spout\Writer\Common\Creator\WriterEntityFactory;
class Excel extends AbstractSpreadsheet
{
@@ -9,4 +10,9 @@ public function getType()
{
return Type::XLSX;
}
+
+ public function createWriter()
+ {
+ return WriterEntityFactory::createXLSXWriter();
+ }
}
diff --git a/src/Exporter/OpenOffice.php b/src/Exporter/OpenOffice.php
index 9e28199..15b0970 100644
--- a/src/Exporter/OpenOffice.php
+++ b/src/Exporter/OpenOffice.php
@@ -2,6 +2,7 @@
namespace Cyberduck\LaravelExcel\Exporter;
use Box\Spout\Common\Type;
+use Box\Spout\Writer\Common\Creator\WriterEntityFactory;
class OpenOffice extends AbstractSpreadsheet
{
@@ -9,4 +10,9 @@ public function getType()
{
return Type::ODS;
}
+
+ public function createWriter()
+ {
+ return WriterEntityFactory::createODSWriter();
+ }
}
diff --git a/src/Importer/AbstractSpreadsheet.php b/src/Importer/AbstractSpreadsheet.php
index 12fa276..d94d337 100644
--- a/src/Importer/AbstractSpreadsheet.php
+++ b/src/Importer/AbstractSpreadsheet.php
@@ -1,8 +1,7 @@
path = '';
- $this->sheet = 0;
+ $this->sheet = 1;
+ $this->hasHeaderRow = 0;
$this->type = $this->getType();
$this->parser = new BasicParser();
+ $this->model = false;
+ $this->callbacks = collect([]);
+ }
+
+ public function __call($name, $args)
+ {
+ $this->callbacks->push([$name, $args]);
+ return $this;
}
public function load($path)
{
$this->path = $path;
+ return $this;
}
public function setSheet($sheet)
{
$this->sheet = $sheet;
+ return $this;
+ }
+
+ public function hasHeader($hasHeaderRow)
+ {
+ $this->hasHeaderRow = $hasHeaderRow;
}
public function setParser(ParserInterface $parser)
{
$this->parser = $parser;
+ return $this;
+ }
+
+ public function setModel(Model $model)
+ {
+ $this->model = $model;
+ return $this;
}
abstract public function getType();
+ abstract public function createReader();
+
public function getCollection()
{
- $reader = $this->create();
- $reader->open();
- $collection = $this->parseRows($reader);
+ $headers = false;
+
+ $reader = $this->open();
+
+ foreach ($reader->getSheetIterator() as $index => $sheet) {
+ if ($index !== $this->sheet) {
+ continue;
+ }
+
+ $collection = $this->model ? $this->model->newCollection() : collect([]);
+
+ foreach ($sheet->getRowIterator() as $rowindex => $row) {
+ if ($rowindex == 1 && $this->hasHeaderRow) {
+ $headers = $row->toArray();
+ } else {
+ $data = $this->parser->transform($row->toArray(), $headers);
+
+ if ($data !== false) {
+ if ($this->model) {
+ $data = $this->model->getQuery()->newInstance($data);
+ }
+
+ $collection->push($data);
+ }
+ }
+ }
+ }
+
$reader->close();
+
return $collection;
}
- protected function create()
+ public function save($updateIfEquals = [])
{
- return ReaderFactory::create($this->type);
- }
+ if (!$this->model) {
+ return;
+ }
+
+ $headers = false;
+
+ $reader = $this->open();
+
+ $updateIfEquals = array_flip($updateIfEquals);
- protected function parseRows($reader)
- {
- $collection = [];
foreach ($reader->getSheetIterator() as $index => $sheet) {
if ($index !== $this->sheet) {
continue;
}
- foreach ($sheet->getRowIterator() as $row) {
- $collection[] = $this->parser->getData($row);
+
+ foreach ($sheet->getRowIterator() as $rowindex => $row) {
+ if ($rowindex == 1 && $this->hasHeaderRow) {
+ $headers = $row->toArray();
+ } else {
+ $data = $this->parser->transform($row->toArray(), $headers);
+ if ($data !== false) {
+ $relationships = [];
+ $when = array_intersect_key($data, $updateIfEquals);
+ $values = array_diff_key($data, $when);
+
+ foreach ($values as $key => $val) {
+ if (method_exists($this->model, $key)) {
+ unset($values[$key]);
+ $relationships[$key] = $val;
+ }
+ }
+
+ if (!empty($when)) {
+ $this->model->getQuery()->updateOrInsert($when, $values);
+ } else {
+ $this->model->getQuery()->insert($values);
+ }
+
+ if (count($relationships)) {
+ $model = $this->model->where($values)
+ ->orderBy($this->model->getKeyName(), 'desc')
+ ->first();
+ foreach ($relationships as $key => $val) {
+ if (is_array($val)) {
+ $model->{$key}()->createMany($val);
+ } else {
+ $model->{$key}()->associate($val);
+ }
+ }
+ }
+ }
+ }
}
}
- return collect($collection);
+ }
+
+ protected function open()
+ {
+ $reader = $this->createReader();
+ $reader->open($this->path);
+ $this->callbacks->each(function ($elem) use (&$writer) {
+ call_user_func_array(array($writer, $elem[0]), $elem[1]);
+ });
+ return $reader;
}
}
diff --git a/src/Importer/Csv.php b/src/Importer/Csv.php
index f91e380..dc23e4d 100644
--- a/src/Importer/Csv.php
+++ b/src/Importer/Csv.php
@@ -2,6 +2,7 @@
namespace Cyberduck\LaravelExcel\Importer;
use Box\Spout\Common\Type;
+use Box\Spout\Reader\Common\Creator\ReaderEntityFactory;
class Csv extends AbstractSpreadsheet
{
@@ -9,4 +10,9 @@ public function getType()
{
return Type::CSV;
}
+
+ public function createReader()
+ {
+ return ReaderEntityFactory::createCSVReader();
+ }
}
diff --git a/src/Importer/Excel.php b/src/Importer/Excel.php
index b5e51b9..6389825 100644
--- a/src/Importer/Excel.php
+++ b/src/Importer/Excel.php
@@ -2,6 +2,7 @@
namespace Cyberduck\LaravelExcel\Importer;
use Box\Spout\Common\Type;
+use Box\Spout\Reader\Common\Creator\ReaderEntityFactory;
class Excel extends AbstractSpreadsheet
{
@@ -9,4 +10,9 @@ public function getType()
{
return Type::XLSX;
}
+
+ public function createReader()
+ {
+ return ReaderEntityFactory::createXLSXReader();
+ }
}
diff --git a/src/Importer/OpenOffice.php b/src/Importer/OpenOffice.php
index abd2b3e..b936d39 100644
--- a/src/Importer/OpenOffice.php
+++ b/src/Importer/OpenOffice.php
@@ -2,6 +2,7 @@
namespace Cyberduck\LaravelExcel\Importer;
use Box\Spout\Common\Type;
+use Box\Spout\Reader\Common\Creator\ReaderEntityFactory;
class OpenOffice extends AbstractSpreadsheet
{
@@ -9,4 +10,9 @@ public function getType()
{
return Type::ODS;
}
+
+ public function createReader()
+ {
+ return ReaderEntityFactory::createODSReader();
+ }
}
diff --git a/src/Parser/BasicParser.php b/src/Parser/BasicParser.php
index 86824e3..bc179b6 100644
--- a/src/Parser/BasicParser.php
+++ b/src/Parser/BasicParser.php
@@ -1,12 +1,21 @@
toArray();
+ if ($data instanceof Model) {
+ return $data->toArray();
+ } elseif (is_array($data)) {
+ return $data;
+ } else {
+ return get_object_vars($data);
+ }
}
public function getHeaderRow()
diff --git a/tests/TestCase.php b/tests/TestCase.php
new file mode 100644
index 0000000..7514f6e
--- /dev/null
+++ b/tests/TestCase.php
@@ -0,0 +1,61 @@
+ 'A',
+ 'field2' => 'B',
+ 'field3' => 'C',
+ 'field4' => 'D',
+ 'field5' => 'E',
+ 'field6' => 'F',
+ 'field7' => 'G',
+ 'field8' => 'H',
+ 'field9' => 'I',
+ 'field10' => 'J',
+ 'field11' => 'K',
+ 'field12' => 'L',
+ 'field13' => 'M',
+ 'field14' => 'N',
+ 'field15' => 'O',
+ ];
+
+ public function createApplication()
+ {
+ $app = require __DIR__.'/../vendor/laravel/laravel/bootstrap/app.php';
+ $app->register('Cyberduck\LaravelExcel\ExcelServiceProvider');
+
+ $app->make('Illuminate\Contracts\Console\Kernel')->bootstrap();
+
+ return $app;
+ }
+
+ /**
+ * Setup DB before each test.
+ *
+ * @return void
+ */
+ public function setUp() : void
+ {
+ parent::setUp();
+
+ $this->app['config']->set('database.default', 'sqlite');
+ $this->app['config']->set('database.connections.sqlite.database', ':memory:');
+ }
+
+ public function seed($item = 10)
+ {
+ for ($j = 0; $jfloor($item/50)) ? 50 : ($item-($j*50));
+ for ($i = 0; $i<$limit; $i++) {
+ $rows[] = $this->defaultRow;
+ }
+ DB::table('items')->insert($rows);
+ }
+ }
+}
diff --git a/tests/Unit/ExporterTest.php b/tests/Unit/ExporterTest.php
new file mode 100644
index 0000000..4da2c9c
--- /dev/null
+++ b/tests/Unit/ExporterTest.php
@@ -0,0 +1,176 @@
+file = __DIR__.'/../docs/test.xlsx';
+ (new Migration)->up();
+ }
+
+ public function tearDown() : void
+ {
+ (new Migration)->down();
+ parent::tearDown();
+ }
+
+ public function test_can_export_csv()
+ {
+ $itemsToSeed = 2;
+ $this->seed($itemsToSeed);
+
+ //Export the file
+ $exporter = $this->app->make('cyber-duck/exporter')->make('csv');
+ $exporter->load(Item::all())->save(self::FILE);
+
+ //Read the content
+ $lines = 0;
+ $reader = ReaderEntityFactory::createCSVReader();
+ $reader->open($this->file);
+ foreach ($reader->getSheetIterator() as $index => $sheet) {
+ foreach ($sheet->getRowIterator() as $row) {
+ $this->assertEquals(array_values($this->defaultRow), $row->toArray());
+ $lines++;
+ }
+ }
+ $reader->close();
+ $this->assertEquals($itemsToSeed, $lines);
+
+ unlink(self::FILE);
+ }
+
+ public function test_can_export_ods()
+ {
+ $itemsToSeed = 2;
+ $this->seed($itemsToSeed);
+
+ //Export the file
+ $exporter = $this->app->make('cyber-duck/exporter')->make('openoffice');
+ $exporter->load(Item::all())->save(self::FILE);
+
+ //Read the content
+ $lines = 0;
+ $reader = ReaderEntityFactory::createODSReader();
+ $reader->open($this->file);
+ foreach ($reader->getSheetIterator() as $index => $sheet) {
+ foreach ($sheet->getRowIterator() as $row) {
+ $this->assertEquals(array_values($this->defaultRow), $row->toArray());
+ $lines++;
+ }
+ }
+ $reader->close();
+ $this->assertEquals($itemsToSeed, $lines);
+
+ unlink(self::FILE);
+ }
+
+ public function test_can_export_xlsx()
+ {
+ $itemsToSeed = 2;
+ $this->seed($itemsToSeed);
+
+ //Export the file
+ $exporter = $this->app->make('cyber-duck/exporter')->make('excel');
+ $exporter->load(Item::all())->save(self::FILE);
+
+ //Read the content
+ $lines = 0;
+ $reader = ReaderEntityFactory::createXLSXReader();
+ $reader->open($this->file);
+ foreach ($reader->getSheetIterator() as $index => $sheet) {
+ foreach ($sheet->getRowIterator() as $row) {
+ $this->assertEquals(array_values($this->defaultRow), $row->toArray());
+ $lines++;
+ }
+ }
+ $reader->close();
+ $this->assertEquals($itemsToSeed, $lines);
+
+ unlink(self::FILE);
+ }
+
+ public function test_can_use_a_query_builder()
+ {
+ $itemsToSeed = 2;
+ $this->seed($itemsToSeed);
+
+ //Export the file
+ $exporter = $this->app->make('cyber-duck/exporter')->make('csv');
+ $exporter->loadQuery(Item::getQuery())->save(self::FILE);
+
+ //Read the content
+ $lines = 0;
+ $reader = ReaderEntityFactory::createCSVReader();
+ $reader->open($this->file);
+ foreach ($reader->getSheetIterator() as $index => $sheet) {
+ foreach ($sheet->getRowIterator() as $idx => $row) {
+ $expected = array_merge([strval($idx)], array_values($this->defaultRow));
+ $this->assertEquals($expected, $row->toArray());
+ $lines++;
+ }
+ }
+ $reader->close();
+ $this->assertEquals($itemsToSeed, $lines);
+
+ unlink(self::FILE);
+ }
+
+ public function test_can_use_a_query_builder_with_chunk()
+ {
+ $itemsToSeed = 2;
+ $this->seed($itemsToSeed);
+
+ //Export the file
+ $exporter = $this->app->make('cyber-duck/exporter')->make('csv');
+ $exporter->loadQuery(Item::getQuery())->setChunk(2)->save(self::FILE);
+
+ //Read the content
+ $lines = 0;
+ $reader = ReaderEntityFactory::createCSVReader();
+ $reader->open($this->file);
+ foreach ($reader->getSheetIterator() as $index => $sheet) {
+ foreach ($sheet->getRowIterator() as $idx => $row) {
+ $expected = array_merge([strval($idx)], array_values($this->defaultRow));
+ $this->assertEquals($expected, $row->toArray());
+ $lines++;
+ }
+ }
+ $reader->close();
+ $this->assertEquals($itemsToSeed, $lines);
+
+ unlink(self::FILE);
+ }
+
+ public function test_can_use_a_custom_serialiser()
+ {
+ $itemsToSeed = 2;
+ $this->seed($itemsToSeed);
+
+ //Export the file
+ $exporter = $this->app->make('cyber-duck/exporter')->make('csv');
+ $exporter->setSerialiser(new FirstColumnOnlySerialiser())->load(Item::all())->save(self::FILE);
+
+ //Read the content
+ $lines = 0;
+ $reader = ReaderEntityFactory::createCSVReader();
+ $reader->open($this->file);
+ foreach ($reader->getSheetIterator() as $index => $sheet) {
+ foreach ($sheet->getRowIterator() as $row) {
+ if ($lines == 0) {
+ $this->assertEquals(['HEADER'], $row->toArray());
+ } else {
+ $this->assertEquals(['A'], $row->toArray());
+ }
+ $lines++;
+ }
+ }
+ $reader->close();
+
+ unlink(self::FILE);
+ }
+}
diff --git a/tests/Unit/FacadesTest.php b/tests/Unit/FacadesTest.php
new file mode 100644
index 0000000..2ad9024
--- /dev/null
+++ b/tests/Unit/FacadesTest.php
@@ -0,0 +1,16 @@
+assertInstanceOf(
+ \Cyberduck\LaravelExcel\Factory\ExporterFactory::class,
+ Exporter::getFacadeRoot()
+ );
+ $this->assertInstanceOf(
+ \Cyberduck\LaravelExcel\Factory\ImporterFactory::class,
+ Importer::getFacadeRoot()
+ );
+ }
+}
diff --git a/tests/Unit/FactoryTest.php b/tests/Unit/FactoryTest.php
new file mode 100644
index 0000000..55b7ebd
--- /dev/null
+++ b/tests/Unit/FactoryTest.php
@@ -0,0 +1,90 @@
+make('csv');
+ $this->assertInstanceOf(
+ \Cyberduck\LaravelExcel\Importer\Csv::class,
+ $spreadsheet
+ );
+ $this->assertEquals(
+ \Box\Spout\Common\Type::CSV,
+ $spreadsheet->getType()
+ );
+ }
+
+ public function test_factory_can_create_odt()
+ {
+ $factory = new ImporterFactory();
+ $spreadsheet = $factory->make('openoffice');
+ $this->assertInstanceOf(
+ \Cyberduck\LaravelExcel\Importer\OpenOffice::class,
+ $factory->make('openoffice')
+ );
+ $this->assertEquals(
+ \Box\Spout\Common\Type::ODS,
+ $spreadsheet->getType()
+ );
+ }
+
+ public function test_factory_can_create_xls()
+ {
+ $factory = new ImporterFactory();
+ $spreadsheet = $factory->make('excel');
+ $this->assertInstanceOf(
+ \Cyberduck\LaravelExcel\Importer\Excel::class,
+ $factory->make('excel')
+ );
+ $this->assertEquals(
+ \Box\Spout\Common\Type::XLSX,
+ $spreadsheet->getType()
+ );
+ }
+ public function test_exporter_factory_can_create_csv()
+ {
+ $factory = new ExporterFactory();
+ $spreadsheet = $factory->make('csv');
+ $this->assertInstanceOf(
+ \Cyberduck\LaravelExcel\Exporter\Csv::class,
+ $spreadsheet
+ );
+ $this->assertEquals(
+ \Box\Spout\Common\Type::CSV,
+ $spreadsheet->getType()
+ );
+ }
+
+ public function test_exporter_factory_can_create_odt()
+ {
+ $factory = new ExporterFactory();
+ $spreadsheet = $factory->make('openoffice');
+ $this->assertInstanceOf(
+ \Cyberduck\LaravelExcel\Exporter\OpenOffice::class,
+ $spreadsheet
+ );
+ $this->assertEquals(
+ \Box\Spout\Common\Type::ODS,
+ $spreadsheet->getType()
+ );
+ }
+
+ public function test_exporter_factory_can_create_xls()
+ {
+ $factory = new ExporterFactory();
+ $spreadsheet = $factory->make('excel');
+ $this->assertInstanceOf(
+ \Cyberduck\LaravelExcel\Exporter\Excel::class,
+ $spreadsheet
+ );
+ $this->assertEquals(
+ \Box\Spout\Common\Type::XLSX,
+ $spreadsheet->getType()
+ );
+ }
+}
diff --git a/tests/Unit/ImporterTest.php b/tests/Unit/ImporterTest.php
new file mode 100644
index 0000000..72b2e39
--- /dev/null
+++ b/tests/Unit/ImporterTest.php
@@ -0,0 +1,7 @@
+assertTrue($this->app->bound('cyber-duck/exporter'));
+ $this->assertTrue($this->app->bound('cyber-duck/importer'));
+ $this->assertInstanceOf(
+ \Cyberduck\LaravelExcel\Factory\ExporterFactory::class,
+ $this->app->make('cyber-duck/exporter')
+ );
+ $this->assertInstanceOf(
+ \Cyberduck\LaravelExcel\Factory\ImporterFactory::class,
+ $this->app->make('cyber-duck/importer')
+ );
+ //Test aliases
+ $this->assertInstanceOf(
+ \Cyberduck\LaravelExcel\Exporter\AbstractSpreadsheet::class,
+ Exporter::make("Excel")
+ );
+ $this->assertInstanceOf(
+ \Cyberduck\LaravelExcel\Importer\AbstractSpreadsheet::class,
+ Importer::make("Excel")
+ );
+ }
+}
diff --git a/tests/docs/.gitignore b/tests/docs/.gitignore
new file mode 100644
index 0000000..c96a04f
--- /dev/null
+++ b/tests/docs/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
\ No newline at end of file
diff --git a/tests/utils/DatabaseSeeder.php b/tests/utils/DatabaseSeeder.php
new file mode 100644
index 0000000..c5eb6f8
--- /dev/null
+++ b/tests/utils/DatabaseSeeder.php
@@ -0,0 +1,34 @@
+ 'A',
+ 'field2' => 'B',
+ 'field3' => 'C',
+ 'field4' => 'D',
+ 'field5' => 'E',
+ 'field6' => 'F',
+ 'field7' => 'G',
+ 'field8' => 'H',
+ 'field9' => 'I',
+ 'field10' => 'J',
+ 'field11' => 'K',
+ 'field12' => 'L',
+ 'field13' => 'M',
+ 'field14' => 'N',
+ 'field15' => 'O',
+ ];
+ }
+ DB::table('items')->insert($rows);
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/utils/FirstColumnOnlySerialiser.php b/tests/utils/FirstColumnOnlySerialiser.php
new file mode 100644
index 0000000..108a6c1
--- /dev/null
+++ b/tests/utils/FirstColumnOnlySerialiser.php
@@ -0,0 +1,17 @@
+toArray();
+ return [$arrayValues['field1']];
+ }
+
+ public function getHeaderRow()
+ {
+ return ['HEADER'];
+ }
+}
diff --git a/tests/utils/Item.php b/tests/utils/Item.php
new file mode 100644
index 0000000..d52b569
--- /dev/null
+++ b/tests/utils/Item.php
@@ -0,0 +1,8 @@
+increments('id');
+ $table->text('field1');
+ $table->text('field2');
+ $table->text('field3');
+ $table->text('field4');
+ $table->text('field5');
+ $table->text('field6');
+ $table->text('field7');
+ $table->text('field8');
+ $table->text('field9');
+ $table->text('field10');
+ $table->text('field11');
+ $table->text('field12');
+ $table->text('field13');
+ $table->text('field14');
+ $table->text('field15');
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::drop('items');
+ }
+}