ThinkPHP5.0(六)PHP處理excel文件流程,PHPExcel

從前臺獲取文件:

  • 前臺代碼
<input id='location' type="text" class="controls" disabled>//用來顯示選擇的文件
<input type="button" id="i-check" value="選擇報名表" class="btn btn-sm btn-success" onclick="$('#i-file').click();" style="margin-top: -2px">
<input type="file" id='i-file' name="examfile"  accept=".xlsx,.xls" onchange="$('#location').val($('#i-file').val());" style="display: none">
//隱藏的存文件的目錄

前臺獲取文件爲3個input框:

  • 第一個type=”text”,用來顯示獲取到文件的路徑;

  • 第二個type=”button”點擊按鈕;

  • 第三個type=”file”隱藏的獲取文件的表單。
    流程:
    當button 觸發click事件,則調用$(‘#i-file’).click();觸發file,當file類型的input獲取到值(文件路徑),則change事件將路徑值顯示在location。
    jQuery的 .val() - 設置或返回表單字段的值。

後臺接收文件:

獲取:
通過調用request對象的file()方法獲取。

 if(request()->isPost()){
            $file = request()->file('examfile');
            if (!$file)
            {
                return $this->error('未選擇任何文件','JoinController/joinMultiple');
            }
 }

移動(上傳):

內置的上傳只是上傳到本地服務器,上傳到遠程或者第三方平臺的話需要自己擴展。

            // 移動到框架應用根目錄/public/uploads/ 目錄下
            $file_url = ROOT_PATH . 'public' . DS . 'upload'; //. DS . 'excel'
            $config = [
                'size' => 2097152,
                'ext'  => 'xlsx,xls'
            ];
            $info = $file->validate($config)->move($file_url); //2MB

其中validata()是一個格式驗證,傳入參數爲最大字節size和限定的後綴ext

    /**
     * 設置上傳文件的驗證規則
     * @param  array   $rule    驗證規則
     * @return $this
     */
    public function validate($rule = [])
    {
        $this->validate = $rule;
        return $this;
    }

move 方法成功的話返回的是一個 \think\File 對象,你可以對上傳後的文件進行後續操作。

後續操作:
move()方法獲取到的返回值$info可以執行:

  • getExtension()獲得擴展名(後綴名)
  • getSaveName()域名(路徑名)
  • getFilename()文件名

好的可以獲取文件地址通過:

$url=$info->getSaveName();

注意:在文檔中查到

getSaveName 方法返回的是圖片的服務器文件地址,並不能直接用於圖片的URL地址,尤其在 windows平臺上必須做轉換才能正常顯示圖片。

所以正確的獲取路徑的方法爲:

               $url=$info->getSaveName();
               $file_url .= "\\" . $url;

得到的$file_url爲可用的URL地址。

則將$file_url傳入到真正的文件文件處理的方法中,這裏是import()方法。

上述過程完整代碼:

    public function upload()
    {
        if(request()->isPost()){
            $file = request()->file('examfile');
            if (!$file)
            {
                return $this->error('未選擇任何文件','JoinController/joinMultiple');
            }
            // 移動到框架應用根目錄/public/uploads/ 目錄下
            $file_url = ROOT_PATH . 'public' . DS . 'upload'; //. DS . 'excel'
            $config = [
                'size' => 2097152,
                'ext'  => 'xlsx,xls'
            ];
            $info = $file->validate($config)->move($file_url); //2MB
            if ($info) {
                $url=$info->getSaveName();
                $file_url .= "\\" . $url;
                try{
                    chmod($file_url, 0777);
                }catch(\Exception $e){}

                $result =  $this->import($file_url,$info->getExtension());

                try{
                    //使用文件對象的時候沒有完全關閉句柄,導致無法刪除該文件。
                    //解決方法只需要在上傳邏輯完成之後清空釋放一下變量 會在public/upload下多一些空文件夾
                    unset($info);
                    unlink($file_url);
                }catch(\Exception $e){}
                if (!$result) //爲""
                {
                    return $this->success('導入成功','JoinController/joinMultiple');
                }else
                {
                    return $this->error($result,'JoinController/joinMultiple');
                }
            } else {
                // 上傳失敗獲取錯誤信息
                return $this->error($file->getError(),'JoinController/joinMultiple');
            }
        }else
        {
            return $this->error("非法請求",'JoinController/joinMultiple');
        }

    }

處理文件:

我處理的爲Excel文件,經過上述步驟將一個Excel的URL地址,和其擴展名傳入了處理函數import()。
一.PHPExcel的安裝和引用:

注意在處理之前必須採用使用composer安裝PHPExcel。
教程
Git地址
use一下全套服務:

use PHPExcel;
use PHPExcel_IOFactory;
use PHPExcel_Cell;

或者:

       //引入PHPExcel
        header("content-type:text/html; charset=utf-8");
        vendor("phpoffice.phpexcel.Classes.PHPExcel");

就完成了引用!

二.開始處理:

1.通過實例化的PHPExcel_IOFactory對象調用createReader()方法獲得Reader對象;

$PHPReader = PHPExcel_IOFactory::createReader('Excel5'); //use excel2007 for 2007 format

2.Reader對象的load方法調用URL地址獲取到存放文件內容的PHPExcel

$PHPExcel = $PHPReader->load($filename);

3.通過PHPExcelgetActiveSheet方法獲取sheet當前工作sheet

sheet可以存在多個,通過索引getActiveSheet(0)

$sheet = $PHPExcel->getActiveSheet(0);//獲得sheet
$highestRow = $sheet->getHighestRow(); // 取得共有數據數

4.將sheet轉化爲數組進行處理,則Excel中的內容就變成了一個二維數組,方便處理了。

$data=$sheet->toArray();

上述過程完整代碼:

   /** 對xlsx文件解析處理,寫入數據庫
     * @param $filename 文件路徑
     * @param $ext 文件後綴
     * @return string  處理結果
     */
    private function import($filename,$ext){
        //引入PHPExcel
        header("content-type:text/html; charset=utf-8");
        vendor("phpoffice.phpexcel.Classes.PHPExcel");
        //文件導入
        if ($ext == 'xls')
            $PHPReader = PHPExcel_IOFactory::createReader('Excel5'); //use excel2007 for 2007 format
        else
            $PHPReader = PHPExcel_IOFactory::createReader('Excel2007');
        //載入excel文件
        try{
            $PHPExcel = $PHPReader->load($filename);
        }catch(\Exception $e)
        {
            return '您使用的文件可能爲改變文件擴展名之後的Excel文件';
        }
        $sheet = $PHPExcel->getActiveSheet(0);//獲得sheet
        $highestRow = $sheet->getHighestRow(); // 取得共有數據數
        $data=$sheet->toArray();

        $res=$this->checkExcel($data); //結果 檢查上傳的Excel是否合格
        if ($res) //不爲"" ,即不通過
        {
            return $res;
        }
        $hyjyzlb = new Hyjyzlb();
        $yearId = $hyjyzlb->getId();  //Hyjyzlb表的id
        if (!$yearId)  //無合適數據
        {
            return "該時間不能報名";
        }
        $arr['YEAR_ID'] = $yearId; //報名年份
        $arr['DEPTID'] = Session::get('DEPTID','think');// 院系ID
        $join = new Join();
        $unit = new Unit();
        for($i=1;$i<$highestRow;$i++){
            if(!$data[$i][0]||!$data[$i][1]||!$data[$i][2])//學號,姓名性別不全的跳過
            {
                continue;
            }
            $arr['XH'] = $data[$i][0];//學號
            $arr['XM'] = $data[$i][1]; //姓名
            if ($data[$i][2]=='男') //0:男  1:女
            {
                $arr['GENDER'] = 0;
            }
            else if ($data[$i][2]=='女'){
                $arr['GENDER'] = 1;
            }else
            {
                continue;
            }

            for ($j=3;$j<count($data[0]);$j++)
            {
                if($data[$i][$j]=='1')
                {
                    $where=[
                        'NAME'=>$data[0][$j],
                        'GENDER' =>$arr['GENDER']
                    ];
                    $unitInfo = $unit->select($where);
                    if (!$unitInfo)  //數據庫沒有相關項目
                    {
                        continue;
                    }else
                    {
                        $arr['UNIT_ID'] = $unitInfo->ID;
                    }
                    $where=[
                        'XH'=>$data[$i][0],
                        'YEAR_ID'=>$yearId,
                        'UNIT_ID'=>$unitInfo->ID, //運動項目id
                    ];
                    $joinInfo = $join->select($where);
                    if (!$joinInfo)  //數據庫沒有相關報名
                    {
                        $maxs = $join->getMaxNumber($yearId);
                        $arr['NUMBER'] = sprintf("%04d\n", intval($maxs)+1);  //比賽號碼
                        $join->insertOneJoin($arr);
                    }
                }
            }
        }
        return $res;
    }

注意:
checkExcel()爲檢查表頭是否和標準Excel表相同;
insertOneJoin()往數據庫插數據。

最後

終於完了,有點長,寫的頭皮發麻。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章