設置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
爲例而已,還可以是其他值,比如AZ
,ZZ
等。最後一個是高度,因爲這個值是依據用戶錄入的,所以不確定,所以傳入0