2013-05-09 5 views
1

Je traite 700 lignes de données dans mon Excel.Optimisation de setCellValueExplicit() dans PHPExcel

Et j'ajouter sur une colonne cette entrée:

foreach($data as $k => $v){ 
    $users ->getCell('A'.$k)->setValue($v['Username']); 
    $users->setCellValueExplicit('B'.$k, 
     '=INDEX(\'Feed\'!H2:H'.$lastRow.',MATCH(A'.$k.',\'Feed\'!G2:G'.$lastRow.',0))', 
     PHPExcel_Cell_DataType::TYPE_FORMULA); 
} 

$users représente une feuille de calcul. Je vois que l'écriture 700 cellules avec le setCellValueExplicit() ci-dessus prend plus de 2 minutes pour être traitées. Si j'ignore cette ligne, il faut 4 secondes à la même machine pour la traiter.

2 minutes peuvent être ok, mais que faire si j'ai 2000 cellules. Y a-t-il un moyen d'optimiser la vitesse?

ps: =VLOOKUP est le même lent que la fonction ci-dessus.


Mise à jour

L'idée du script: lire un fichier CSV (13 colonnes et au moins 100 lignes), écrire dans une feuille de calcul, créez une nouvelle feuille de calcul ($users), lire deux colonnes, les trier en fonction d'une colonne et l'écrire dans la feuille de calcul $users.

Lire les colonnes:

$data = array(); 
for ($i = 1; $i <= $lastRow; $i++) { 
    $user = $Feed ->getCell('G'.$i)->getValue(); 
    $number = $Feed ->getCell('H'.$i)->getValue(); 
    $row = array('User' => $user, 'Number' => $number); 
    array_push($data, $row); 
} 

Trier les données

function cmpb($a,$b){ 
    //get which string is less or 0 if both are the same 
    if($a['Number']>$b['Number']){ 
     $cmpb = -1; 
    }elseif($a['Number']<$b['Number']){ 
     $cmpb = 1; 
    }else{ 
     $cmpb = 0; 
    } 
    //if the strings are the same, check name 
    if($cmpb == 0){ 
     //compare the name 
     $cmpb = strcasecmp($a['User'], $b['User']); 
    } 
    return $cmpb; 
} 
usort($data, 'cmpb'); 

données Ecrire

foreach($data as $k => $v){ 
    $users ->getCell('A'.$k)->setValue($v['Username']); 
    $users ->getCell("B{$k}")->setValueExplicit("=INDEX('Feed'!H2:H{$lastRow},MATCH(A{$k},'Feed'!G2:G{$lastRow},0))", 
PHPExcel_Cell_DataType::TYPE_FORMULA); 
} 

et aussi unset les données de la mémoire:

unset($data); 

Donc si commenter la ligne avec setValueExplicit tout devient plus lisse.

+0

La valeur que vous définissez sur 'setCellValueExplicit' est un peu illisible en raison de toutes ces concaténations et d'échappement sur les guillemets simples. Vous pouvez le remplacer par '" = INDEX ('Feed'! H2: H {$ lastRow}, MATCH (A {$ k}, 'Feed'! G2: G {$ lastRow}, 0)) "'. –

+0

@RolandoIsidoro Malheureusement, je ne peux pas dire que j'ai vu une amélioration des performances. – Diolor

+0

C'est pourquoi j'ai ajouté comme commentaire et non comme réponse. Je regardais juste le code source de PHPExcel et je ne trouve pas de raison pour le comportement que vous décrivez. Je vais ajouter une réponse avec quelques considérations parce que cela ne correspondrait pas aux commentaires. Dis moi ce que tu penses de ça. –

Répondre

2

En regardant le code source de PHPExcel, c'est PHPExcel_Worksheet :: setCellValueExplicit fonction:

public function setCellValueExplicitByColumnAndRow($pColumn = 0, $pRow = 1, $pValue = null, $pDataType = PHPExcel_Cell_DataType::TYPE_STRING) 
{ 
    return $this->getCell(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow)->setValueExplicit($pValue, $pDataType); 
} 

Pour les type de données que vous utilisez, PHPExcel_Cell_DataType::TYPE_FORMULA, le PHPExcel_Cell :: setValueExplicit fonction juste exécute:

case PHPExcel_Cell_DataType::TYPE_FORMULA: 
    $this->_value = (string)$pValue; 
    break; 

Je ne trouve pas d'explication logique pour l'ancien sur l'exécution de cette instruction en particulier. Essayez de le remplacer pour la suivante et laissez-moi savoir s'il y avait une amélioration:

$users ->getCell("B{$k}")->setValueExplicit("=INDEX('Feed'!H2:H{$lastRow},MATCH(A{$k},'Feed'!G2:G{$lastRow},0))", PHPExcel_Cell_DataType::TYPE_FORMULA); 

En tant que dernière ressource mon conseil serait de temps suivre l'exécution de l'instruction pour trouver le goulot d'étranglement.

+0

Merci pour votre réponse. Je l'ai essayé et il a laissé tomber le temps de 2 minutes à une minute. J'ai toujours peur que ce soit beaucoup et assez déraisonnable. J'ai également exécuté le script 2-3 fois et j'ai 'la taille de mémoire permise de 134217728 bytes épuisés'. 128 mégaoctets de mémoire ... D'autres idées sont les bienvenues, merci – Diolor

+0

Si vous pouvez coller l'ensemble '$ data' avec lequel vous travaillez quelque part peut-être que je pourrais essayer de l'accélérer. –

+0

Si vous rencontrez également des problèmes de mémoire, vous devez soit augmenter votre mémoire, soit utiliser la mise en cache des cellules. mais ce dernier affectera la vitesse –