web-dev-qa-db-fra.com

Comment réparer la mémoire s'épuisant avec PHPExcel?

Erreur fatale: taille de mémoire autorisée de 134217728 octets épuisés (essayé de Allouer 1078799 octets) dans D:\xampplite\htdocs\Scraper\PHPExcel\Reader\Excel2007.php à la ligne 269

Ma limite de mémoire de 128M PHP s'épuise rapidement même lorsque j'essaie simplement d'ouvrir un petit fichier Excel d'environ 350 Ko avec PHPExcel. 

Bien que je puisse augmenter la limite de mémoire dans la configuration, il sera intéressant de voir s'il existe des alternatives pour résoudre ce problème.

18
Shubham

La taille de fichier n'est pas une bonne mesure pour les fichiers de classeur lorsque vous travaillez avec PHPExcel. Le nombre de lignes et de colonnes (c.-à-d. Les cellules) est plus important.

Le code PHPExcel lui-même a une empreinte de 10 à 25 Mo, en fonction des composants utilisés.

À l'heure actuelle, chaque cellule d'un classeur occupe en moyenne 1 Ko de mémoire (sans aucune mise en cache) ou 1,6 Ko sur PHP 64 bits - je supposerai pour le moment 32 bits PHP - donc ( par exemple) une feuille de calcul de 8 000 lignes avec 31 colonnes (248 000 cellules) fera environ 242Mo. Avec la mise en cache de cellules (telle que php: // temp ou DiskISAM), cela peut être réduit à environ un tiers, de sorte que les 8000 lignes de 31 colonnes nécessiteront environ 80 Mo.

Un certain nombre d'options sont disponibles pour vous aider à réduire l'utilisation de la mémoire:

Utilisez-vous la mise en cache de cellules avec 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");

Si vous devez uniquement accéder aux données de vos feuilles de calcul et n'avez pas besoin d'accéder à la mise en forme de la cellule, vous pouvez désactiver la lecture des informations de mise en forme à partir du classeur:

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

Si vous devez uniquement accéder à certaines feuilles de calcul du classeur, mais pas à toutes, vous pouvez uniquement charger ces feuilles de calcul:

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

si vous souhaitez uniquement lire certaines cellules dans les feuilles de calcul, vous pouvez ajouter un filtre:

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");

Toutes ces techniques peuvent réduire considérablement les besoins en mémoire.

54
Mark Baker

PHPExcel est connu pour ses fuites de mémoire. Je vous conseille d’utiliser les éléments suivants qui nécessitent a FRACTION de la mémoire utilisée par PHPExcel:

1) Pour la lecture: PHP-Excel-Reader

2) Pour l’écriture: Tableur Excel

4
shamittomar

Ce n'est pas parce que le fichier de données ne contient que X octets que X octets de mémoire vive sont utilisés. Par exemple, seuls 4 Ko de données dans un tableau $ _SESSION utilisent 64 Ko de RAM lorsqu'il est chargé. Cela dépend simplement de ce que le code fait avec ces données. La bonne réponse est d'augmenter la quantité de bélier.

De plus, s’il s’agit d’un fichier XLSX, il s’agit de documents XML compressés. Fichiers texte Zip beaucoup plus serré que 1/2, votre fichier 350K XLSX est facilement un fichier Excel de 1 Mo.

3
TravisO

Vous devez également noter les cellules vides.

J'ai eu le même problème, seulement 800 lignes de données et le script n'a même pas été en mesure de lire . Les délais d'expiration et les erreurs de mémoire insuffisante ont été corrigés.

Quelque chose que Mark Baker a dit à propos des cellules m'a fait réfléchir. J'ai remarqué que j'avais plein de cellules vides et que je ne copiais que les cellules contenant des données dans un nouveau classeur, le tout fonctionnait en une seconde. 

J'espère que ça aide quelqu'un.

1
frostymarvelous

Xdebug est un profileur/débogueur pour php et peut vous aider à retracer l'utilisation de la mémoire et les appels fonctionnels afin de déterminer la cause du problème. Et c'est facile à installer, la plupart des distributions Linux l'ont dans un référentiel, "yum install xdebug", "apt-get install xdebug".

1
Chris

Si vous voulez le savoir, vous pouvez utiliser xhprof . Selon ce lien, vous pouvez suivre l'utilisation de la mémoire avec celui-ci ...

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

Ce code suffit

0
Annie Chandel

Cet article explique comment fermer un lecteur PHPExcel: Comment fermer un fichier Excel dans php-Excel-reader Si vous ouvrez plusieurs fichiers Excel simultanément, sans en avoir réellement besoin tous à la En même temps, vous pouvez alors essayer d’ouvrir et de fermer (c’est-à-dire de désélectionner) les lecteurs de chaque fichier, un par un. Btw, en utilisant le même nom de variable pour les lecteurs suffirait pour l'opération "unsetting".

0
Mian Lu