bzzear 2017-08-14 10:40:24 12222次浏览 5条评论 34 5 0
<?php
namespace common\helpers;

use \PHPExcel;
use \PHPExcel_Reader_Excel2007;
use \PHPExcel_Reader_Excel5;
use \PHPExcel_IOFactory;

class Excel{

    /**
     * 读取excel表格中的数据
     * @author xxx
     * @dateTime 2017-06-12T09:39:01+0800
     * @param    string $filePath excel文件路径
     * @param    integer $startRow 开始的行数
     * @return   array
     */
    public function getExcelData($filePath, $startRow = 1) {
        $PHPExcel = new PHPExcel();
        /**默认用excel2007读取excel,若格式不对,则用之前的版本进行读取*/
        $PHPReader = new PHPExcel_Reader_Excel2007();
        //setReadDataOnly Set read data only 只读单元格的数据,不格式化 e.g. 读时间会变成一个数据等
        $PHPReader->setReadDataOnly(TRUE);
        if (!$PHPReader->canRead($filePath)) {
            $PHPReader = new PHPExcel_Reader_Excel5();
            //setReadDataOnly Set read data only 只读单元格的数据,不格式化 e.g. 读时间会变成一个数据等
            $PHPReader->setReadDataOnly(TRUE);
            if (!$PHPReader->canRead($filePath)) {
                echo 'can not read excel';
                return;
            }
        }

        $PHPExcel = $PHPReader->load($filePath);
        //获取sheet的数量
        $sheetCount = $PHPExcel->getSheetCount();
        //获取sheet的名称
        $sheetNames = $PHPExcel->getSheetNames();

        //获取所有的sheet表格数据
        $excleDatas = array();
        $emptyRowNum = 0;
        for ($i = 0; $i < $sheetCount; $i++) {
            /**读取excel文件中的第一个工作表*/
            $currentSheet = $PHPExcel->getSheet($i);
            /**取得最大的列号*/
            $allColumn = $currentSheet->getHighestColumn();
            /**取得一共有多少行*/
            $allRow = $currentSheet->getHighestRow();

            $arr = array();
            for ($currentRow = $startRow; $currentRow <= $allRow; $currentRow++) {
                /**从第A列开始输出*/
                for ($currentColumn = 'A'; $currentColumn <= $allColumn; $currentColumn++) {
                    $val = $currentSheet->getCellByColumnAndRow(ord($currentColumn) - 65, $currentRow)->getValue();
                    $arr[$currentRow][] = trim($val);
                }
                $arr[$currentRow] = array_filter($arr[$currentRow]);
                //统计连续空行
                if(empty($arr[$currentRow]) && $emptyRowNum <= 50) {
                    $emptyRowNum++ ;
                } else {
                    $emptyRowNum = 0;
                }
                //防止坑队友的同事在excel里面弄出很多的空行,陷入很漫长的循环中,设置如果连续超过50个空行就退出循环,返回结果
                //连续50行数据为空,不再读取后面行的数据,防止读满内存
                if($emptyRowNum > 50) {
                    break;
                }
            }
            $excleDatas[$i] = $arr; //多个sheet的数组的集合
        }

        //这里我只需要用到第一个sheet的数据,所以只返回了第一个sheet的数据
        $returnData = $excleDatas ? array_shift($excleDatas) : [];

        //第一行数据就是空的,为了保留其原始数据,第一行数据就不做array_fiter操作;
        $returnData = $returnData && isset($returnData[$startRow]) && !empty($returnData[$startRow])  ? array_filter($returnData) : $returnData;
        return $returnData;
        //return $excleDatas  ? array_filter(array_shift($excleDatas)) : [];
    }

    /**
     * 生成excel数据表
     * e.g.
     * $fields = [
     *     ['key' => 'province', 'name' => '省', 'required' => false]
     *     ['key' => 'city', 'name' => '市', 'required' => true]
     *     ['key' => 'district', 'name' => '区/县', 'required' => true]
     *     ['key' => 'street', 'name' => '街道', 'required' => true]
     * ];
     *
     * $dataList = [
     *     ['province' => 'xx省' , 'city'=>'xx市' , 'district' => 'xx县' ,'street' => 'xx街道'],
     *     ['province' => 'xx省' , 'city'=>'xx市' , 'district' => 'xx县' ,'street' => 'xx街道'],
     *     ['province' => 'xx省' , 'city'=>'xx市' , 'district' => 'xx县' ,'street' => 'xx街道'],
     *     ['province' => 'xx省' , 'city'=>'xx市' , 'district' => 'xx县' ,'street' => 'xx街道'],
     * ]
     *
     * @author xxx
     * @dateTime 2017-07-18T15:19:04+0800
     * @param    array $fileds 表头数据
     * @param    array $dataList 导出数据的数组
     * @param    string $fileName 生成的文件名
     * @return   mix
     */
    public function createExcelFromData($fileds, $dataList = array(),$fileName = 'data') {
        if(!count($fileds || !count($dataList))) {return false;}
        $dataList = array_values($dataList);
        $fieldConfig = array();
        $objPHPExcel = new PHPExcel();
        $objPHPExcel->setActiveSheetIndex(0);
        $i = 0;
        foreach ($fileds as $key => $value) {
            $cloumStr = chr(ord("A") + $key);
            $column = $cloumStr . "1";
            //必填字段列表标红
            $required = isset($value['required']) ? $value['required'] : false;
            if ($required == true) {
                //把必填字段标红
                $objPHPExcel->getActiveSheet()->getStyle($column)->getFont()->getColor()->setARGB('FF0000');
            }
            $objPHPExcel->getActiveSheet()->setCellValue($column, $value['name']);
            $i++;
        }

        $filedKeys = array_column($fileds, 'key');
        $list = [];
        ob_start();
        foreach ($dataList as $key => $value) {
            if ($key % 5000 == 0) {
                ob_flush();
                flush();
            }
            $num = $key + 2;
            for ($j = 0; $j < $i; $j++) {
                $cloumStr = chr(ord("A") + $j);
                $column = $cloumStr . $num;
                if(isset($value[$filedKeys[$j]])) {
                    $objPHPExcel->getActiveSheet()->setCellValue($column, $value[$filedKeys[$j]]);
                } else {
                    $objPHPExcel->getActiveSheet()->setCellValue($column, '');
                }
            }
        }

        //设置必填字段字体颜色
        $objPHPExcel->getActiveSheet()->setTitle('Simple');
        $objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
        if(php_sapi_name() != 'cli'){
            $fileName = basename($fileName);
            $fileName = iconv("utf-8", "gb2312", $fileName);
            header('Content-Type: application/vnd.ms-excel');
            header('Content-Disposition: attachment;filename='.$fileName);
            header('Cache-Control: max-age=0');
            $objWriter->save('php://output'); //文件通过浏览器下载
        }else{

            $dirname = dirname($fileName);
            if ($dirname != '.') {
                //文件路径如果不存在则递归创健
                CommonFun::recursionMkDir($dirname);
            }
            $objWriter->save($fileName); //脚本方式运行,保存在指定目录
            if(!file_exists($fileName)) {
                return false;
            }
            return true;
        }
    }
}

觉得很赞
  • 评论于 2017-11-05 17:41 举报

    弱弱的请教一下大神:$filePath,该怎么写?也就是在Yii2.0中,需要读取的excel文件的路径的具体写法。我想把excel放到根目录下的web目录下,可总是读取不到,提示文件不存在。

  • 评论于 2017-11-06 16:14 举报

    web下面直接读取就好了
    如果在根目录下就用 dirname(Yii::$app->basePath) 拼接下你的路径

  • 评论于 2017-12-25 11:06 举报

    补充1:

    在使用的过程中遇到了问题,①ord函数只能转义字符串首个字母的ASCII值,当excel表格的列超过Z列的时候(AA,AB,AC,...)的时候会出bug,
    这个时候只能获取到第一列数据的二维数组;②读取单元格内内容为数字为0的数据被array_filter过滤了;③增加第三个参数,读取某个sheet的数据, 不需要读取所以sheet的数据。读取excel数据的方法作出如下修改:

    
    public function getExcelData($filePath, $startRow = 1,$sheetIndex = 0) {
        $PHPExcel = new PHPExcel();
        /**默认用excel2007读取excel,若格式不对,则用之前的版本进行读取*/
        $PHPReader = new PHPExcel_Reader_Excel2007();
        //setReadDataOnly Set read data only 只读单元格的数据,不格式化 e.g. 读时间会变成一个数据等
        $PHPReader->setReadDataOnly(TRUE);
        if (!$PHPReader->canRead($filePath)) {
            $PHPReader = new PHPExcel_Reader_Excel5();
            //setReadDataOnly Set read data only 只读单元格的数据,不格式化 e.g. 读时间会变成一个数据等
            $PHPReader->setReadDataOnly(TRUE);
            if (!$PHPReader->canRead($filePath)) {
                echo 'can not read excel';
                return;
            }
        }
    
        $PHPExcel = $PHPReader->load($filePath);
        //获取sheet的数量
        $sheetCount = $PHPExcel->getSheetCount();
        //获取sheet的名称
        $sheetNames = $PHPExcel->getSheetNames();
    
        //获取所有的sheet表格数据
        $emptyRowNum = 0;
        $i = $sheetIndex ;
        //超过范围
        if($i > ($sheetCount-1))
        {
            echo 'count error';
            return;
        }
    
        /**默认读取excel文件中的第一个工作表*/
        $currentSheet = $PHPExcel->getSheet($i);
        /**取得最大的列号*/
        $allColumn = $currentSheet->getHighestColumn();
        $allColumnIndex = PHPExcel_Cell::columnIndexFromString($allColumn);
        /**取得一共有多少行*/
        $allRow = $currentSheet->getHighestRow();
    
        $arr = array();
        for ($currentRow = $startRow; $currentRow <= $allRow; $currentRow++) {
            /**从第A列开始输出*/
            $ifhasZero = false;
            for ($currentColumn = 0; $currentColumn <= $allColumnIndex; $currentColumn++) {
                $val = $currentSheet->getCellByColumnAndRow($currentColumn, $currentRow)->getValue();
                if($val == '0') $ifhasZero = true;
                $arr[$currentRow][] = trim($val);
            }
    
            if ($ifhasZero == true) {
                foreach ($arr[$currentRow] as $key => $value) {
                    if($value === '') {
                        unset($arr[$currentRow][$key]);
                    }
                }
            }
    
            $arr[$currentRow] = $ifhasZero ? $arr[$currentRow] : array_filter($arr[$currentRow]);
            //统计连续空行
            if(empty($arr[$currentRow]) && $emptyRowNum <= 50) {
                $emptyRowNum++ ;
            } else {
                $emptyRowNum = 0;
            }
            //防止坑队友的同事在excel里面弄出很多的空行,陷入很漫长的循环中,设置如果连续超过50个空行就退出循环,返回结果
            //连续50行数据为空,不再读取后面行的数据,防止读满内存
            if($emptyRowNum > 50) {
                break;
            }
        }
    
        //只返回了第一个sheet的数据
        $returnData = $arr;
    
        //第一行数据就是空的,为了保留其原始数据,第一行数据就不做array_fiter操作;
        $returnData = $returnData && isset($returnData[$startRow]) && !empty($returnData[$startRow])  ? array_filter($returnData) : $returnData;
        return $returnData;
    }
    
    
    
    觉得很赞
  • 评论于 2018-03-07 09:47 举报

    导出大批量的数据呢?

    1 条回复
    评论于 2018-12-14 10:49 回复

    导出大批量数据看这个:https://www.yiichina.com/code/1863

  • 评论于 2018-12-04 16:06 举报

    添加单元格数据验证的方法

    /**
     * e.g.
     * addCellDataValidation($objPHPExcel->getActiveSheet(),'M4:M1000','"选择题,组合题,判断题,填空题,连线题,排序题,应用题"');
     *
     * 设置单元格公式(现在只用到数据验证)
     * @author ****
     * @dateTime 2018-09-27T14:06:27+0800
     * @param    PHPExcel_Worksheet $workSheet 工作表
     * @param    string $rangeCell e.g.   B3  A1:A9  A1:C9
     * @param    string $formula 公式
     * @param    string $errorTitle 错误提示标题
     * @param    string $errorMsg 错误提示信息
     * @param    string $prompTitle 标题
     */
    public static function addCellDataValidation(
            PHPExcel_Worksheet $workSheet,
            $rangeCell,
            $formula,
            $errorTitle = '输入的值有误',
            $errorMsg = '您输入的值不在下拉框列表内',
            $prompTitle = '') {
        $cells = PHPExcel_Cell::extractAllCellReferencesInRange($rangeCell);
        if ($cells) {
            foreach ($cells as $key => $value) {
                $objValidation = $workSheet->getCell($value)->getDataValidation();
                $objValidation->setType(PHPExcel_Cell_DataValidation::TYPE_LIST)
                    ->setErrorStyle(PHPExcel_Cell_DataValidation::STYLE_INFORMATION)
                    ->setAllowBlank(false)
                    ->setShowInputMessage(true)
                    ->setShowErrorMessage(true)
                    ->setShowDropDown(true)
                    ->setErrorTitle($errorTitle)
                    //->setError($errorMsg)
                    ->setPromptTitle($prompTitle)
                    ->setFormula1($formula);
            }
        }
    }
    
    Excel::addCellDataValidation($objPHPExcel->getSheet(0),'G2:G1000','"故事类,非故事类"');
    Excel::addCellDataValidation($objPHPExcel->getSheet(0),'G2:G1000','sheet1!$A$2:$A$10');
    
您需要登录后才可以评论。登录 | 立即注册