小編給大家分享一下PHP切割excel大文件的方法,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
成都創(chuàng)新互聯(lián)專注于平陰網(wǎng)站建設服務及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗。 熱誠為您提供平陰營銷型網(wǎng)站建設,平陰網(wǎng)站制作、平陰網(wǎng)頁設計、平陰網(wǎng)站官網(wǎng)定制、成都微信小程序服務,打造平陰網(wǎng)絡公司原創(chuàng)品牌,更為您提供平陰網(wǎng)站排名全網(wǎng)營銷落地服務。
利用phpspreadsheet可以輕松的解析excel文件,但是phpspreadsheet的內(nèi)存消耗也是比較大的,我試過解析將近5M的純文字excel內(nèi)存使用量就會超過php默認的最大內(nèi)存128M。
當然這可以用調(diào)節(jié)內(nèi)存大小的方法來解決,但是在并發(fā)量大的時候就比較危險了。所以今天介紹下一種方法,利用phpspreadsheet對excel文件進行切割,這是個拿時間換空間的方法所以一般對時效性要求低的需求可以使用。
先放個phpspreadsheet官網(wǎng)提供的一個功能readCell,我們就可以利用這個功能來進行切割。
首先對excel文件進行預讀,主要是獲取所有的工作表以及工作表下面的數(shù)據(jù)行數(shù),這個階段readCell方法一直返回的都是false,我們只需要記錄readCell進來的工作表及數(shù)據(jù)行數(shù)。
然后就是對獲取到的記錄進行分析,確定每部分數(shù)據(jù)需要裝多少行原始excel的數(shù)據(jù),需要注意的是為了避免內(nèi)容混淆,不要講兩個工作表的內(nèi)容切到一起。
最后就是循環(huán)分析的數(shù)據(jù)和再次利用readCell獲取每部分數(shù)據(jù),注意每次讀取文件后都要利用disconnectWorksheets方法清理phpspreadsheet的內(nèi)存。
經(jīng)過我自己的測試發(fā)現(xiàn),利用該方法解析5M的excel文件,平均只需要21M的內(nèi)存就可以搞定!
record[$worksheetName]) ) { if ($this->lastRow != $row) { $this->record[$worksheetName] ++; $this->lastRow = $row; } } else { $this->record[$worksheetName] = 1; $this->lastRow = $row; } return false; } } /** * 解析過濾類 * @author wangyelou * @date 2018-07-30 */ class MyreadFilter implements \PhpOffice\PhpSpreadsheet\Reader\IReadFilter { public $startRow; public $endRow; public $worksheetName; public function readCell($column, $row, $worksheetName = '') { if ($worksheetName == $this->worksheetName && $row >= ($this->startRow+1) && $row <= ($this->endRow+1)) { return true; } return false; } } /** * 切割類 * @author wangyelou * @date 2018-07-30 */ class excelCut { public $cutNum = 5; public $returnType = 'Csv'; public $fileDir = '/tmp/'; public $log; /** * 切割字符串 * @param $str * @return array|bool */ public function cutFromStr($str) { try { $filePath = '/tmp/' . time() . mt_rand(1000, 9000) . $this->returnType; file_put_contents($filePath, $str); if (file_exists($filePath)) { $result = $this->cutFromFile($filePath); unlink($filePath); return $result; } else { throw new Exception('文件寫入錯誤'); } } catch (Exception $e) { $this->log = $e->getMessage(); return false; } } /** * 切割文件 * @param $file * @return array|bool */ public function cutFromFile($file) { try { $cutRules = $this->readaheadFromFile($file); $dir = $this->getFileDir($file); $returnType = $this->returnType ? $this->returnType : 'Csv'; $results = array(); //初始化讀 $myFilter = new MyreadFilter(); $inputFileType = \PhpOffice\PhpSpreadsheet\IOFactory::identify($file); $reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader($inputFileType); $reader->setReadDataOnly(true); $reader->setReadFilter($myFilter); foreach ($cutRules as $sheetName => $rowIndexRange) { //讀 list($myFilter->startRow, $myFilter->endRow, $myFilter->worksheetName) = $rowIndexRange; $spreadsheetReader = $reader->load($file); $sheetData = $spreadsheetReader->setActiveSheetIndexByName($myFilter->worksheetName)->toArray(null, false, false, false); $realDatas = array_splice($sheetData, $myFilter->startRow, ($myFilter->endRow - $myFilter->startRow + 1)); $spreadsheetReader->disconnectWorksheets(); unset($sheetData); unset($spreadsheetReader); //寫 $saveFile = $dir . $sheetName . '.' . $returnType; $spreadsheetWriter = new \PhpOffice\PhpSpreadsheet\Spreadsheet(); foreach ($realDatas as $rowIndex => $row) { foreach ($row as $colIndex => $col) { $spreadsheetWriter->getActiveSheet()->setCellValueByColumnAndRow($colIndex+1, $rowIndex+1, $col); } } $writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheetWriter, $returnType); $writer->save($saveFile); $spreadsheetWriter->disconnectWorksheets(); unset($spreadsheetWriter); $results[] = $saveFile; } return $results; } catch (Exception $e) { $this->log = $e->getMessage(); return false; } } /** * 預讀文件 */ public function readaheadFromFile($file) { if (file_exists($file)) { //獲取統(tǒng)計數(shù)據(jù) $myFilter = new MyAheadreadFilter(); $inputFileType = \PhpOffice\PhpSpreadsheet\IOFactory::identify($file); $reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader($inputFileType); $reader->setReadDataOnly(true); //只讀數(shù)據(jù) $reader->setReadFilter($myFilter); $spreadsheet = $reader->load($file); //$sheetData = $spreadsheet->getActiveSheet()->toArray(null, false, false, false); list($fileName,) = explode('.', basename($file)); $datas = array(); $averageNum = ceil(array_sum($myFilter->record) / $this->cutNum); foreach ($myFilter->record as $sheetName => $count) { for ($i=0; $ifileDir . $fullName . '/'; mkdir($path, 0777); chmod($path, 0777); if (is_dir($path)) { return $path; } else { $this->log = "mkdir {$path} failed"; return false; } } }
以上是PHP切割excel大文件的方法的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學習更多知識,歡迎關注創(chuàng)新互聯(lián)行業(yè)資訊頻道!