diff --git a/composer.json b/composer.json
index 152628506..8b0837fe1 100644
--- a/composer.json
+++ b/composer.json
@@ -25,9 +25,9 @@
}
},
"require": {
- "php": "^7.4|^8.0",
+ "php": "^7.4|^8",
"livewire/livewire": "^2.4",
- "shuchkin/simplexlsxgen": "^0.9.25"
+ "box/spout": "^3.2"
},
"require-dev": {
"phpunit/phpunit": "^9.5"
diff --git a/resources/views/tailwind/2/header.blade.php b/resources/views/tailwind/2/header.blade.php
index 643b3c033..1a20a510f 100644
--- a/resources/views/tailwind/2/header.blade.php
+++ b/resources/views/tailwind/2/header.blade.php
@@ -28,6 +28,7 @@ class="block px-4 py-2 text-gray-800 hover:bg-gray-100 hover:text-black-200">Exc
Csv
+
diff --git a/src/PowerGridComponent.php b/src/PowerGridComponent.php
index 0d029c214..3abc2857a 100644
--- a/src/PowerGridComponent.php
+++ b/src/PowerGridComponent.php
@@ -5,8 +5,8 @@
use Livewire\Component;
use Livewire\WithPagination;
use PowerComponents\LivewirePowerGrid\Helpers\Collection;
-use PowerComponents\LivewirePowerGrid\Services\ExportToCsv;
-use PowerComponents\LivewirePowerGrid\Services\ExportToXLS;
+use PowerComponents\LivewirePowerGrid\Services\Spout\ExportToCsv;
+use PowerComponents\LivewirePowerGrid\Services\Spout\ExportToXLS;
use PowerComponents\LivewirePowerGrid\Traits\Checkbox;
use PowerComponents\LivewirePowerGrid\Traits\Filter;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
@@ -330,6 +330,7 @@ public function exportToExcel(): BinaryFileResponse
->fromCollection($this->columns(), $this->collection())
->withCheckedRows(array_merge($this->checkbox_values, $this->filtered))
->download();
+
}
/**
diff --git a/src/Services/Export.php b/src/Services/Export.php
index 96319edb3..af83dff21 100644
--- a/src/Services/Export.php
+++ b/src/Services/Export.php
@@ -13,29 +13,48 @@ class Export
public array $columns;
public array $checked_values;
+ public function fileName(string $name): Export
+ {
+ $this->fileName = $name;
+ return $this;
+ }
+
+ public function fromCollection(array $columns, Collection $collection): Export
+ {
+ $this->columns = $columns;
+ $this->collection = $collection;
+ return $this;
+ }
+
+ public function withCheckedRows($checked_values): Export
+ {
+ $this->checked_values = $checked_values;
+ return $this;
+ }
+
/**
* @throws Exception
*/
public function prepare(Collection $collection, array $columns, array $checkedValues): array
{
- $header = [];
- $title = collect();
+
+ $header = collect();
if (count($checkedValues)) {
$collection = $collection->whereIn('id', $checkedValues);
}
- $collection = $collection->map(function ($row) use ($columns, $title) {
+ $collection = $collection->map(function ($row) use ($columns, $header) {
$item = collect();
- collect($columns)->each(function ($column) use ($row, $title, $item) {
+ collect($columns)->each(function ($column) use ($row, $header, $item) {
if ($column->hidden === false && $column->visible_in_export === true) {
foreach ($row as $key => $value) {
if ($key === $column->field) {
$item->put($column->title, $value);
}
}
- if (!$title->contains($column->title)) {
- $title->push($column->title);
+ if (!$header->contains($column->title)) {
+ $header->push($column->title);
}
}
@@ -43,29 +62,10 @@ public function prepare(Collection $collection, array $columns, array $checkedVa
return $item->toArray();
});
- $header[] = $title->toArray();
-
- return array_merge($header, $collection->toArray());
+ return [
+ 'headers' => $header->toArray(),
+ 'rows' => $collection->toArray()
+ ];
}
- public function fileName(string $name): Export
- {
- $this->fileName = $name;
- return $this;
- }
-
- public function fromCollection(array $columns, Collection $collection): Export
- {
- $this->columns = $columns;
- $this->collection = $collection;
- return $this;
- }
-
- public function withCheckedRows($checked_values): Export
- {
- $this->checked_values = $checked_values;
- return $this;
- }
-
-
}
diff --git a/src/Services/ExportToCsv.php b/src/Services/ExportToCsv.php
deleted file mode 100644
index 155e242c5..000000000
--- a/src/Services/ExportToCsv.php
+++ /dev/null
@@ -1,34 +0,0 @@
-put($this->fileName . '.csv', $this->build());
-
- return response()
- ->download(storage_path("app/public/" . $this->fileName . '.csv'));
-
- }
-
- public function build()
- {
- $data = $this->prepare($this->collection, $this->columns, $this->checked_values);
-
- $f = fopen('php://memory', 'w');
- foreach ($data as $line) {
- fputcsv($f, $line, ";");
- }
- return $f;
- }
-}
diff --git a/src/Services/ExportToXLS.php b/src/Services/ExportToXLS.php
deleted file mode 100644
index 718c03b1e..000000000
--- a/src/Services/ExportToXLS.php
+++ /dev/null
@@ -1,34 +0,0 @@
-put($this->fileName . '.xlsx', $this->build());
-
- return response()
- ->download(storage_path("app/public/" . $this->fileName . '.xlsx'));
- }
-
- public function build()
- {
- $data = $this->prepare($this->collection, $this->columns, $this->checked_values);
- return \SimpleXLSXGen::fromArray($data, $this->fileName);
- }
-
-}
diff --git a/src/Services/Spout/ExportToCsv.php b/src/Services/Spout/ExportToCsv.php
new file mode 100644
index 000000000..3edb74898
--- /dev/null
+++ b/src/Services/Spout/ExportToCsv.php
@@ -0,0 +1,46 @@
+build();
+
+ return response()
+ ->download(storage_path($this->fileName . '.csv'));
+
+ }
+
+ public function build()
+ {
+
+ $data = $this->prepare($this->collection, $this->columns, $this->checked_values);
+
+ $writer = WriterEntityFactory::createCSVWriter();
+ $writer->openToFile(storage_path($this->fileName . '.csv'));
+
+ $row = WriterEntityFactory::createRowFromArray($data['headers']);
+
+ $writer->addRow($row);
+
+ foreach ($data['rows'] as $row) {
+ $row = WriterEntityFactory::createRowFromArray($row);
+ $writer->addRow($row);
+ }
+
+ $writer->close();
+
+ }
+}
diff --git a/src/Services/Spout/ExportToXLS.php b/src/Services/Spout/ExportToXLS.php
new file mode 100644
index 000000000..4bb410b5a
--- /dev/null
+++ b/src/Services/Spout/ExportToXLS.php
@@ -0,0 +1,53 @@
+build();
+
+ return response()
+ ->download(storage_path($this->fileName . '.xlsx'));
+
+ }
+
+ public function build()
+ {
+ $data = $this->prepare($this->collection, $this->columns, $this->checked_values);
+
+ $writer = WriterEntityFactory::createXLSXWriter();
+ $writer->openToFile(storage_path($this->fileName . '.xlsx'));
+
+ $style = (new StyleBuilder())
+ ->setFontBold()
+ ->setFontColor(Color::BLACK)
+ ->setShouldWrapText(false)
+ ->setCellAlignment(CellAlignment::CENTER)
+ ->setBackgroundColor('d0d3d8')
+ ->build();
+
+ $row = WriterEntityFactory::createRowFromArray($data['headers'], $style);
+
+ $writer->addRow($row);
+
+ foreach ($data['rows'] as $row) {
+ $row = WriterEntityFactory::createRowFromArray($row);
+ $writer->addRow($row);
+ }
+
+ $writer->close();
+
+ }
+}
diff --git a/src/Traits/Filter.php b/src/Traits/Filter.php
index 327a2cd1a..0716096eb 100644
--- a/src/Traits/Filter.php
+++ b/src/Traits/Filter.php
@@ -11,10 +11,10 @@ trait Filter
public Collection $make_filters;
public array $filters = [];
public array $filters_enabled = [];
- private string $format_date = '';
public array $select = [];
+ private string $format_date = '';
- public function clearFilter( $field = '' )
+ public function clearFilter($field = '')
{
$this->search = '';
unset($this->filters_enabled[$field]);
@@ -40,7 +40,7 @@ private function renderFilter()
}
- private function advancedFilter( Collection $collection ): Collection
+ private function advancedFilter(Collection $collection): Collection
{
foreach ($this->filters as $key => $type) {
@@ -51,93 +51,23 @@ private function advancedFilter( Collection $collection ): Collection
switch ($key) {
case 'date_picker':
- if (isset($value[0]) && isset($value[1])) {
- $collection = $collection->whereBetween($field, [Carbon::parse($value[0]), Carbon::parse($value[1])]);
- }
- break;
-
+ $collection = $this->usingDatePicker($collection, $field, $value);
+ break;
case 'multi_select':
- if (count(collect($value)->get('values'))) {
- $collection = $collection->whereIn($field, collect($value)->get('values'));
- }
- break;
-
+ $collection = $this->usingMultiSelect($collection, $field, $value);
+ break;
case 'select':
- $collection = $collection->where($field, $value);
- break;
-
+ $collection = $this->usingSelect($collection, $field, $value);
+ break;
case 'boolean':
-
- if ($value != "all") {
- $value = ($value == "true");
- $collection = $collection->where($field, '=', $value);
- }
- break;
-
+ $collection = $this->usingBoolean($collection, $field, $value);
+ break;
case 'input_text':
-
- $textFieldOperator = ( $this->validatenputTextOptions($field) ? strtolower($this->filters['input_text_options'][$field]) : 'contains');
-
- if ($textFieldOperator == 'is') {
- $collection = $collection->where($field, '=', $value);
- }
-
- if ($textFieldOperator == 'is_not') {
- $collection = $collection->where($field, '!=', $value);
- }
-
- if ($textFieldOperator == 'starts_with') {
- $collection = $collection->filter(function ($row) use ($field, $value) {
- return Str::startsWith(Str::lower( $row->$field), Str::lower($value));
- //return preg_match("#^{$value}(.*)$#i", $row->$field);
- });
- }
-
- if ($textFieldOperator == 'ends_with') {
- $collection = $collection->filter(function ($row) use ($field, $value) {
- return Str::endsWith(Str::lower($row->$field), Str::lower($value));
-
- });
- }
-
- if ($textFieldOperator == 'contains') {
- $collection = $collection->filter(function ($row) use ($field, $value) {
- return false !== stristr($row->$field, strtolower($value));
- });
- }
-
- if ($textFieldOperator == 'contains_not') {
- $collection = $collection->filter(function ($row) use ($field, $value) {
- return !Str::Contains(Str::lower($row->$field), Str::lower($value));
- //return (!preg_match("#(.*?)(?i)({$value})(.*?)#", $row->$field));
- });
- }
- break;
-
+ $collection = $this->usingInputText($collection, $field, $value);
+ break;
case 'number':
-
- if (isset($value['start']) && !isset($value['end'])) {
- $start = str_replace($value['thousands'], '', $value['start']);
- $start = (float)str_replace($value['decimal'], '.', $start);
-
- $collection = $collection->where($field, '>=', $start);
- }
- if (!isset($value['start']) && isset($value['end'])) {
- $end = str_replace($value['thousands'], '', $value['end']);
- $end = (float)str_replace($value['decimal'], '.', $end);
-
- $collection = $collection->where($field, '<=', $end);
- }
- if (isset($value['start']) && isset($value['end'])) {
- $start = str_replace($value['thousands'], '', $value['start']);
- $start = str_replace($value['decimal'], '.', $start);
-
- $end = str_replace($value['thousands'], '', $value['end']);
- $end = str_replace($value['decimal'], '.', $end);
-
- $collection = $collection->whereBetween($field, [$start, $end]);
- }
- break;
+ $collection = $this->usingNumber($collection, $field, $value);
+ break;
}
}
}
@@ -148,7 +78,7 @@ private function advancedFilter( Collection $collection ): Collection
/**
* @param $data
*/
- public function eventChangeDatePiker(array $data ): void
+ public function eventChangeDatePiker(array $data): void
{
$input = explode('.', $data['values']);
$this->filters['date_picker'][$input[2]] = $data['selectedDates'];
@@ -157,7 +87,7 @@ public function eventChangeDatePiker(array $data ): void
/**
* @param $data
*/
- public function eventMultiSelect(array $data )
+ public function eventMultiSelect(array $data)
{
$this->filters['multi_select'][$data['id']] = $data;
}
@@ -168,7 +98,7 @@ public function eventMultiSelect(array $data )
* @param string $thousands
* @param string $decimal
*/
- public function filterNumberStart( string $field, string $value, string $thousands, string $decimal ): void
+ public function filterNumberStart(string $field, string $value, string $thousands, string $decimal): void
{
$this->filters['number'][$field]['start'] = $value;
$this->filters['number'][$field]['thousands'] = $thousands;
@@ -181,7 +111,7 @@ public function filterNumberStart( string $field, string $value, string $thousan
* @param string $thousands
* @param string $decimal
*/
- public function filterNumberEnd( string $field, string $value, string $thousands, string $decimal ): void
+ public function filterNumberEnd(string $field, string $value, string $thousands, string $decimal): void
{
$this->filters['number'][$field]['end'] = $value;
$this->filters['number'][$field]['thousands'] = $thousands;
@@ -192,7 +122,7 @@ public function filterNumberEnd( string $field, string $value, string $thousands
* @param string $field
* @param string $value
*/
- public function filterInputText( string $field, string $value ): void
+ public function filterInputText(string $field, string $value): void
{
$this->filters['input_text'][$field] = $value;
}
@@ -218,12 +148,146 @@ public function filterInputTextOptions(string $field, string $value): void
/**
* Validate if the given value is valid as an Input Option
*
- * @param string $field Field to be checked
- * @return void
+ * @param string $field Field to be checked
+ * @return bool
+ */
+ private function validateInputTextOptions(string $field)
+ {
+
+ return isset($this->filters['input_text_options'][$field]) && in_array(strtolower($this->filters['input_text_options'][$field]),
+ ['is', 'is_not', 'contains', 'contains_not', 'starts_with', 'ends_with']);
+
+ }
+
+ /**
+ * @param Collection $collection
+ * @param string $field
+ * @param $value
+ * @return Collection
+ */
+ private function usingDatePicker(Collection $collection, string $field, $value): Collection
+ {
+ if (isset($value[0]) && isset($value[1])) {
+ $collection = $collection->whereBetween($field, [Carbon::parse($value[0]), Carbon::parse($value[1])]);
+ }
+ return $collection;
+ }
+
+ /**
+ * @param Collection $collection
+ * @param string $field
+ * @param $value
+ * @return Collection
*/
- private function validatenputTextOptions(string $field) {
+ private function usingInputText(Collection $collection, string $field, $value): Collection
+ {
+
+ $textFieldOperator = ($this->validateInputTextOptions($field) ? strtolower($this->filters['input_text_options'][$field]) : 'contains');
- return isset($this->filters['input_text_options'][$field]) && in_array(strtolower($this->filters['input_text_options'][$field]), ['is', 'is_not', 'contains', 'contains_not', 'starts_with', 'ends_with']);
+ if ($textFieldOperator == 'is') {
+ return $collection->where($field, '=', $value);
+ }
+
+ if ($textFieldOperator == 'is_not') {
+ return $collection->where($field, '!=', $value);
+ }
+
+ if ($textFieldOperator == 'starts_with') {
+ return $collection->filter(function ($row) use ($field, $value) {
+ return Str::startsWith(Str::lower($row->$field), Str::lower($value));
+ });
+ }
+ if ($textFieldOperator == 'ends_with') {
+ return $collection->filter(function ($row) use ($field, $value) {
+ return Str::endsWith(Str::lower($row->$field), Str::lower($value));
+
+ });
+ }
+
+ if ($textFieldOperator == 'contains') {
+ return $collection->filter(function ($row) use ($field, $value) {
+ return false !== stristr($row->$field, strtolower($value));
+ });
+ }
+
+ if ($textFieldOperator == 'contains_not') {
+ return $collection->filter(function ($row) use ($field, $value) {
+ return !Str::Contains(Str::lower($row->$field), Str::lower($value));
+ });
+ }
+ return $collection;
+ }
+
+ /**
+ * @param Collection $collection
+ * @param string $field
+ * @param $value
+ * @return Collection
+ */
+ private function usingBoolean(Collection $collection, string $field, $value): Collection
+ {
+ if ($value != "all") {
+ $value = ($value == "true");
+ return $collection->where($field, '=', $value);
+ }
+ return $collection;
+ }
+
+ /**
+ * @param Collection $collection
+ * @param string $field
+ * @param $value
+ * @return Collection
+ */
+ private function usingSelect(Collection $collection, string $field, $value): Collection
+ {
+ return $collection->where($field, $value);
+ }
+
+ /**
+ * @param Collection $collection
+ * @param string $field
+ * @param $value
+ * @return Collection
+ */
+ private function usingMultiSelect(Collection $collection, string $field, $value): Collection
+ {
+ if (count(collect($value)->get('values'))) {
+ return $collection->whereIn($field, collect($value)->get('values'));
+ }
+ return $collection;
+ }
+
+ /**
+ * @param Collection $collection
+ * @param string $field
+ * @param $value
+ * @return Collection
+ */
+ private function usingNumber(Collection $collection, string $field, $value): Collection
+ {
+ if (isset($value['start']) && !isset($value['end'])) {
+ $start = str_replace($value['thousands'], '', $value['start']);
+ $start = (float)str_replace($value['decimal'], '.', $start);
+
+ return $collection->where($field, '>=', $start);
+ }
+ if (!isset($value['start']) && isset($value['end'])) {
+ $end = str_replace($value['thousands'], '', $value['end']);
+ $end = (float)str_replace($value['decimal'], '.', $end);
+
+ return $collection->where($field, '<=', $end);
+ }
+ if (isset($value['start']) && isset($value['end'])) {
+ $start = str_replace($value['thousands'], '', $value['start']);
+ $start = str_replace($value['decimal'], '.', $start);
+
+ $end = str_replace($value['thousands'], '', $value['end']);
+ $end = str_replace($value['decimal'], '.', $end);
+
+ return $collection->whereBetween($field, [$start, $end]);
+ }
+ return $collection;
}
}