phpexcel生成excel並下載


 Loader::import('PHPExcel.Classes.PHPExcel');      // tp5中只需將phpexcel文件放入extend文件夾中,即可采用該方法引入,需要先 use think\Loader $objPHPExcel = new \PHPExcel(); // 創建對象 $objPHPExcel->getDefaultStyle()->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER); // 水平居中 $objPHPExcel->getDefaultStyle()->getAlignment()->setVertical(\PHPExcel_Style_Alignment::VERTICAL_CENTER); // 上下居中 $sheet = $objPHPExcel -> getActiveSheet(); $sheet -> getColumnDimension('A')->setWidth(22); // 設置單元格寬度 $sheet -> getColumnDimension('B')->setWidth(15); $sheet -> getColumnDimension('C')->setWidth(15); $sheet -> getColumnDimension('D')->setWidth(20); $sheet -> getColumnDimension('E')->setWidth(15); $sheet -> getColumnDimension('F')->setWidth(20); $sheet -> getColumnDimension('G')->setWidth(10); $sheet -> getColumnDimension('H')->setWidth(40); $sheet->getStyle( 'A1')->getFont()->setName('Candara' ); // 設置單元格字體 $sheet->getStyle( 'A1')->getFont()->setSize(15); // 設置單元格字體大小 $sheet->getStyle( 'A1')->getFont()->setBold(true); // 字體加粗 $sheet->getStyle( 'B1')->getFont()->setName('Candara' ); $sheet->getStyle( 'B1')->getFont()->setSize(15); $sheet->getStyle( 'B1')->getFont()->setBold(true); $sheet->getStyle( 'B1')->getFont()->setName('Candara' ); $sheet->getStyle( 'B1')->getFont()->setSize(15); $sheet->getStyle( 'B1')->getFont()->setBold(true); $sheet->getStyle( 'C1')->getFont()->setName('Candara' ); $sheet->getStyle( 'C1')->getFont()->setSize(15); $sheet->getStyle( 'C1')->getFont()->setBold(true); $sheet->getStyle( 'D1')->getFont()->setName('Candara' ); $sheet->getStyle( 'D1')->getFont()->setSize(15); $sheet->getStyle( 'D1')->getFont()->setBold(true); $sheet->getStyle( 'E1')->getFont()->setName('Candara' ); $sheet->getStyle( 'E1')->getFont()->setSize(15); $sheet->getStyle( 'E1')->getFont()->setBold(true); $sheet->getStyle( 'F1')->getFont()->setName('Candara' ); $sheet->getStyle( 'F1')->getFont()->setSize(15); $sheet->getStyle( 'F1')->getFont()->setBold(true); $sheet->getStyle( 'G1')->getFont()->setName('Candara' ); $sheet->getStyle( 'G1')->getFont()->setSize(15); $sheet->getStyle( 'G1')->getFont()->setBold(true); $sheet->getStyle( 'H1')->getFont()->setName('Candara' ); $sheet->getStyle( 'H1')->getFont()->setSize(15); $sheet->getStyle( 'H1')->getFont()->setBold(true); $sheet -> setCellValue("A1",'作業題目'); $sheet -> setCellValue("B1",'作業名稱'); $sheet -> setCellValue("C1",'作者'); $sheet -> setCellValue("D1",'提交時間'); $sheet -> setCellValue("E1",'批閱人'); $sheet -> setCellValue("F1",'批閱時間'); $sheet -> setCellValue("G1",'得分'); $sheet -> setCellValue("H1",'評語'); $count = isset($list->count) ? $list->count : $list->subject_count; for($row = 0; $row < $count; $row ++) {// 向單元格中插入內容 $subjectTitle = $list->$row->subjectTitle; $workname = $list->$row->workname; $staffname = $list->$row->staffname; $uptime = $list->$row->uptime; $checkStaff = $list->$row->checkStaff; $checktime = $list->$row->checktime; $score = number_format($list->$row->score,2); $number = $list->$row->comment; $sheet -> setCellValue("A".($row+2),$subjectTitle); $sheet -> setCellValue("B".($row+2),$workname); $sheet -> setCellValue("C".($row+2),$staffname); $sheet -> setCellValue("D".($row+2),$uptime); $sheet -> setCellValue("E".($row+2),$checkStaff); $sheet -> setCellValue("F".($row+2),$checktime); $sheet -> setCellValue("G".($row+2),$score); $sheet -> setCellValue("H".($row+2),$number); } $sheet -> setTitle('批閱列表'); if(!file_exists(config('upload_path').'/excel')){ mkdir(config('upload_path').'/excel'); chmod(config('upload_path').'/excel',0777); } (new \PHPExcel_Writer_Excel2007($objPHPExcel))->save(config('upload_path').'/excel/checklist.xls'); $file_name = "checklist.xls"; $contents = file_get_contents(config('upload_path').'/excel/checklist.xls'); $file_size = filesize(config('upload_path').'/excel/checklist.xls'); header("Content-type: application/octet-stream;charset=utf-8"); header("Accept-Ranges: bytes"); header("Accept-Length: $file_size"); header("Content-Disposition: attachment; filename=".$file_name); exit($contents);



二、不用生成 Excel 文件就強制下載:

header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");
header("Content-Disposition: attachment;filename=工單" . "_" . $localtime . ".xls ");
header("Content-Transfer-Encoding: binary ");

請求頭解釋:
1、header("Pragma: public");
Pragma頭域用來包含實現特定的指令
Pragma: public 意思是 響應可被任何緩存區緩存。 
關於Pragma:no-cache,跟Cache-Control: no-cache相同。Pragma: no-cache兼容http 1.0 ,Cache-Control: no-cache是http 1.1提供的。因此,Pragma: no-cache可以應用到http 1.0 和http 1.1,而Cache-Control: no-cache只能應用於http 1.1.

 

2、header("Expires: 0");

     header("Expires: 0");  的意思是緩存已過期

    Expires實體報頭域給出響應過期的日期和時間。為了讓代理服務器或瀏覽器在一段時間以后更新緩存中(再次訪問曾訪問過的頁面時,直接從緩存中加載,縮短響應時間和降低服務器負載)     的頁面,我們可以使用Expires實體報頭域指定頁面過期時間。例:Expires:Thu,15 Sep 2006 16:23:12 GMT

   HTTP1.1的客戶端和緩存必須將其他非法的日期格式(包括0)看作已經過期。如:為了讓瀏覽器不要緩存頁面,也可以利用Expires實體報關域,設置為 0

 

3、header("Cache-Control: must-revalidate, post-check=0, pre-check=0");

     header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); 的意思是強制頁面不緩存,post-check=0, pre-check=0這兩個 是 IE 5.0才有的防cache聲明

Cache-Control。它用來指定請求和響應遵循的緩存機制。在請求消息或響應消息中設置Cache -Control並不會修改另一個消息處理過程中的緩存處理過程。請求時的緩存指令包括no-cache、no-store、max-age、max- stale、min-fresh、only-if-cached,響應消息中的指令包括public、private、no-cache、no-store、no-transform、must-revalidate、proxy-revalidate、max-age、s-maxage。我們來說說響應消息,因為 它是服務器發出的,對於客戶端和Cache System都有非常重要的意義:
Public    指示響應可被任何緩存區緩存。
Private    指示對於單個用戶的整個或部分響應消息,不能被共享緩存處理。這允許服務器僅僅描述當用戶的部分響應消息,此響應消息對於其他用戶的請求無效。
no-cache    指示請求或響應消息不能緩存
no-store    用於防止重要的信息被無意的發布。在請求消息中發送將使得請求和響應消息都不使用緩存
max-age    指示客戶機可以接收生存期不大於指定時間(以秒為單位)的響應。
no-transform     不允許轉換存儲系統
must-revalidate  使得客戶端再次瀏覽當前頁時必須發送相關 HTTP 頭信息到服務器進行驗證,然后才決定是否加載客戶端本地 cache

 

4、header("Content-Type: application/force-download");

    header("Content-Type: application/force-download"); 的意思是 強制下載

 

5、header("Content-Type: application/octet-stream");

   不知道下載文件的類型時使用,采用二進制流

 

6、header("Content-Disposition: attachment;filename=附件名.xls ");

     意思是 類型為附件, 附件名為 :附件名.xls

7、header("Content-Transfer-Encoding: binary ");

意思是采用二進制進行傳輸

Transfer-Encoding 告知接收端為了保證報文的可靠傳輸,對報文采用了什么編碼方式

 

 8、header("Content-Range: 580-1899/1900");

在HTTP/1.1協議沒出的時候,也就是HTTP/1.0協議,這種協議不可以使用長鏈接和斷點續傳和其他新特性;自從這個1.1被廣大使用的現在,很多的下載器都被支持斷點續傳。
 
斷點續傳也就是從下載斷開的哪里,重新接着下載,直到下載完整/可用。如果要使用這種斷點續傳,4個HTTP頭不可少的,分別是Range頭、Content-Range頭、Accept-Ranges頭、Content-Length頭。這里我講的是服務端,其中要用Range頭是因為它是客戶端發過來的信息。服務端是響應,而客戶端(瀏覽器)是請求。
 
Range頭必須要了解它,否則沒法解析。請求中會帶過來的斷點信息,一般三種格式。
 
Range : bytes=50-          意思是從第50個字節開始到最后一個字節

Range : bytes=-70          意思是最后的70個字節

Range : bytes=50-100    意思是從第50字節到100字節 
 
讀取客戶端發來的Range頭解析為:
 
假設文件總大小為130字節。
 
第一種Range    50-130
 

第二種Range   ( 130 - 70 )-130

 
第三種Range   50-100
 
還有一點要曉得的就是返回的HTTP狀態碼200、206、416這些意義。200是OK(一切正常),206是Partial Content(服務器已經成功處理了部分內容),416 Requested Range Not Satisfiable(對方(客戶端)發來的Range 請求頭不合理)。
 
一般處理單線程處理: 客戶端發來請求 ——->  服務端返回200  ——> 客戶端開始接受數據  ——> 用戶手多多把下載停止了 ——> 客戶端突然停止接受數據 ——> 然后客戶端都沒說再見就與服務端斷開了 ——> 用戶手的癢了又按回開始鍵 ——> 客戶端再次與服務端連接上,並發送Range請求頭給服務端 ——> 這時服務端返回是206 ——> 服務端從斷開的數據那繼續發送,並且會發送響應頭:Content-Range給客戶端 ——>客戶端接收數據 ——>直到完成。
 
再服務端返回206的前面,客戶端假如發送了些不合理的Range請求頭,服務端就不是返回206而是416。就是結尾字節大於開始字節或者是結尾字節是0什么的,這必定是416的。
 
單線程通常就是這樣,那么我們的客戶端是多線程呢,那么我們必定也是多線程。客戶端會一次性發來多個請求,來貪婪的快速地下載完成文件。鏈接別太多就行了。會爆?Http/1.1協議 <wbr>Content-Range頭 <wbr>用於http斷點續傳
 
GET /123.zip HTTP/1.1   客戶端發來請求了。
 
那我們告訴它。
 
HTTP/1.1 200 OK 
Accept-Ranges : bytes   //告訴客戶端,我們是支持斷點傳輸的,你知道了嗎?
Content-Length : 1900 //文件總大小 
Content-Type : image/jpeg //文件類型
 
二進制數據。
 
好了,就這樣發送去了。發着發着,咦TM斷掉了。我的七舅姥爺姑奶奶,為毛就斷掉了呢,包租婆,怎么霎時間摸左水吶。
 
客戶端又發來請求這回有點意思。
 
GET /123.zip HTTP/1.1 
Range:bytes=580-
 
大家看到沒,會多了怎么一行,我們解析為從580字節開始到1900字節,是要部分內容耶,那么返回什么呢。沒錯206啊。
 
HTTP/1.1 206 Partial Content
Accept-Ranges : bytes
Content-Type : image/jpeg //文件類型
Content-Length : (1900 - 580) //長度則不是總長度了,而580到1900共有多少字節。
Content-Range :bytes 580-(1900-1 ) / 1900   //這位同學,我想問問你,為什么結束字節要減1呢。這是因為發來的Range請求頭文件下標是0開始,那么結尾數顯示也要減1;但是實際上輸出的字節是不減1的,完全是寫法問題。
 
注:Content-Range 這一部分是源自博友的博客,感謝博友分享:http://blog.sina.com.cn/s/blog_ec8c9eae0102x3uu.html

 

三、用數據生成 excel 並下載(不用生成臨時文件)

 

<?php
include_once "phpexcel/PHPExcel.php";
$cfg_columns = array( 'date' => array( 'name' => '日期', 'type' => 'label', 'width' => 100 ), 'name' => array( 'name' => '姓名', 'type' => 'label', 'width' => 100 ), 'dept_name' => array( 'name' => '部門', 'type' => 'label', 'width' => 100 ), ); $list = array( 0 => array( 'date' => '2017-12-01 10:32:45', 'name' => '張三', 'dept_name' => '研發部', ), 1 => array( 'date' => '2017-12-02 10:32:45', 'name' => '李四', 'dept_name' => '客服部', ), 2 => array( 'date' => '2017-12-03 10:32:45', 'name' => '王五', 'dept_name' => '人力資源部', ), ); $filename = 'test.xls'; header('Pragma:public'); header('Content-Type:application/x-msexecl;name="'.$filename.'"'); header('Content-Disposition:inline;filename="'.$filename.'"'); $objPHPExcel = new PHPExcel(); $objPHPExcel->getActiveSheet(0)->mergeCells('B1:D1'); $export_time = date('Y-m-d H:i:s'); $objPHPExcel->setActiveSheetIndex(0)->setCellValue('A1', '導出時間:'); $objPHPExcel->setActiveSheetIndex(0)->setCellValue('B1', $export_time); $cols = 'A'; foreach ($cfg_columns as $val){ $objPHPExcel->setActiveSheetIndex(0)->setCellValue($cols++.'2',$val['name']); } //第三行, 輸出詳細數據 $rows = 3; foreach ($list as $fields){ $cols = 'A'; //按cfg_column的配置項導出 foreach ($cfg_columns as $k => $val){ if(empty( $fields[$k])){ $objPHPExcel->getActiveSheet()->setCellValue($cols++.$rows, 0); }else{ $objPHPExcel->getActiveSheet()->setCellValue($cols++.$rows, $fields[$k]); } } //end foreach ($cfg_column as $key => $val) $rows ++; } $objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5'); $objWriter->save('php://output'); exit;

 如果遇到需要導出的表格包含復選框等各種格式,可以先生成生個視圖,在渲染視圖$this->display() 之前使用header()下載,下載的文件名為 xxx.xls ,就可以將整個表格下載到excel啦。

讀取 excel 文件內容,並變成一個由 , 分割的字符串

include_once "phpexcel/PHPExcel.php";
$filePath = $_FILES['file']['tmp_name'];
$PHPExcel = new PHPExcel();
/**默認用excel2007讀取excel,若格式不對,則用之前的版本進行讀取*/
$PHPReader = new PHPExcel_Reader_Excel2007();
if(!$PHPReader->canRead($filePath)){
    $PHPReader = new PHPExcel_Reader_Excel5();
    if(!$PHPReader->canRead($filePath)){
        echo 'no Excel';
        return ;
    }
}

$PHPExcel = $PHPReader->load($filePath);
/**讀取excel文件中的第一個工作表*/
$currentSheet = $PHPExcel->getSheet(0);
/**取得最大的列號*/
$allColumn = $currentSheet->getHighestColumn();
/**取得一共有多少行*/
$allRow = $currentSheet->getHighestRow();
/**從第二行開始輸出,因為excel表中第一行為列名*/
$temStr = "";
for($currentRow = 2;$currentRow <= $allRow;$currentRow++){
    /**從第A列開始輸出*/
    for($currentColumn= 'A';$currentColumn<= $allColumn; $currentColumn++) {
        $temStr .= $currentSheet->getCellByColumnAndRow(ord($currentColumn) - 65, $currentRow)->getValue();
        $temStr .=',';
    }
}
$temStr = rtrim($temStr,',');

...

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM