fastadmin的匯出到excel功能

悦~發表於2024-06-21

正常的excel匯出沒什麼問題,最近一直頭疼的是怎麼匯出資料中包含圖片,並且圖片還是陣列?????by user 悅悅 https://www.cnblogs.com/nuanai

1、匯出的excel佈局是圖片分行顯示

2、匯出圖片路徑,並且已另外的文字設定超連結

3、其他行合併(這個還沒有想好怎麼設定合併後賦值)

使用的框架是fastadmin,就要引入必要的PhpOffice包,不必介紹,其中使用到了匯出excel的檔案、超連結檔案、單元格樣式檔案 by user 悅悅 https://www.cnblogs.com/nuanai

1 use PhpOffice\PhpSpreadsheet\Spreadsheet;
2 use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
3 use PhpOffice\PhpSpreadsheet\Writer\Xls;
4 
5 use PhpOffice\PhpSpreadsheet\Cell\Hyperlink;
6 use PhpOffice\PhpSpreadsheet\Style\Alignment;

使用sql語句將資料庫需要匯出的資料進行查詢成結果集,正常的查詢語句不做過多介紹(控制器命名不做過多介紹,懂得都懂哈)

這裡使用的連表查詢,查詢出需要匯出的欄位;有時間欄位的,如果資料庫中存的是時間戳,需要進行格式化後賦值 by user 悅悅 https://www.cnblogs.com/nuanai

 1 $dataList = Db::name('inspection_project_site')
 2             ->alias('site')
 3             ->field('staff.staff_name,asite.code,asite.code,site_name,site.latlng,site.check_lnglat,site.checktime,site.images')
 4             ->join('inspection_staff staff','staff.id = site.staff_id','LEFT')
 5             ->join('inspection_area_site asite','asite.id = site.area_site_id','LEFT')
 6             ->where('status',1)
 7             ->order(['site.checktime'=>'desc'])
 8             ->select();
 9             
10 foreach ($dataList as $k => &$v)
11 {
12     $v['checktime'] = isset($v['checktime']) ? date('Y-m-d H:i:s',$v['checktime']) : "";
13 }

需要匯出的欄位已經有了,那麼下面就是進行excel的工程,想要匯出excel就要使用到上面引入的PHPoffice包

設定匯出excel表的檔名稱、表頭名稱和單元格大小等樣式,可以使用資料庫欄位,也可以自己先設定好,我這邊是提前設定好的 by user 悅悅 https://www.cnblogs.com/nuanai

 1 $filename = '巡檢記錄';
 2 $spreadsheet = new Spreadsheet();
 3 $worksheet = $spreadsheet->getActiveSheet();
 4 
 5 $title = ['巡檢員','巡檢點編號','巡檢點名稱','巡檢經緯度','打卡經緯度','打卡時間','打卡圖片'];
 6 $cell_width = [15,10,25,20,20,20,25,30,10,10,30,10,20,10,10,10,10,20,20,20,20,20,20,20,15,15,10];
 7 
 8 $titCol = 'A';// 表頭單元格內容 第一行
 9         
10 foreach ($title as $k=>$value) {
11     // 單元格內容寫入
12     $worksheet->setCellValue($titCol . '1', $value);
13     if (isset($cell_width[$k])){
14         $worksheet->getColumnDimension($titCol)->setWidth($cell_width[$k]);
15     }
16     $titCol++;
17 }
18         
19 $styleArray = [
20     'font' => [
21         'bold' => true
22     ],
23     'alignment' => [
24         'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER,
25     ],
26 ];
27 //設定單元格樣式
28 $worksheet->getStyle('A1:V1')->applyFromArray($styleArray)->getFont()->setSize(12);        

配置好基本要素後,就是資料內容的寫入了,這邊圖片的欄位是用“逗號”進行拼接的字串,所以當寫入excel中時,需要判斷圖片欄位進行逗號拆分為陣列,然後分條寫入excel表中 by user 悅悅 https://www.cnblogs.com/nuanai

讓我比較頭疼的是,之前的迴圈寫入有點錯誤,大家一定要注意,迴圈的順序。錯誤是圖片寫入後,又被下一條的資料給覆蓋了,所以一定要計算好圖片需要用到多少行,並且下一條寫入時要圖片的行數+1才不會覆蓋上一條的圖片

1 $maxImageCount = !empty($dataRow['images']) ? count(explode(',', $dataRow['images'])) : 1;   //這是判斷圖片欄位是否為空,下面會在合併時用到
1 //這是超連結的名稱顯示,不想直接顯示路徑顯示另外的名稱
2 $hyperlinkText = "打卡圖" . ($index + 1); 
3 //先寫入再這是值為超連結
4 $worksheet->setCellValue($cellCoordinate, $hyperlinkText);
5 // 設定超連結
6 $worksheet->getCell($cellCoordinate)->getHyperlink()->setUrl(trim($image));
1 //除了圖片單元格外,其他的單元格列合併圖片所佔的行數
2 $worksheet->mergeCells($colIndex . $rowIndex . ':' . $colIndex . ($rowIndex + $maxImageCount - 1));

上面是設定超連結和合並的編寫內容,下面進行迴圈寫入excel,需要注意的是要在結果集的foreach外設定開始的行數,裡面進行設定開始的列;然後進行結果集的迴圈判斷圖片欄位,並且迴圈完後才能進行行數追加

 1 $rowIndex = 2;
 2 foreach ($dataList as $dataRow) {
 3     $colIndex = 'A';
 4     $maxImageCount = !empty($dataRow['images']) ? count(explode(',', $dataRow['images'])) : 1;
 5     
 6     foreach ($dataRow as $key => $value) {
 7         $worksheet->getStyle($colIndex.$rowIndex)->getAlignment()->setWrapText(true);  // 設定自動換行
 8         
 9         if ($key == 'images' && !empty($value)) {
10             $imagePaths = explode(',', $value);
11             foreach ($imagePaths as $index => $image) {
12                 //$worksheet->setCellValue($colIndex . ($rowIndex + $index), trim($image));
13                 $cellCoordinate = $colIndex . ($rowIndex + $index);
14                 $hyperlinkText = "打卡圖" . ($index + 1);
15                 $worksheet->setCellValue($cellCoordinate, $hyperlinkText);
16                 // 設定超連結
17                 $worksheet->getCell($cellCoordinate)->getHyperlink()->setUrl(trim($image));  
19             }
20         } else {
21             $worksheet->setCellValue($colIndex .$rowIndex, $value);
22             $worksheet->mergeCells($colIndex . $rowIndex . ':' . $colIndex . ($rowIndex + $maxImageCount - 1));
23         }
24         $colIndex++;
25     }
27     $rowIndex += $maxImageCount;
28 }

寫入完畢後,再進行excel檔案的匯出 by user 悅悅 https://www.cnblogs.com/nuanai

1 header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
2 header('Content-Disposition: attachment;filename="'.$filename.date("Y-m-d",time()).'.xlsx"'); //檔名+當前時間命名,可以防止被覆蓋
3 header('Cache-Control: max-age=0');
4 $writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet);
5 $writer->save('php://output');

到這裡終於解決的圖片迴圈匯出的難題,還有一些excel的其他格式設定等,我沒有設定超連結的顏色等 by user 悅悅 https://www.cnblogs.com/nuanai

1 //預設B列隱藏
2 $worksheet->getColumnDimension('B')->setVisible(false); 
3 
4 // 將值以字串型別寫入單元格
5 $worksheet->setCellValueExplicit($titCol2.$i, $v, \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_STRING);

by user 悅悅 https://www.cnblogs.com/nuanai

相關文章