数千や数万行あるエクセルファイルをPHPExcelで処理しようとすると、「Allowed memory size of *** exhausted」と出力されることがある。コマンドラインの場合は Killed と出力され強制終了することがある。
原因がメモリ使用量の超過の場合、下記のいずれかで対処する。
##必要なデータのみ読み込む##
罫線や背景色などの装飾は不要な場合、セルの値や式(SUMなど)のみ読み込んだり、特定のシートのみ読み込むようにすることでメモリ使用量を節約する。
$objReader = PHPExcel_IOFactory::createReader('Excel2007');
$objReader->setReadDataOnly(true); //罫線や背景色などの装飾を無視して、セルの値や式(SUMなど)のみを読み込む
$wsList = $objReader->listWorksheetNames($excelFile); //シート名を配列で取得
$objReader->setLoadSheetsOnly($wsList[0]); //シート名を指定して特定のシートのみ読み込む
//$objReader->setLoadSheetsOnly( array($wsList[0], $wsList[1]) );//複数シートを読み込む場合
##ループ処理の場合は1回のループ終了ごとにメモリを解放する##
複数のエクセルファイルに対してループで処理を行っている場合などは、ループ回数が増えるたびにメモリ使用量が増加していくので、1回のループが終了するたびに次を実行しメモリを解放する。
$objExcel->disconnectWorksheets();
unset($objExcel);
次のように使用する。
$objReader = PHPExcel_IOFactory::createReader('Excel2007');
foreach($excelFiles as $excelFile){
$objExcel = $objReader->load($excelFile);
/* 何らかの処理 */
$objExcel->disconnectWorksheets();
unset($objExcel);
}
##オブジェクトの保存先をメモリ以外にする##
PHPExcel_CachedObjectStorageFactory で一時データの保存先をメモリ以外に変更する。
PHPExcel_CachedObjectStorageFactory::cache_in_memory
デフォルト。メモリにセルオブジェクトをそのままメモリに保存 PHPExcel_CachedObjectStorageFactory::cache_in_memory_serialized
シリアライズされたオブジェクト配列でメモリ上に保存
PHPExcel_CachedObjectStorageFactory::cache_in_memory_gzip
cache_in_memory_serializedをさらにgzip圧縮して保存
PHPExcel_CachedObjectStorageFactory::cache_igbinary
igbinary拡張を用いて、メモリに保存
PHPExcel_CachedObjectStorageFactory::cache_to_discISAM
一時ファイルに保存
PHPExcel_CachedObjectStorageFactory::cache_to_phpTemp
php://tempに保存
PHPExcel_CachedObjectStorageFactory::cache_to_apc
APCを利用して保存
PHPExcel_CachedObjectStorageFactory::cache_to_memcache
memcacheに保存
PHPExcel_CachedObjectStorageFactory::cache_to_wincache
wincacheに保存
PHPExcel_CachedObjectStorageFactory::cache_to_sqlite
PHPExcel_CachedObjectStorageFactory::cache_to_sqlite3
SQLiteに保存
//php://tempに保存する場合はキャッシュサイズを定義する
$cacheMethod = PHPExcel_CachedObjectStorageFactory::cache_to_phpTemp;
$cacheSettings = array( 'memoryCacheSize' => '32MB');
PHPExcel_Settings::setCacheStorageMethod($cacheMethod, $cacheSettings);
//一時ファイルに保存保存する場合は一時ファイルのパスを定義する
//$cacheMethod = PHPExcel_CachedObjectStorageFactory::cache_to_discISAM;
//$cacheSettings = array('dir' => '/tmp');
//PHPExcel_Settings::setCacheStorageMethod($cacheMethod, $cacheSettings);
$objExcel = PHPExcel_IOFactory::load($excelFile);
##PHPが確保できる最大メモリの値を上げる##
ini_set や .htaccess、 php.ini にて memory_limit を設定