设置PHPExcel读取WPS文件时内存耗尽的问题

设置PHPExcel读取WPS文件时内存耗尽的问题

用过PHPExcel的都知道这玩意的坑不是一般的少啊,偏偏一般用户对excel有着莫名的偏爱。

这次遇到的问题就是使用这玩意读取WPS生成的excel,或者使用WPS打开过的excel时,老是会报内存耗尽之类的问题,具体问题当时忘记截图了。

好像是因为获取excel的数据内容的宽度和高度时,明明页面中没有值,但是WPS处理过的excel都会被PHPExcel以最大的高度和宽度读取数据,导致内存耗尽。所以读取文件时,需要加上过滤器。

过滤器类

namespace PHPExcelAssist;

class Filter implements \PHPExcel_Reader_IReadFilter{
    protected $workSheetName;
    protected $endColumn;
    protected $endRow;

    /**
     * 构造函数,指定截止行,截止列
     * Filter constructor.
     * @param $workerSheetName string|array 表空间,支持多个表空间
     * @param $endColumn string 截止列
     * @param int $endRow 截止行
     */
    public function __construct($workerSheetName,$endColumn,$endRow=0)
    {
        $this->workSheetName=$workerSheetName;
        $this->endColumn=$endColumn;
        $this->endRow=$endRow;
    }

    /**
     * 实现过滤器
     * @param \Column $column 当前列数
     * @param \Row $row 当前行数
     * @param string $worksheetName 表名
     * @return bool
     */
    public function readCell($column, $row, $worksheetName = '') {
        // 只设置了一个表空间
        if(!is_array($this->workSheetName) && $worksheetName!=$this->workSheetName){
            return false;
        }else{
            // 设置了多个表空间
            if(is_array($this->workSheetName) && !in_array($worksheetName,$this->workSheetName)){
                return false;
            }
        }
        // 设置了截止行,且当前行超过了指定行
        if($this->endRow!=0 && $row>$this->endRow){
            return false;
        }
        // 如果当前行的长度超过指定截止行,则也设置成错误
        if(strlen($column)>strlen($this->endColumn)){
            return false;
        }
        return true;
    }
}

具体使用

public function organizeExcelData($excelFileInfo){
        try{
            // 加载上传文件
            $fileType=\PHPExcel_IOFactory::identify($excelFileInfo['tmp_name']);// 获取读取文件的类型
            $objReader=\PHPExcel_IOFactory::createReader($fileType);// 创建对应文件的读取器
            $excelInstance=$objReader->setReadDataOnly(true)->setReadFilter(
              	// 调用过滤器
                new Filter(
                    0,
                    "T",
                    0
                )
            )->load($excelFileInfo['tmp_name']);// 读取文件
            $contentSheet=$excelInstance->getSheet(0);
         		// 这里的$contentSheet就是经过过滤的值,其中的宽度已经经过限制,基本上不会报内存耗尽之类的问题了
            return $contentSheet;
        }catch (Exception $e){
            throw new Exception("在调用底层封装类处理Excel文件时出错:".$e->getMessage());
        }
    }

可以看到这里调用时传入了3个值,第一个值是sheet的值,可以传入数组或者具体的值,这里因为只有一个sheet,所以传入0,第二个是宽度,这个在设计导入的Excel的时候肯定是定好的,所以可以传入对应的具体值,这里以T为例而已,还可以是其他值,比如AZZZ等。最后一个是高度,因为这个值是依据用户录入的,所以不确定,所以传入0

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