DcatAdmin 配合 `maatwebsite/excel` 擴充套件 在後臺增加 excel 匯出的功能,並可匯出圖片

laravel_peng發表於2022-03-22

1. 準備

1.1 環境

  1. Laravel 版本:Laravel Framework 8.77.1
  2. PHP 版本:PHP 8.0.6 (cli)

1.2 擴充套件包

  1. dcatAdmin 的擴充套件,文件連結:傳送

    composer require dcat/laravel-admin
  2. maatwebsite/exce 的擴充套件,文件連結:傳送

    composer require maatwebsite/excel

2. 程式碼

2.1 新增GridTool檔案

  1. 新增 dcatAdmin 的 GridTool 檔案

    php artisan admin:action
  2. 選擇 [3] grid-tool

    Which type of action would you like to make?:
    ...
    [3] grid-tool
    ...
  3. 設定 grid-tool 的檔名

    InspectionItemsPostExportTool
  4. InspectionItemsPostExportTool 檔案內容主要的方法:

    ...
     /**
      *  接收引數 * InspectionItemsPost constructor
      * @param null $filename
      * @param $title
      */
     public function __construct($filename = null, $title = '')
     {
         parent::__construct($title);
         $this->title = $title;
     }
    
     /**
      * @return string
      */
     protected $title = '匯出巡檢資訊';
    
     /**
      *  按鈕的樣式 * @var string
      */
     protected $style = 'btn btn-outline-info';
    
     /**
      *  業務處理 * @param Request $request
      * @return Response
      */
     public function handle(Request $request)
     {
         // 獲取檔名
         $filename = $request->get('filename');
         // 這裡有一個 admin_route 路由,接下來在 route.php 檔案新增
         return $this->response()->download(admin_route('inspection-item-posts.export'[
             'filename' => $filename,
         ]);
     }
     ...

2.2 新增控制器方法

  1. 控制器增加 export() 方法

    ...
     /**
      *  巡檢記錄資料的匯出
      * @param Request $request
      * @return BinaryFileResponse
      */
     public function export(Request $request)
     {
         $filename = $request->get('filename');
         ob_end_clean();
         // 這裡面有一個 InspectionItemPostExport 檔案,接下來通過 php artisan make:export 命令建立
         return Excel::download(new InspectionItemPostExport(), $filename . '.xlsx');
     }
    ...
  2. 新增控制器路由:

     // 記著:單個方法的路由一定要放到 resource 資源路由前面
     $router->get('inspection-item-posts/export', 'InspectionItemPostController@export')->name('inspection-item-posts.export');
  3. 在控制器的 grid 方法中引入這個 tool 按鈕檔案

    /**
      * Make a grid builder.
      *
      * @return Grid
      */
     protected function grid()
     {
         return Grid::make(new InspectionItemPost(['productionLine', 'inspectionPoint', 'inspectionItem', 'user']), function (Grid $grid) {
             $grid->column('id')->sortable();
             // 引入匯出工具按鈕
             $grid->tools(function (Grid\Tools $tools) use ($grid) {
                 // 匯出
                 $tools->append(new InspectionItemsPostExportTool('巡檢問題資訊', '匯出巡檢問題資訊'));
             });
         });
     }

2.3 建立匯出檔案

  1. 建立 export 檔案

    php artisan make:export InspectionItemPostExport
  2. InspectionItemPostExport 檔案的方法

    // 我這裡實現了幾個介面
    // FromCollection 必須實現 collection() 方法
    // ShouldAutoSize 不需要實現介面,自動設定 excel 表格 column 的寬度
    // WithDrawings 必須實現 drawings() 方法,可以在 excel 表格中新增圖片(圖片需是本地地址)
    // WithColumnWidths 必須實現 columnWidths() 可以設定對應列的寬,可與 ShouldAutoSize 一起使用,不過本設定優先
    class InspectionItemPostExport implements FromCollection, ShouldAutoSize, WithDrawings, WithColumnWidths
    {
         // 最總資料
         private $data;
         // 圖片資料
         private $imageData;
    
         /**
         *  構造方法
         * InspectionItemPostExport constructor.
         */
         public function __construct()
         {
             // 表頭設定
             $this->data = $this->createData();
         }
    
         /**
          *  陣列轉集合 
          * @return Collection
          */
         public function collection()
         {
              return new Collection($this->data);
         }
    
         /**
          *  業務程式碼 
          * @return array|string[][]
           */
         public function createData()
         {
             $headTitle = [
                 '編號',
                 '提交型別',
                 '生產線',
                 '巡檢點',
                 '觀察項',
                 '巡檢人',
                 '緊急狀態',
                 '問題圖片',
                 '問題說明',
                 '建立時間',
             ];
             $bodyData = [];
             $data = InspectionItemPost::with('productionLine:id,name')
                 ->with('inspectionPoint:id,name')
                 ->with('inspectionItem:id,name')
                 ->with('user:id,name')
                 ->get();
             if (empty($data)) {
                 return [$headTitle];
             }
             // 資料迴圈
             foreach ($data as $k => $item) {
                 $arr[0] = $item->id;
                 $arr[1] = Arr::get(InspectionItemPostRepositories::TYPE_OPTION, $item->type, '無');
                 $arr[2] = $item->productionLine->name ?? '';
                 $arr[3] = $item->inspectionPoint->name ?? '';
                 $arr[4] = $item->inspectionItem->name ?? '';
                 $arr[5] = $item->user->name ?? '';
                 $arr[6] = Arr::get(InspectionItemPostRepositories::STATUS_OPTION, $item->status, '無');
                 $arr[7] = '';    // 這裡設定為空為後續新增圖片騰出地方
                 $this->imageData[] = $url;
                 $arr[8] = $item->remark;
                 $arr[9] = $item->created_at;
                 $bodyData[] = $arr;
             }
             // 清除掉 $arr
             unset($arr);
             return [$headTitle, $bodyData];
         }
    
         /**
          *  繪畫 * @return array|BaseDrawing|BaseDrawing[]
           */
         public function drawings()
         {
             $result = [];
             foreach ($this->imageData as $k => $v) {
                 // 如果存在全連線跳出
                 if (strpos($v, 'http') === 0 || strpos($v, 'https') === 0) {
                     continue;
                 }
                 // 如果圖片不存在跳出
                 if (!Storage::exists($v)) {
                     continue;
                 }
                 $k += 2;
                 ${'drawing' . $k} = new Drawing();
                 ${'drawing' . $k}->setName('問題圖片');
                 ${'drawing' . $k}->setDescription('問題圖片');
                 //圖片路徑
                 ${'drawing' . $k}->setPath(Storage::path($v));
                 ${'drawing' . $k}->setHeight(50);
                 //設定圖片列
                 ${'drawing' . $k}->setCoordinates('H' . $k);
                 $result[] = ${'drawing' . $k};
             }
             return $result;
         }
    
         /**
          *  列寬限制 * @return int[]
          */
         public function columnWidths(): array
         {
             return [
                 'A' => 10,
                 'B' => 15,
                 'C' => 15,
                 'D' => 15,
                 'E' => 40,
                 'F' => 10,
                 'G' => 10,
                 'H' => 20,
                 'I' => 30,
                 'J' => 20,
             ];
         }
    }
本作品採用《CC 協議》,轉載必須註明作者和本文連結
Xiao Peng

相關文章