PHPExcel使用體會

PHPExcel使用體會

由於畢設導師智能分配系統的須要,系負責人在管理學生和導師時,但願可使用Excel批量導入學生和導師的信息,學長的報課系統使用的是PHPExcel的類庫,因而我也抽空花了2天的時間學習了PHPExcel的最基礎的導入導出功能的實現,總結了本身的使用心得和一些經常使用的使用方法

1、類庫的引入

  • PHP我使用的是ThinkPHP5的框架,因此以TP5框架爲例,這是項目的PHPExcel的目錄結構:
    php

    require_once 'extend/reader.php'; //Excel讀取
      require_once 'extend/PHPExcel_1.8.0_doc/Classes/PHPExcel.php'; //Excel導入導出

2、Excel導入

  • 調用Reader數據庫

    require_once 'extend/reader.php';
  • 建立Reader數組

    $data = new \Spreadsheet_Excel_Reader();
  • 設置在頁面中輸出的編碼方式瀏覽器

    $data->setOutputEncoding('utf-8');
  • 讀取上傳到當前目錄下實際路徑爲$realPath的文件網絡

    $data->read($realPath);
  • 設置PHP的報錯級別並返回當前的級別app

    error_reporting(E_ALL ^ E_NOTICE);
      或error_reporting(E_ALL & ~E_NOTICE);

    起初並非很懂這句代碼的含義,通過查找資料後發現,在不一樣的PHP版本中,本來可能在低版本的PHP中運行正常的代碼,在較高版本的PHP中運行可能就會出現報錯,爲了使程序可以正常運行,須要在程序開頭加上這句代碼;error_reporting()設置PHP的報錯級別並返回當前的級別,如下是網絡上查找的一些資料,在作Excel導出的時候出現了一個bug好久都沒有解決,在TP5的交流羣詢問以後被某位大佬問到:「你知道PHP的報錯等級嗎?你知道什麼是未定義變量嗎?」查看錯誤報告以後發現確實出現了下面的第7條錯誤:框架

    1. 錯誤報告是按位的。或者將數字加起來獲得想要的錯誤報告等級
    2. E_ALL - 全部的錯誤和警告
    3. E_ERROR - 致命性運行時錯
    4. E_WARNING - 運行時警告(非致命性錯)
    5. E_PARSE - 編譯時解析錯誤
    6. E_NOTICE - 運行時提醒
    7. 多是有意的行爲形成的(如:基於未初始化的變量自動初始化爲一個空字符串的事實而使用一個未初始化的變量)
    8. E_CORE_ERROR - 發生於PHP啓動時初始化過程當中的致命錯誤
    9. E_CORE_WARNING - 發生於PHP啓動時初始化過程當中的警告(非致命性錯)
    10. E_COMPILE_ERROR - 編譯時致命性錯
    11. E_COMPILE_WARNING - 編譯時警告(非致命性錯)
    12. E_USER_ERROR - 用戶產生的出錯消息
    13. E_USER_WARNING - 用戶產生的警告消息
    14. E_USER_NOTICE - 用戶產生的提醒消息
  • 循環處理Excel表格裏的每一行數據並插入數據庫post

    for ($i=3; $i <=$data->sheets[0]['numRows'] ; $i++) { 
              $insert = [];
              $insert['grade'] = $data->sheets[0]['cells'][$i][1];
              $insert['serialNum'] = $data->sheets[0]['cells'][$i][2];
              $insert['password'] = $data->sheets[0]['cells'][$i][2];
              $insert['name'] = $data->sheets[0]['cells'][$i][3];
              $insert['gender'] = $data->sheets[0]['cells'][$i][4];
              $insert['college'] = $data->sheets[0]['cells'][$i][5];
              $insert['department'] = $data->sheets[0]['cells'][$i][6];
              $insert['gpa'] = $data->sheets[0]['cells'][$i][7];
              $insert['rank'] = $data->sheets[0]['cells'][$i][8];
              $insert['telephone'] = $data->sheets[0]['cells'][$i][9];
              $insert['chosen'] = 0;
              //插入數據庫中
              Db('user_student_'.$insert['grade'])->insert($insert);
          }

3、Excel導出

  • 引入PHPExcel.php學習

    require_once 'extend/PHPExcel_1.8.0_doc/Classes/PHPExcel.php';
  • 建立一個新的Excel文件字體

    $excel = new \PHPExcel();
  • 先進行通常的Excel格式的處理

    $excel->getActiveSheet()->getColumnDimension('A')->setWidth(9);  //手動設置單元格寬度
      $excel->getActiveSheet()->getColumnDimension('B')->setWidth(30);
      $excel->getActiveSheet()->getColumnDimension('C')->setWidth(9);
    
      $excel->getActiveSheet()->getRowDimension(2)->setRowHeight(35);  //設置某一行高度
    
      $excel->getActiveSheet()->getStyle('A1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);  //設置水平居中
      $excel->getActiveSheet()->getStyle('A1')->getAlignment()->setVertical(\PHPExcel_Style_Alignment::VERTICAL_CENTER);  //設置水平居中
    
      $excel->getActiveSheet()->getStyle('G')->getNumberFormat()->setFormatCode('000000000');  //設置文本格式
    
      //設置邊框和水平垂直居中,PHPExcel貌似沒有對全部的單元格進行統一處理的功能,因此我定義裏一個$styleArray,方便在往Excel中寫入數據時,同時對單元格進行格式的設置
      $styleArray = [ 
          'alignment' => [
              'horizontal' => \PHPExcel_Style_Alignment::HORIZONTAL_CENTER,
              'vertical' => \PHPExcel_Style_Alignment::VERTICAL_CENTER
          ],
          'borders' => [
              'allborders' => [
                  'style' => \PHPExcel_Style_Border::BORDER_THIN
              ]
          ]
      ];
      $excel->getActiveSheet()->getStyle('A1')->applyFromArray($styleArray);
    
      $excel->getActiveSheet()->getStyle('A1')->getFont()->setBold(true);  //設置字體加粗
    
      $excel->getActiveSheet()->mergeCells('A1:H1');  //合併A1:F1單元格
  • 對錶格第一行標題的特殊處理

    $excel->getActiveSheet()->mergeCells('A1:H1');  //合併A1:H1單元格
      $excel->getActiveSheet()->setCellValue('A1',$insert[0]['grade'].'級'.$insert[0]['dep'].'導師分配結果');
      $excel->getActiveSheet()->getStyle('A1')->getFont()->setBold(true);  //加粗
      $excel->getActiveSheet()->getStyle('A1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER); //設置水平居中
      $excel->getActiveSheet()->getStyle('A1')->getAlignment()->setVertical(\PHPExcel_Style_Alignment::VERTICAL_CENTER);     //設置垂直居中
  • 對錶的標題行的特殊處理

    $letter = ['A','B','C','D','E','F','G','H'];
      $tableHeader = ['序號','系別','專業導師','職稱','課題','學生姓名','學號','聯繫方式'];    //設置表頭數組,單獨處理
      for ($i=0; $i <8 ; $i++) { 
          $excel->getActiveSheet()->setCellValue($letter[$i].'2',$tableHeader[$i]);            //設置單元格的值
          $excel->getActiveSheet()->getStyle($letter[$i].'2')->applyFromArray($styleArray);    //設置單元格格式:水平、垂直居中、加邊框
          $excel->getActiveSheet()->getStyle($letter[$i].'2')->getFont()->setBold(true);       //設置單元格字體加粗
      }
  • 在此次項目中碰到的比較奇葩的問題和處理辦法 - 某些單元格的動態合併:

    第一種狀況如上圖,對於上圖這種格式的Excel寫入是比較簡單的,只需從數據庫中取出數據,逐條的插入進表格中,並做格式處理就行了

    $totalInsert = count($insert);   //計算總插入數
      for ($i=0; $i <$totalInsert ; $i++) { 
          $excel->getActiveSheet()->setCellValue('A'.($i+3),($i+1));
          $excel->getActiveSheet()->setCellValue('B'.($i+3),$insert[$i]['tdep']);
          $excel->getActiveSheet()->setCellValue('C'.($i+3),$insert[$i]['sname']);
          $excel->getActiveSheet()->setCellValue('D'.($i+3),$insert[$i]['snum']);
          $excel->getActiveSheet()->setCellValue('E'.($i+3),$insert[$i]['stele']);
          $excel->getActiveSheet()->setCellValue('F'.($i+3),$insert[$i]['tname']);
          $excel->getActiveSheet()->setCellValue('G'.($i+3),$insert[$i]['tposi']);
          $excel->getActiveSheet()->setCellValue('H'.($i+3),$insert[$i]['title']);
          $excel->getActiveSheet()->setCellValue('I'.($i+3),$insert[$i]['ttele']);
      }
    
      for ($j=0; $j <9 ; $j++) { 
              $excel->getActiveSheet()->getStyle($letter[$j].'3'.':'.$letter[$j].($totalInsert+2))->applyFromArray($styleArray); //設置單元格格式:水平、垂直居中、加邊框
          }

    第二種狀況如上圖,對於初學PHPExcel的我來講,上圖的操做簡直是麻煩,個人作法是

    1. 先設置兩個臨時變量 $oldTemp$newTemp 用來處理合並的單元格的範圍,例如合併A1:A6,$oldTemp 用來記錄合併的左範圍,$newTemp用來記錄合併的右範圍,而且 $newTemp = $oldTemp + 每一個導師的學生數,若學生數爲0,則加1

    2. 先插入列F、G、H的數據,加樣式,而後對前面的列A、B、C、D、E先插值,再進行單元格合併,由於好比A1:A3合併,合併後的單元格名稱仍然爲A1,合併的範圍爲 $oldTemp : $newTemp-1,而後交換 $oldTemp$newTemp

    3. 不知道有沒有更好的處理辦法,對本身的處理辦法表示有點愚蠢。。

      $oldTemp = 3;           //臨時變量,用於處理合並單元格的範圍
       $newTemp = 0;           //臨時變量,用於處理合並單元格的範圍
      
       for ($i=0; $i <$totalInsert ; $i++) {                 //循環插入數據,並做格式處理
           if ($insert[$i]['stuNum'] == 0) {                 //判斷導師是否有學生,若是沒有學生,只需插入一行 
               $tempCount = $insert[$i]['stuNum'] + 1;
           } else {
               $tempCount = $insert[$i]['stuNum'];
           }
           for ($j=0; $j <$tempCount ; $j++) {               //開始插入
               if ($insert[$i]['stuNum'] != 0) {             //逐一插入導師的學生信息
                   $excel->getActiveSheet()->setCellValue('F'.($j+$oldTemp),$insert[$i]['tstudentL'][$j]['sname']);
                   $excel->getActiveSheet()->setCellValue('G'.($j+$oldTemp),$insert[$i]['tstudentL'][$j]['snum']);
                   $excel->getActiveSheet()->setCellValue('H'.($j+$oldTemp),$insert[$i]['tstudentL'][$j]['stele']);
           }
      
               $excel->getActiveSheet()->getStyle('F'.($j+$oldTemp))->applyFromArray($styleArray); //設置單元格格式:水平、垂直居中、加邊框
               $excel->getActiveSheet()->getStyle('G'.($j+$oldTemp))->applyFromArray($styleArray); //設置單元格格式:水平、垂直居中、加邊框
               $excel->getActiveSheet()->getStyle('H'.($j+$oldTemp))->applyFromArray($styleArray); //設置單元格格式:水平、垂直居中、加邊框
       }
      
           $excel->getActiveSheet()->setCellValue('A'.$oldTemp,($i+1));                            //設置單元格的值
           $excel->getActiveSheet()->setCellValue('B'.$oldTemp,$insert[$i]['dep']);
           $excel->getActiveSheet()->setCellValue('C'.$oldTemp,$insert[$i]['tname']);
           $excel->getActiveSheet()->setCellValue('D'.$oldTemp,$insert[$i]['position']);
           $excel->getActiveSheet()->setCellValue('E'.$oldTemp,$insert[$i]['title']);
      
           $newTemp = $oldTemp + $tempCount;
           if ($insert[$i]['stuNum'] != 1 && $insert[$i]['stuNum'] != 0) {
               for ($k=0; $k <5 ; $k++) { 
                   $excel->getActiveSheet()->mergeCells($letter[$k].$oldTemp.':'.$letter[$k].($newTemp-1)); //根據導師的學生數合併A、B、C、D、E列的單元格
               }
           }
      
           for ($z=0; $z <5 ; $z++) { 
               $excel->getActiveSheet()->getStyle($letter[$z].$oldTemp.':'.$letter[$z].($newTemp-1))->applyFromArray($styleArray); //設置單元格格式:水平、垂直居中、加邊框
           }
      
           $oldTemp = $newTemp;
       }
  • 直接輸出至瀏覽器,即下載至本地,只需直接加入代碼就行

    $write = new \PHPExcel_Writer_Excel5($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/vnd.ms-execl");
      header("Content-Type:application/octet-stream");
      header("Content-Type:application/download");;
      header('Content-Disposition:attachment;filename='.'"'.$insert[0]['grade'].'級導師互選結果.xls"'); //能夠對文件名進行處理
      header("Content-Transfer-Encoding:binary");
      $write->save('php://output');

4、實踐效果動圖

學生Excel導入:

Excel模版導出:

結果導出:

5、總結

  • 期間遇到了不少的bug,不斷的上網找資料、找博客,學到了不少的知識,好比在一個''上剛了很是多的時間,最後找到錯誤的時候又喜又氣的,還有在往Excel中寫數據的時候,碰到一個未定義數組下標[0]的錯誤的時候,花了更多的時間,反反覆覆的檢查代碼愣是沒發現錯誤在哪裏,躺在牀上沒解決bug不甘心又下牀苦尋,最後發現數據庫中的數據有一些是空的,直接插入會出錯,要作一些相應的處理

  • 學到了新知識內心是驚喜的,不過我也是得去作下編譯實驗的。。

相關文章
相關標籤/搜索