Saltar al contenido

PHPExcel muy lento – ¿formas de mejorar?

Solución:

¿Está llenando la hoja de trabajo? o ahorrando? que te parece demasiado lento?

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

  • Utilizando el fromArray() El método es más eficaz que rellenar cada celda individual, especialmente si usa Advanced Value Binder para configurar los 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);
    

    usar

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

    para que solo acceda al getActiveSheet() método una vez; o aproveche la interfaz fluida para configurar múltiples celdas con una sola 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 tienes la opción de usar 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 fila en lugar de simplemente a un rango

Si está usando fórmulas en su libro de trabajo, al guardar:

  • Usar

    $objWriter->setPreCalculateFormulas(false)
    

    para deshabilitar 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 todos necesariamente ayudarán, demasiado depende de su libro de trabajo específico para dar absolutos, pero debería poder mejorar esa velocidad lenta. Incluso el pequeño cuaderno que utilizo para el desarrollo puede escribir un archivo Excel 2007 de 3 hojas de trabajo, 20 columnas y 2000 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 mucho 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 las que puede ofrecer PHPExcel, aquí encontrará una lista de bibliotecas alternativas.

También me encontré con este problema. Pensé en tirar mis dos centavos ya que esta pregunta recibe tantas visitas.

Configuración de valores de celda

En lugar de establecer el valor para cada celda individualmente, use el fromArray() método. Tomado y modificado de 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. Dado que cada celda se verifica individualmente, puse los estilos en una matriz (nulo para ningún estilo) y usé el ciclo a continuación para obtener el rango de celdas a las que 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;
    }
} 

Me estaba encontrando con el mismo problema: tenía alrededor de 450 filas con 11 columnas de datos que estaba tratando de 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 filas nuevas a granel, y luego revisando y configurando el contenido de la celda después del hecho. En otras palabras, inserto 450 filas en una llamada a insertNewRowBefore (), 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++;
}
¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *