設置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

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