tutorial phpspreadsheet ejemplos composer php spreadsheet phpexcel

phpspreadsheet - PHPExcel muy lento-¿formas de mejorar?



phpoffice/phpspreadsheet laravel (7)

¿Está poblando la hoja de trabajo? o ahorrando? que encuentras demasiado lento?

¿Cómo está rellenando la hoja de cálculo con los datos?

  • El uso del método fromArray () es más eficiente que rellenar cada celda individual, especialmente si usa la Carpeta de valor avanzado para establecer tipos de datos de celda automáticamente.
  • Si está configurando valores para cada celda individual en una hoja usando

    $objPHPExcel->getActiveSheet()->setCellValue(''A1'',$x); $objPHPExcel->getActiveSheet()->setCellValue(''B1'',$y);

    utilizar

    $sheet = $objPHPExcel->getActiveSheet(); $sheet->setCellValue(''A1'',$x); $sheet->setCellValue(''B1'',$y);

    para que solo acceda al método getActiveSheet () una vez; o aproveche la interfaz fluida para configurar múltiples celdas con solo una llamada a $ objPHPExcel-> getActiveSheet ()

    $objPHPExcel->getActiveSheet()->setCellValue(''A1'',$x) ->setCellValue(''B1'',$y);

Ha comentado sobre la aplicación de estilos a rangos de celdas:

  • También tiene la opción de utilizar applyFromArray () para establecer una gran variedad de configuraciones de estilo de una sola vez.
  • Es mucho más eficiente si puede aplicar estilos a una columna o una fila en lugar de simplemente a un rango

Si usa fórmulas en su libro de trabajo, al guardar:

  • Utilizar

    $objWriter->setPreCalculateFormulas(false)

    para desactivar el cálculo de las fórmulas dentro de PHPExcel.

Esos son solo algunos consejos para ayudar a mejorar el rendimiento, y hay muchos más sugeridos en los hilos del foro. No necesariamente ayudarán, depende mucho de su libro de trabajo específico para dar algunos absolutos, pero usted debe ser capaz de mejorar esa velocidad lenta. Incluso el pequeño bloc de notas que uso para el desarrollo puede escribir un archivo Excel 2007 de dos hojas de trabajo, 20 columnas y 2.000 filas más rápido que su servidor de producción.

EDITAR

Si fuera posible simplemente mejorar la velocidad de PHPExcel, lo habría hecho hace tanto tiempo. Tal como están las cosas, estoy constantemente probando el rendimiento para ver cómo se puede mejorar su velocidad. Si desea velocidades más rápidas que PHPExcel puede dar, entonces hay una lista de bibliotecas alternativas aquí .

Estoy generando informes en .xlsx usando PHPExcel. Estuvo bien en las etapas iniciales de prueba con pequeños conjuntos de datos (decenas de filas, 3 hojas), pero ahora cuando se usa en datos de producción reales con más de 500 filas en cada hoja, se vuelve increíblemente lento. 48 segundos para generar un archivo, y al ejecutar un informe que combina más información, todo falla con un Fatal error: Maximum execution time of 30 seconds exceeded in PHPExcel/Worksheet.php on line 1041 . A veces está en otro archivo PHPExcel, así que dudo que la ubicación exacta sea relevante.

Idealmente, me gustaría acelerarlo de alguna manera, si es posible. De lo contrario, al menos aumente el límite de ejecución para este script.

Las únicas sugerencias que he visto hasta ahora fueron estilos en rangos en lugar de celdas individuales. Desafortunadamente, ya hago mi estilo en los rangos y es bastante mínimo también. ¿Cualquier otra sugerencia?


En mi caso, aumenté el rendimiento cambiando el método de almacenamiento de caché en memoria gzip cache_in_memory_gzip

$cm = /PHPExcel_CachedObjectStorageFactory::cache_in_memory_gzip; /PHPExcel_Settings::setCacheStorageMethod($cm);


Me encontré con el mismo problema: tenía aproximadamente 450 filas con 11 columnas de datos que intentaba escribir, y seguí corriendo contra el tiempo de espera de 30 segundos. Pude reducir el tiempo de ejecución a 2 segundos o menos agregando todas mis nuevas filas en bloque, y luego revisando y configurando el contenido de la celda después del hecho. En otras palabras, inserto 450 filas en una llamada para insertarNewRowBefore (), y luego recorro y establezco el contenido dentro de esas filas más adelante.

Al igual que:

$num_rows = count($output_rows); $last_row = $sheet->getHighestRow(); $row = $last_row + 1; $sheet->insertNewRowBefore($row, $num_rows); // Now add all of the rows to the spreadsheet foreach($output_rows as $line) { $i = 0; foreach($line as $val) { // Do your setCellValue() or setCellValueByColumnAndRow() here $i++; } $row++; }


Me encontré con este problema también. Pensé que invertiría mis dos centavos ya que esta pregunta tiene tantos puntos de vista.

Configuración de valores de celda

En lugar de establecer el valor para cada celda individualmente, use el método fromArray() . Tomado y modificado desde la wiki .

$arrayData = array( array(NULL, 2010, 2011, 2012), array(''Q1'', 12, 15, 21), array(''Q2'', 56, 73, 86), array(''Q3'', 52, 61, 69), array(''Q4'', 30, 32, 0), ); $as = $objPHPExcel->getActiveSheet(); $as->fromArray( $arrayData, // The data to set NULL, // Array values with this value will not be set ''C3'' // Top left coordinate of the worksheet range where // we want to set these values (default is A1) );

Estilo de celdas

Estático

También es más rápido aplicar los estilos para un rango, que establecer el estilo para cada celda individualmente (¿notando un patrón?).

$default_style = array( ''font'' => array( ''name'' => ''Verdana'', ''color'' => array(''rgb'' => ''000000''), ''size'' => 11 ), ''alignment'' => array( ''horizontal'' => /PHPExcel_Style_Alignment::HORIZONTAL_CENTER, ''vertical'' => /PHPExcel_Style_Alignment::VERTICAL_CENTER ), ''borders'' => array( ''allborders'' => array( ''style'' => /PHPExcel_Style_Border::BORDER_THIN, ''color'' => array(''rgb'' => ''AAAAAA'') ) ) ); // Apply default style to whole sheet $as->getDefaultStyle()->applyFromArray($default_style); $titles = array( ''Name'', ''Number'', ''Address'', ''Telephone'' ); $title_style = array( ''font'' => array( ''bold'' => true ), ''fill'' => array( ''type'' => /PHPExcel_Style_Fill::FILL_SOLID, ''startcolor'' => array(''rgb'' => ''5CACEE'') ), ''alignment'' => array( ''wrap'' => true ) ); $as->fromArray($titles, null, ''A1''); // Add titles $last_col = $as->getHighestColumn(); // Get last column, as a letter // Apply title style to titles $as->getStyle(''A1:''.$last_col.''1'')->applyFromArray($title_style);

Dinamicamente

Utilizo PHPExcel para verificar los datos proporcionados en la hoja de cálculo con los datos actuales en la base de datos. Como cada celda se verifica individualmente, puse los estilos en una matriz (nulo para ningún estilo) y utilicé el ciclo a continuación para obtener el rango de celdas para aplicar el estilo.

/* * $row is previously set in a loop iterating through each * row from the DB, which is equal to a spreadsheet row. * $styles = array(0 => ''error'', 1 => ''error'', 2 => null, 3 => ''changed'', ...); */ $start = $end = $style = null; foreach ($styles as $col => $s) { if (!$style && !$s) continue; if ($style === $s) { $end = $col; } else { if ($style) { $array = null; switch ($style) { case ''changed'': $array = $this->changed_style; break; case ''error'': $array = $this->error_style; break; case ''ignored'': $array = $this->ignored_style; break; } if ($array) { $start = /PHPExcel_Cell::stringFromColumnIndex($start); $end = /PHPExcel_Cell::stringFromColumnIndex($end); $as->getStyle($start.$row.'':''.$end.$row)->applyFromArray($array); } } $start = $end = $col; $style = $s; } }


No soy un experto en el uso de PHPExcel, pero el formato OfficeOpenXML (el formato de los archivos * .xlsx) es en sí mismo un grupo de archivos XML empaquetados en un archivo ZIP con la extensión * .xlsx . Si valoras tu rendimiento y sabes qué tipo de datos vas a aprobar, tal vez sea una mejor idea construir tu propio generador XLSX , desglosado en las funciones más importantes, tal vez haciendo algunos cálculos en la capa de la base de datos, etc. en lugar de analizar todo documento.

Para hacerlo, puede comenzar analizando los archivos generados utilizando conjuntos de datos más pequeños (cambiando la extensión de * .xlsx a * .zip, desempaquetando y explorando los contenidos de los archivos individuales). De esta forma, podría determinar lo que realmente necesita y generarlo usted mismo (creando archivos XML apropiados y empaquetándolos en un archivo ZIP, luego renombrándolo para tener la extensión * .xlsx).

También hay una especificación de OfficeOpenXML , que es grande (un par de miles de páginas), por lo que no propongo leerlo a menos que realmente lo desee. Crear archivos para que coincidan con la forma en que fueron generados por PHPExcel debería ser suficiente.

La solución mencionada anteriormente no incluye ningún consejo relacionado con PHPExcel, porque no soy un experto en eso. Sin embargo, he estado interesado anteriormente en el proceso de estandarización de OOXML, y estaría feliz si el conocimiento sobre este estándar lo ayudara a resolver su problema.


Para una exportación XLSX con columnas a - amj (~ 800) y solo ~ 50 filas, también encontré el límite de 30 segundos. Para probar mi programa, limité la cantidad de filas procesadas a solo 7, que funcionó en 25 segundos.

  1. pasando de $ objPHPExcel-> getActiveSheet () a $ sheet (primer consejo), en realidad aumentó el tiempo en una cantidad limitada de filas de 25 segundos a 26 segundos.

  2. Lo que realmente me ayudó fue reemplazar todo mi getHighestDataColumn () con una simple variable $ column_nr que se incrementa en PHP, pasé de 26 segundos a 7 segundos.

Después de eso, pude procesar las 50 filas en 11 segundos.


Yo tuve exactamente el mismo problema. Obtuve un archivo CSV de 5000 filas y 32 columnas que llevó mucho tiempo procesar. Resulta que casi todo el tiempo dedicado al "procesamiento" es en realidad la codificación de caracteres que está configurada para codificar todo a UTF8 de forma predeterminada. Entonces, si ingresa en su archivo config / excel.php y se desplaza hacia abajo hasta la codificación, simplemente configúrelo como:

/* |-------------------------------------------------------------------------- | Import encoding |-------------------------------------------------------------------------- */ ''encoding'' => array( ''input'' => '''', ''output'' => '''' ),

Solo con esto: el archivo mencionado anteriormente tarda alrededor de 8 segundos en procesarse. Sin embargo, es posible que desee advertir a su cliente que guarde el archivo CSV correctamente.