• Как выгрузить в laravel nova данные в exel?

    @jouu Автор вопроса
    кот экшина
    <?php
    namespace App\Nova\Actions;
    use Illuminate\Bus\Queueable;
    use Illuminate\Support\Facades\Hash;
    use Laravel\Nova\Actions\Action;
    use Illuminate\Support\Collection;
    use Laravel\Nova\Fields\ActionFields;
    use Illuminate\Queue\SerializesModels;
    use Illuminate\Queue\InteractsWithQueue;
    use Illuminate\Contracts\Queue\ShouldQueue;
    use Laravel\Nova\Fields\Boolean;
    use Laravel\Nova\Fields\Text;
    
    class  DownloadExcel extends Action
    {
        use InteractsWithQueue, Queueable, SerializesModels;
    
        private $columns;
        private $default_name;
        private $dates;
        private $foreign;
        private $enums;
        private $borders;
    
        public $name = 'Экспорт в Excel';
    
        public function __construct($columns, $default_name = null, $dates = [], $foreign = [], $enums = [], $borders = false)
        {
            $this->columns = $columns;
            $this->default_name = $default_name;
            $this->dates = $dates;
            $this->foreign = $foreign;
            $this->enums = $enums;
            $this->borders = $borders;
        }
    
        /**
         * Perform the action on the given models.
         *
         * @param  \Laravel\Nova\Fields\ActionFields  $fields
         * @param  \Illuminate\Support\Collection  $models
         * @return mixed
         */
        public function handle(ActionFields $fields, Collection $models)
        {
            $attrs = $fields->getAttributes();
            unset($attrs['file_name']);
    
            $l = 'A';
            $columns = [];
            foreach ($attrs as $column => $value) {
                if ($value) {
                    if (in_array($column, $this->dates))
                        $type = 'date';
                    elseif (in_array($column, array_keys($this->foreign)))
                        $type = 'foreign';
                    elseif (in_array($column, array_keys($this->enums)))
                        $type = 'enum';
                    else
                        $type = 'string';
                    $columns[$l++] = [
                        'name' => $column,
                        'type' => $type,
                    ];
                }
            }
            $array = [];
            foreach ($models as $i => $model) {
                $t = [];
                foreach ($columns as $l => $column) {
                    $value = '';
                    switch ($column['type']) {
                        case 'date':
                            if ($model->{$column['name']}) {
                                $value = \PhpOffice\PhpSpreadsheet\Shared\Date::PHPToExcel($model->{$column['name']});
                            }
                            break;
                        case 'foreign':
                            if (is_array($this->foreign[$column['name']])) {
                                if (isset($model->{$this->foreign[$column['name']][0]}))
                                    $value = $model->{$this->foreign[$column['name']][0]}->{$this->foreign[$column['name']][1]};
                            } elseif (isset($model->{$column['name']}))
                                $value = $model->{$column['name']}->{$this->foreign[$column['name']]};
                            break;
                        case 'enum':
                            if (isset($model->{$column['name']}))
                                $value = $this->enums[$column['name']][$model->{$column['name']}];
                            break;
                        default:
                            $value = $model->{$column['name']} ?? '';
                            break;
                    }
    
                    $t[$l] = $value;
                }
                $array[] = $t;
            }
            return $array;
        }
    
        public function handleResult(ActionFields $fields, $results)
        {
            $spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
            try {
                $spreadsheet->setActiveSheetIndex(0);
            } catch(\PhpOffice\PhpSpreadsheet\Exception $e) {
                return Action::danger('Произошла ошибка, обратитесь а администратору.');
            }
    
            $attrs = $fields->getAttributes();
            $file_name = $attrs['file_name'];
            unset($attrs['file_name']);
            $l = 'A';
            $columns = [];
    
            try {
                $active_sheet = $spreadsheet->getActiveSheet();
            } catch(\PhpOffice\PhpSpreadsheet\Exception $e) {
                return Action::danger('Произошла ошибка, обратитесь а администратору.');
            }
    
            foreach ($attrs as $column => $value) {
                if ($value) {
                    $active_sheet->setCellValue($l . '1', $this->columns[$column]);
                    $active_sheet->getColumnDimension($l)->setAutoSize(true);
                    if (in_array($column, $this->dates))
                        $type = 'date';
                    elseif (in_array($column, array_keys($this->foreign)))
                        $type = 'foreign';
                    elseif (in_array($column, array_keys($this->enums)))
                        $type = 'enum';
                    else
                        $type = 'string';
                    $columns[$l++] = [
                        'name' => $column,
                        'type' => $type,
                    ];
                }
            }
            $i = 2;
            foreach ($results as $result)
                foreach ($result as $r) {
                    foreach ($columns as $l => $column) {
                        if ($column['type'] === 'date') {
                            $active_sheet->getStyle($l . $i)
                                ->getNumberFormat()->setFormatCode('dd.mm.YYYY');
                        }
    
                        $active_sheet->setCellValue($l . $i, $r[$l]);
                    }
                    $i++;
                }
    
            if ($this->borders) {
                $styleArray = ['borders' => ['allBorders' => ['borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN]]];
                $active_sheet->getStyle('A1:' . --$l . ($i - 1))->applyFromArray($styleArray);
            }
    
    
            $fn = \Auth::user()->id . '-' . $file_name;//Hash::make($file_name);
            try {
                $writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, "Xlsx");
                $writer->save(storage_path("app/public/excel_tmp/$fn.xlsx"));
            } catch(\PhpOffice\PhpSpreadsheet\Exception $e) {
                return Action::danger('Произошла ошибка, обратитесь а администратору.');
            }
    
            return Action::download(
                url('/download_excel?') . http_build_query([
                    'path'     => storage_path("app/public/excel_tmp/"),
                    'filename' => "$fn.xlsx",
                    'ffn' => "$file_name.xlsx",
                ]),
                "$file_name.xlsx"
            );
        }
    
        public function fields()
        {
            $fields = [Text::make('Имя файла', 'file_name')->withMeta(["value" => $this->default_name])];
            foreach ($this->columns as $name => $caption) {
                $fields[] = Boolean::make($caption, $name)->withMeta(["value" => "true"]);
            }
            return $fields;
        }
    }