2011-08-11 36 views
8

Estoy tratando de recorrer un documento de 3mb Excel, para obtener todos los datos que luego tendré que insertar en la base de datos. La hoja de trabajo que estoy usando tiene 6500 filas, pero puede variar en el futuro. Me he dado cuenta de que a pesar de que estoy usando técnicas de ahorro de memoria recomendadas, todavía tropiezaProblema de memoria PHPExcel

$reader = PHPExcel_IOFactory::createReaderForFile($file_path); 
$reader->setReadDataOnly(true); 

//$sheets = $this->getWorksheetNames($file['tmp_name'], 0); 
$reader->setLoadSheetsOnly('spreadsheetname'); 

$chunkFilter = new IPO_Reader(); 
$reader->setReadFilter($chunkFilter); 

$highestRow = 10000; //$this->objWorksheet->getHighestRow(); 
$chunkSize  = 1; 
$highestColumn = "Y"; 

for ($startRow = 2; $startRow <= $highestRow; $startRow += $chunkSize) 
{ 

    $chunkFilter->setRows($startRow, $chunkSize); 
    $objPHPExcel = $reader->load($file_path); 

    for($row = $startRow ; $row <= $startRow + $chunkSize; $row++) 
    { 
     $this->read_row = $objPHPExcel->getActiveSheet()->rangeToArray('A'.$row.':'.$highestColumn.$row, null, true, true, true); 

     $this->read_row = end($this->read_row);   

     foreach($this->read_row as $column => $value) 
     { 
      $db_column_name = $this->_getDbColumnMap($column); 
      if(!empty($db_column_name)) 
      { 
       $this->new_data_row[$db_column_name] = $this->_getRowData($value, $column); 
      } 

     } 

     $this->read_row = null; 
     $this->new_data_row['date_uploaded'] = date("Y-m-d H:i:s"); 
     $this->new_data_row['source_file_name'] = $file_name; 
     $ipo_row = new Model_UploadData_IPO(); 
     $ipo_row->create($this->new_data_row); 
     $this->new_data_row = null; 
     unset($ipo_row); 

     gc_collect_cycles(); 

    } 
    $objPHPExcel->disconnectWorksheets(); 
    unset($objPHPExcel);  
    gc_collect_cycles(); 

cuando pruebo el uso de memoria antes de desarmar el objPHPExcel y después, no hay aumento de memoria, estoy realmente confundido, ya que la división en fragmentos no parece permitirme borrar la memoria después de cada fragmento, y el uso aumenta gradualmente, y con un límite establecido en 250MB, solo me permite agregar ~ 500 registros

+0

y esto no último problema =) sólo echar un vistazo de http://stackoverflow.com/questions/6857075/problem-with-excell-export (comer 500MB) – Subdigger

+0

medio perdida lamentable de la oración allí. me permite agregar solo ~ 500 registros –

+0

Kasia: puede editar sus preguntas si comete un error – Mchl

Respuesta

3

La biblioteca PHP Excel is known to have these memory issues, también tuve problemas con eso. Lo que funcionó para mí fue este consejo (desde el enlace anterior, probarlo, hay buenos consejos de cómo reducir el uso de memoria):

$objReader = new PHPExcel_Reader_Excel5(); 
$objReader->setReadDataOnly(true); /* this */ 

Pero de todos modos los requisitos de memoria son grandes, ya que destinan una gran cantidad de memoria para cada celda (para formatear, etc., incluso si uno no necesita eso). Me temo que estamos indefensos hasta que lanzan una nueva versión de la biblioteca.

0

Ok, todo el mundo sabe que trwtf es Excel, así que ¿puedo preguntar si es posible convertir esto a CSV?

Tengo mis propias funciones de CSV a la tabla en PHP que se han utilizado para importar archivos muy grandes, CSV tiende a ser mucho más ligero de procesar y también mucho menos propenso a problemas de biblioteca aleatorios.

Si realmente necesita esto para un proceso de una sola vez o puede pasar de XLS a CSV con bastante facilidad, hágalo porque facilitará su vida (como cada vez que se apegue a alternativas más simples y más estándar;)) .

Y así, por una API que se traducirá el formato XLS oh-tan-mal y terrible, puede utilizar uno de los siguientes convertidores o/s - Me gustaría recomendar pitón cada vez pero bueno, su elección:

http://www.oooninja.com/2008/02/batch-command-line-file-conversion-with.html

http://code.google.com/p/jodconverter/wiki/FAQ

Básicamente, la idea es la misma, se utiliza una herramienta externa con el fin de obtener un formato de archivo utilizable, y luego ir de allí.

No creo que tenga mi script csvtotable.php aquí, pero es bastante fácil de replicar, solo necesita tener algunas herramientas básicas como csvtoarray y array para insertar estados.

GL;)

+1

Me encantaría simplemente cargar archivos CSV, pero desafortunadamente, eso no es lo que quiere el cliente. –

+0

Bien, tengo una solución para eso también ... ¿Qué pasa con el autobús? - no es broma usar la API de OpenOffice, puede hacerlo con bastante facilidad. enlaces en la publicación principal –

+0

En mi último trabajo, también tuve un problema con PHPExcel y problemas de memoria con grandes archivos de Excel. Mientras solo los estaba leyendo, todavía tenía problemas ya que algunos de nuestros proveedores estaban cargando archivos de 20MB +. Si mal no recuerdo, yo también utilicé la API de OpenOffice para abrir el archivo y convertirlo a CSV, luego usé el nuevo archivo para iterar e insertar registros en mi base de datos. Ya había ofrecido capacidades de carga para los archivos de OpenOffice Calc a nuestros usuarios, por lo que ya tenía el código. Si obtienes esto funcionando con OpenOffice, nos encantaría ver tu solución. – MB34