本來是想利用ajax提交json數據到服務端, 讓服務端生成一個excel文件並提示客戶端瀏覽器下載的. 但是搞了很久發現ajax方式是無法觸發瀏覽器彈出文件下載的.
網上很多的方案都是說利用form提交, 還有就是純客戶端js去生成excel文件. 這兩種方案都是可行的, 今天只演示第一種.
瀏覽器上展示了一堆數據, 有個按鈕是導出按鈕,點擊后觸發一個事件, 提交數據到服務端, 由服務端來生成excel文件流並提示瀏覽器下載!
按鈕的點擊:
onExportExcel = () => { ....... 這里准備好需要提交到服務端的數據 const inputs = { data, header, columnWidth, filename, }; this.exportExcel('/xx1/xx2/exportExcel', inputs); } exportExcel(url, data) // 導出數據到excel文件 { const form = document.createElement('form'); form.style = "display:none;"; form.method = "post"; form.action = url; const input = document.createElement('input'); input.type = 'hidden'; input.name = 'values'; input.value = Base64.encode(JSON.stringify(data)); form.appendChild(input); $('body').append(form); form.submit(); form.remove(); }
這里用了一個Base64.encode()接口(下載), 這里是關鍵, 因為普通的input表單一般是用於傳遞字符串的, 但是因為我這里要傳遞的是一個object對象(也可認為是json數據), 所以我就想到了將json序列化后並base64編碼下(不編碼的話, 服務端接收到的值有可能json_decode會失敗). ==> 所以服務端在接收時要采取相反的方向先base64_decode, 再調用json_decode才能得到原始的json數據!
服務端代碼(php, thinkcmf5.0):
public function exportExcel() { $values = request()->post('values'); $values = base64_decode($values); $list = json_decode($values, true); if(!$list) { _return(1, '沒有數據, 無法導出到文件'); } log_message($list); $data = $list['data']; $header = $list['header']; $columnWidth = $list['columnWidth']; $filename = $list['filename']; if (empty($data) || empty($header) || empty($filename)) { $this->success('success'); return; } ExcelModule::exportFile($data, $header, $columnWidth, $filename); }
ExcelModule::exportFile是我自已寫的一個類, 封裝的一個靜態接口函數
1 class ExcelModule 2 { 3 /** 4 * 導出數據到excel文件並提供下載 5 * @param array $data 6 * @param array $fileheader 7 * @param array $columnWidth 8 * @param $savefile 9 * @param string $sheetname 10 * @throws \PHPExcel_Exception 11 * @throws \PHPExcel_Reader_Exception 12 * @throws \PHPExcel_Writer_Exception 13 */ 14 public static function exportFile(array $data, array $fileheader, array $columnWidth, $savefile, $sheetname = 'MySheet') 15 { 16 Vendor('PHPExcel.PHPExcel.IOFactory'); 17 $excel = new \PHPExcel(); 18 //防止中文命名,下載時ie9及其他情況下的文件名稱亂碼 19 // iconv('UTF-8', 'GB2312', $savefile); 20 $objActSheet = $excel->getActiveSheet(); 21 //根據有生成的excel多少列,$letter長度要大於等於這個值 22 $letter = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V'); 23 //設置當前的sheet 24 $excel->setActiveSheetIndex(0); 25 //設置sheet的name 26 $objActSheet->setTitle($sheetname); 27 //設置表頭 28 for ($i = 0; $i < count($fileheader); $i++) { 29 // 單元寬度自適應,1.8.1版本phpexcel中文支持勉強可以,自適應后單獨設置寬度無效 30 // $objActSheet->getColumnDimension("$letter[$i]")->setAutoSize(true); 31 $objActSheet->getColumnDimension("$letter[$i]")->setWidth($columnWidth[$i]); 32 // 設置表頭值,這里的setCellValue第二個參數不能使用iconv,否則excel中顯示false 33 $objActSheet->setCellValue("{$letter[$i]}1", $fileheader[$i]); 34 // 設置表頭字體樣式 35 $objActSheet->getStyle("{$letter[$i]}1")->getFont()->setName('微軟雅黑'); 36 //設置表頭字體大小 37 $objActSheet->getStyle("{$letter[$i]}1")->getFont()->setSize(12); 38 //設置表頭字體是否加粗 39 // $objActSheet->getStyle("{$letter[$i]}1")->getFont()->setBold(true); 40 //設置表頭文字垂直居中 41 $objActSheet->getStyle("{$letter[$i]}1")->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER); 42 //設置文字上下居中 43 $objActSheet->getStyle("$letter[$i]")->getAlignment()->setVertical(\PHPExcel_Style_Alignment::VERTICAL_CENTER); 44 //設置表頭外的文字垂直居中 45 $excel->setActiveSheetIndex(0)->getStyle("$letter[$i]")->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER); 46 } 47 48 $j = 2; 49 foreach ($data as $k => $v) { 50 $i = 0; 51 foreach ($v as $key => $value) { 52 $objActSheet->setCellValue($letter[$i] . $j, $value); 53 // $objActSheet->getColumnDimension("$letter[$i]")->setAutoSize(true); 54 $objActSheet->getColumnDimension("$letter[$i]")->setWidth($columnWidth[$i]); 55 $i++; 56 } 57 $j++; 58 } 59 header('Content-Type: application/vnd.ms-excel'); 60 //下載的excel文件名稱,為Excel5,后綴為xls,不過影響似乎不大 61 header('Content-Disposition: attachment;filename="' . $savefile . '.xls"'); 62 header('Cache-Control: max-age=0'); 63 // 用戶下載excel 64 $objWriter = \PHPExcel_IOFactory::createWriter($excel, 'Excel2007'); 65 $objWriter->save('php://output'); 66 exit; 67 } 68 }
我這個php服務端是thinkcmf5.0框架下的, 包含了很多現成的庫!
最終效果: