web-dev-qa-db-ja.com

PHPExcelでメモリが使い果たされるのを修正する方法

致命的なエラー:行269のD:\ xampplite\htdocs\Scraper\PHPExcel\Reader\Excel2007.phpで、許可されたメモリサイズ134217728バイトを使い果たしました(1078799バイトを割り当てようとしました)。

私の128M PHPメモリ制限は、PHPExcelで約350 KBの小さなExcelファイルを開こうとしただけでも、すぐに使い果たされます。

ただし、構成でメモリ制限を増やすことはできますが、これを修正するための代替手段があるかどうかを確認するのは素晴らしいことです。

24
Shubham

PHPExcelで作業する場合、ファイルサイズはブックファイルの適切な尺度ではありません。行と列(つまりセル)の数はより重要です。

PHPExcelコード自体のフットプリントは、アクセスされるコンポーネントに応じて10〜25MBです。

現在、ワークブックの各セルは、平均で1kのメモリ(キャッシュなし)または64ビットで1.6kを消費しますPHP-32ビットPHP現時点では-(たとえば)31列(248,000セル)の8000行のワークシートは約242MBになります。セルキャッシュ(php:// tempやDiskISAMなど)を使用すると、約3分の1なので、8000行x 31列は約80MB必要です。

メモリ使用量を減らすのに役立つ多くのオプションがあります。

PHPExcelでセルキャッシングを使用していますか?

require_once './Classes/PHPExcel.php';

$cacheMethod = PHPExcel_CachedObjectStorageFactory:: cache_to_phpTemp;
$cacheSettings = array( ' memoryCacheSize ' => '8MB');
PHPExcel_Settings::setCacheStorageMethod($cacheMethod, $cacheSettings);

$objReader = PHPExcel_IOFactory::createReader('Excel2007');
$objPHPExcel = $objReader->load("test.xlsx");

ワークシートのデータにアクセスするだけで、セルの書式設定にアクセスする必要がない場合は、ワークブックからの書式設定情報の読み取りを無効にすることができます。

$objReader = PHPExcel_IOFactory::createReader('Excel2007');
$objReader->setReadDataOnly(true);
$objPHPExcel = $objReader->load("test.xlsx");

ワークブックのワークシートのすべてではなく一部のみにアクセスする必要がある場合は、それらのワークシートのみをロードできます。

$objReader = PHPExcel_IOFactory::createReader('Excel2007');
$objReader->setLoadSheetsOnly( array("Worksheet1", "Worksheet2") );
$objPHPExcel = $objReader->load("test.xlsx");

ワークシート内の特定のセルのみを読み取りたい場合は、フィルターを追加できます。

class MyReadFilter implements PHPExcel_Reader_IReadFilter
{
    public function readCell($column, $row, $worksheetName = '') {
        // Read title row and rows 20 - 30
        if ($row == 1 || ($row >= 20 && $row <= 30)) {
            return true;
        }

        return false;
    }
}

$objReader = PHPExcel_IOFactory::createReader('Excel2007');
$objReader->setReadFilter( new MyReadFilter() );
$objPHPExcel = $objReader->load("test.xlsx");

これらの手法はすべて、メモリ要件を大幅に削減できます。

59
Mark Baker

PHPExcelはメモリリークで知られています。 PHPExcelが使用するメモリの割合を必要とする以下を使用することをお勧めします

1)読み取り用: PHP-Excel-Reader

2)書き込みの場合: Pear Spreadsheet Excel Writer

4
shamittomar

データファイルがXバイトしかないからといって、XバイトのRAMを使用しているわけではありません。たとえば、$ _ SESSION配列の4Kのデータのみが、ロード時に64KのRAMを使用します。それは、コードがそのデータをどのように処理しているかに依存します。正解は、ラムの量を増やすことです。

また、これがXLSXファイルである場合、それらはZipされたXMLドキュメントです。テキストファイルは、1/2よりも圧縮率が高いため、350K XLSXファイルは1MBのExcelファイルに簡単にできます。

3
TravisO

注意すべきことの1つは、空のセルです。

同じ問題がありましたが、データが800行しかなく、スクリプトも読み取ることができませんでした。タイムアウトとメモリ不足エラーの両方が修正された場合。

@Mark Ba​​kerが細胞について言った何かが私に考えさせられました。空のセルがたくさんあり、データのあるセルのみを新しいブックにコピーすると、1秒で実行できることに気付きました。

これが誰かを助けることを願っています。

1
frostymarvelous

Xdebugは、phpのプロファイラー/デバッガーであり、メモリの使用状況と関数呼び出しをトレースして、問題の場所を突き止めるのに役立ちます。そして、インストールが簡単で、ほとんどのLinuxディストリビューションのリポジトリには、「yum install xdebug」、「apt-get install xdebug」があります。

1
Chris

知りたい場合は、 xhprof を使用できます。このリンクによると、メモリ使用量を追跡できます...

1
greg0ire
$objReader = PHPExcel_IOFactory::createReader('Excel2007');
$objReader->setReadDataOnly(true);
$objPHPExcel = $objReader->load("test.xlsx");

これだけのコードで十分です

0
Annie Chandel

この投稿では、PHPExcelリーダーを閉じる方法について説明しています: php-Excel-readerでExcelファイルを閉じる方法 複数のExcelファイルを同時に開いている場合、しかし、実際にはそれらすべてを同時に必要としないので、各ファイルのリーダーを1つずつ開いたり閉じたり(つまり、設定を解除)することもできます。ところで、リーダーに同じ変数名を使用すると、「設定解除」操作には十分です。

0