<?php

//引入PHPExcel核心
require(FRAMEWORK_PATH . 'libraries/PHPExcel/PHPExcel.php');
/**
 * Excel表操作（导出）
 */
class Excel{

    protected static $instace;
    /**
     * 设置表格标题、表头（注意：列仅A-Z）
     * @param $sheet 工作sheet
     * @param $sheetName 工作簿名
     * @param $title 表格标题，可不填写
     * @param $header 表头标题集合
     * @return int 下一行位置Index
     */
    protected function header($sheet, $sheetName, $title, $header){
        $sheet->setTitle($sheetName); //标题
        //设置标题
        if($title) {
            $a = 'A';
            for($i=1; $i<count($header); $i++){$a++;} //计算合并最后位置
            $sheet->mergeCells("A1:".$a."1"); //合并单元格
            $sheet->getStyle('A1')->getAlignment() //居中
                ->setVertical(PHPExcel_Style_Alignment::VERTICAL_CENTER)
                ->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
            $sheet->setCellValue("A1", $title);
        }
        //设置列名
        $col = 'A';
        foreach($header as $name){
            $sheet->setCellValue($col.($title ? "2" : "1"), $name);
            $col++;
        }
        return $title ? 3 : 2;
    }

    /**
     * 写入导出的数据
     * @param $sheet 工作sheet
     * @param $index 下一个写入记录的位置
     * @param $data 所有数据
     * @param $total 合计位置，1开始
     */
    protected function writeData($sheet, $index, $data, $total){
        $sum = array(); //记录$total位置的和
        $total = "," . $total . ",";
        foreach($data as $row){ //行
            $col = 'A';
            $loc = 1;
            foreach($row as $cell){ //单元格
                if(strpos($total, "".$loc) !== false){
                    if(isset($sum[$loc])){
                        $sum[$loc] += floatval($cell);
                    }else{
                        $sum[$loc] = floatval($cell);
                    }
                }
                $sheet->setCellValue($col.$index, $cell);
                $col++; //列+1
                $loc++; //位置+1
            }
            $index++; //行+1
        }
        //合计行
        if($total && count($sum) > 0){
            foreach($sum as $key => $value){
                $col = 'A';
                for($i=1; $i<$key; $i++){$col++;}
                $sheet->setCellValue($col.$index, $value);
            }
            $sheet->setCellValue("A".$index, "合计");
        }
    }

    /**
     * 开始下载Excel文件
     * @param $phpExcel PHPExcel实体
     * @param $fileName 文件名
     */
    private function execDownExcel($phpExcel, $fileName){
        //设置头信息
        ob_end_clean();//清除缓冲区,避免乱码
        header('Content-Type: application/vnd.ms-excel');
        header('Content-Disposition: attachment;filename="'. $fileName .'.xls"');
        header('Cache-Control: max-age=0');

        $objWriter = PHPExcel_IOFactory::createWriter($phpExcel, 'Excel5');
        $objWriter->save('php://output');
    }

    /**
     * Excel表导出功能
     * @param $fileName 导出时文件命名
     * @param $title 表格标题，第一行，为空时无
     * @param $header 表头，查询SQL中select内容需与此一致
     * @param $data 数据
     * @param $total 需合计的列，从1开始
     */
    public function export($fileName, $title, $header, $data, $total=""){
        $phpExcel = new PHPExcel(); //生成excel核心组件
        $phpExcel->setActiveSheetIndex(0); //设置序号
        $index = $this->header($phpExcel->getActiveSheet(),
            $fileName, $title, $header); //构建工作簿
        $this->writeData($phpExcel->getActiveSheet(), $index, $data, $total);
        $this->execDownExcel($phpExcel, $fileName);
    }
    
    
    public static function download($fileName, $title, $header, $data, $total=""){
        $phpExcel = new PHPExcel(); //生成excel核心组件
        //        $phpExcel->getActiveSheet()->setCellValueExplicit('B','',PHPExcel_Cell_DataType::TYPE_STRING);
        $phpExcel->getActiveSheet()->setTitle('Simple');
        
        $phpExcel->getActiveSheet()->getStyle('B')->getNumberFormat()->setFormatCode(PHPExcel_Style_NumberFormat::FORMAT_TEXT);
        $phpExcel->setActiveSheetIndex(0); //设置序号
        $index = self::getInstace()->header($phpExcel->getActiveSheet(),
            $fileName, $title, $header); //构建工作簿
            self::getInstace()->writeData($phpExcel->getActiveSheet(), $index, $data, $total);
            self::getInstace()->execDownExcel($phpExcel, $fileName);
    }
    
    //////////////////////////////////////////////////////////////////////////////////
    ///                               导 入                                         ///
    ////////////////////////////////////////////////////////////////////////////////////
    /**
     * 获取格式化数据 默认第一列是 表头
     * @param $filename  文件路径
     * @param string $exts 后缀名
     * @throws PHPExcel_Exception
     * @throws PHPExcel_Reader_Exception
     */
    public static function get($filename)
    {
        $arr = explode('.', $filename);
        $filetype = end($arr);
        switch ($filetype) {
            case 'xls':
                $PHPReader = PHPExcel_IOFactory::createReader('Excel5');
                break;
            case 'xlsx':
                $PHPReader = PHPExcel_IOFactory::createReader('Excel2007');
                break;
            default:
                return ['status'=>false,'msg'=>'文件类型不识别 请使用 xls 或 xlsx 格式'];
                break;
        }
        
        $PHPReader = $PHPReader->load(ROOT.$filename);
        $Count= $PHPReader->getSheetCount();  #一共有多少小文件
        $data = [];
        for ($h=0;$h<$Count;$h++) {
            $data[] = self::getInstace()->getData($PHPReader,$h);
        }
        if($Count== 1) {  # 只有一个 sheet 小文件情况
            return $data[0]; #
        }
        return   $data; #
    }
    
    /**
     * 获取原始数据
     * @param $filename  文件路径
     * @param string $exts 后缀名
     * @throws PHPExcel_Exception
     * @throws PHPExcel_Reader_Exception
     */
    public static function getOrg($filename)
    {
        $arr = explode('.', $filename);
        $filetype = end($arr);
        switch ($filetype) {
            case 'xls':
                $PHPReader = PHPExcel_IOFactory::createReader('Excel5');
                break;
            case 'xlsx':
                $PHPReader = PHPExcel_IOFactory::createReader('Excel2007');
                break;
            default:
                return ['status'=>false,'msg'=>'文件类型不识别 请使用 xls 或 xlsx 格式'];
                break;
        }
        
        $PHPReader = $PHPReader->load(ROOT.$filename);
        $Count= $PHPReader->getSheetCount();  # 一共有多少小文件
        $data = [];
        
        for ($h=0;$h<$Count;$h++) {
            $data[] = self::getInstace()->getOrigionData($PHPReader,$h);
        }
        if($Count== 1) {  # 只有一个 sheet 小文件情况
            return $data[0]; #
        }
        return   $data; #
    }
    /**
     * 获取每个小文件的数据
     * @param $PHPReader
     * @param $index
     * @return array[title,datea]
     */
    public function getData($PHPReader,$index)
    {
        $sheet = $PHPReader->getSheet($index);//->getDrawingCollection(); #获取一个小文件 0 为第一个
        
        $data=$sheet->toArray();
        $data = $this->imageDataCase($sheet,$data);
        
        $title = $data[0];
        unset($data[0]);
        return [
            'title'=> $title,
            'data'=>$data
        ];
        
        //        内部实现
        /*   $highestRow = $sheet->getHighestRow(); // 取得总行数
         $highestColumn = $sheet->getHighestColumn(); // 取得总列数  返回的是 A,B,C 等
         $cellname = ['A','B','C','D','E','F','G','H','I','J',
         'K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'];
         $highestColumnNum = array_search($highestColumn, $cellname);  # 列的长度
         $arr  = [
         'title'=>'',
         'data' => '',
         ];
         for($j=1;$j<=$highestRow;$j++)
         {
         $rowdata = [];
         
         for ($i=0; $i<=$highestColumnNum; $i++) {
         if($i==0) {
         $rowdata[] = $PHPReader->getActiveSheet()->getCell($cellname[$i].$j)->getValue();//获取A列的值
         }else {
         $rowdata[] = $PHPReader->getActiveSheet()->getCell($cellname[$i].$j)->getValue();//获取A列的值
         }
         }
         
         if ( $j==1 ) {
         $arr['title'] = $rowdata;
         } else{
         $arr['data'][] = $rowdata;
         }
         }
         return $arr;*/
    }
    
    /**
     * 获取原始 数据
     * @param $PHPReader
     * @param $index
     * @return array
     */
    public function getOrigionData($PHPReader,$index)
    {
        $sheet = $PHPReader->getSheet($index); #获取一个小文件 0 为第一个
        $data = $sheet->toArray();
        
        $data = $this->imageDataCase($sheet,$data );
        return $data;
        
        /*   $highestRow = $sheet->getHighestRow(); // 取得总行数
         $highestColumn = $sheet->getHighestColumn(); // 取得总列数  返回的是 A,B,C 等
         $cellname = ['A','B','C','D','E','F','G','H','I','J',
         'K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'];
         $highestColumnNum = array_search($highestColumn, $cellname);  # 列的长度
         $arr  = [
         
         ];
         for($j=1;$j<=$highestRow;$j++)
         {
         $rowdata = [];
         
         for ($i=0; $i<=$highestColumnNum; $i++) {
         if($i==0) {
         $rowdata[] = $PHPReader->getActiveSheet()->getCell($cellname[$i].$j)->getValue();//获取A列的值
         }else {
         $rowdata[] = $PHPReader->getActiveSheet()->getCell($cellname[$i].$j)->getValue();//获取A列的值
         }
         }
         $arr[] = $rowdata;
         }
         return $arr;*/
    }
    
    /**
     * 字母表头 转换成 数组 index 下标
     * @param $abc
     * @return float|int
     */
    public  function ABC2decimal($abc){
        $ten = 0;
        $len = strlen($abc);
        for($i=1;$i<=$len;$i++){
            $char = substr($abc,0-$i,1);//反向获取单个字符
            
            $int = ord($char);
            $ten += ($int-65)*pow(26,$i-1);
        }
        return $ten;
    }
    /**
     * 读取图片
     * @param $sheet
     * @throws PHPExcel_Exception
     */
    public function imageDataCase($sheet,&$data)
    {
        //var_dump($GLOBALS);die();
        $url = $GLOBALS['config_cache']['UPLOAD_DIR']; # 数据库存储
        $imageFilePath=FRAMEWORK_PATH.'/..'.$url;//图片在本地存储的路径
        if (! file_exists ( $imageFilePath )) {
            mkdir("$imageFilePath", 0777, true);
        }
        //        var_dump($sheet->getDrawingCollection());die;
        //处理图片
        foreach($sheet->getDrawingCollection() as $img) {
            list($startColumn,$startRow) = PHPExcel_Cell::coordinateFromString($img->getCoordinates());//获取图片所在行和列
            $imageFileName = $img->getCoordinates() . mt_rand(100, 999);
            switch($img->getMimeType()) {
                case 'image/jpg':
                    $imageFileName.='.jpg';
                    imagejpeg($img->getImageResource(),$imageFilePath.$imageFileName);
                    break;
                case 'image/jpeg':
                    $imageFileName.='.jpg';
                    imagejpeg($img->getImageResource(),$imageFilePath.$imageFileName);
                    break;
                case 'image/gif':
                    $imageFileName.='.gif';
                    imagegif($img->getImageResource(),$imageFilePath.$imageFileName);
                    break;
                case 'image/png':
                    $imageFileName.='.png';
                    imagepng($img->getImageResource(),$imageFilePath.$imageFileName);
                    break;
            }
            $startColumn = $this->ABC2decimal($startColumn);//由于图片所在位置的列号为字母，转化为数字
            $data[$startRow-1][$startColumn];
            if($data[$startRow-1][$startColumn]) {
                $data[$startRow-1][$startColumn].=','.$url.$imageFileName;//把图片插入到数组中
            }else {
                $data[$startRow-1][$startColumn]=$url.$imageFileName;//把图片插入到数组中
            }
        }
        
        # 空格 数据处理
        foreach ($data as &$val) {
            
            foreach ($val as &$item) {
                $item = trim($item);
            }
        }
        
        return $data;
    }
    
    
    /**
     * 获取实例1
     * @return Excel
     */
    public static function getInstace()
    {
        if(! self::$instace instanceof self) {
            self::$instace = new Excel();
        }
        return self::$instace;
    }
    
}

