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

##从前台获取文件:

  • 前台代码
//用来显示选择的文件


//隐藏的存文件的目录

前台获取文件为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方法如果只传入一个路径则默认会在目录下生成时间目录,且文件名为自动生成的
例如:20180926\bbc624371e90924a8483b5421acc2e43.xlsx 时间目录20180926下的这个文件
如果不想生成时间目录,且用原始文件名,则通过传入其他参数。
原始文件名采用:move($file_url,'')

   /**
     * 移动文件
     * @param  string           $path    保存路径
     * @param  string|bool      $savename    保存的文件名 默认自动生成
     * @param  boolean          $replace 同名文件是否覆盖
     * @return false|SplFileInfo false-失败 否则返回SplFileInfo实例
     */
    public function move($path, $savename = true, $replace = true)

后续操作:
move()方法获取到的返回值$info可以执行:

  • getExtension()获得扩展名(后缀名)
  • getSaveName()域名
  • getFilename()文件名

好的可以获取文件地址通过:

$url=$info->getSaveName();

注意:在文档中查到

getSaveName 方法返回的是图片的服务器文件地址,并不能直接用于图片的URL地址,尤其在 windows平台上必须做转换才能正常显示图片。

所以正确的获取路径的方法为:

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

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$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()**往数据库插数据。

##最后
终于完了,有点长,写的头皮发麻。

你可能感兴趣的:(PHP,Thinkphp5,PHPExcel)