PHPExcel很慢 – 改进方法?
我使用PHPExcel在.xlsx中生成报告。 在小型数据集(几十行,三张)的初始testing阶段就可以了,但是现在在每张纸上使用超过500行的实际生产数据时,它变得非常慢。 48秒来生成一个文件,当运行一个包含更多信息的报告时,整个事件都会失败,并发生Fatal error: Maximum execution time of 30 seconds exceeded in PHPExcel/Worksheet.php on line 1041
。 有时它在另一个PHPExcel文件,所以我怀疑确切的位置是相关的。
理想情况下,如果可能的话,我想尽快加快速度。 如果不是,那么至less增加这个脚本的执行限制。
我迄今看到的唯一build议是在范围而不是单个单元格中进行样式devise。 不幸的是,我已经在范围内做了我的造型,而且也很less。 还有其他build议吗?
它填充工作表吗? 或保存? 你觉得太慢了?
你如何用数据填充电子表格?
- 使用fromArray()方法比填充每个单元格更有效,特别是如果使用“高级值绑定器”自动设置单元格数据types。
-
如果您正在使用表单中的每个单元格设置值
$objPHPExcel->getActiveSheet()->setCellValue('A1',$x); $objPHPExcel->getActiveSheet()->setCellValue('B1',$y);
使用
$sheet = $objPHPExcel->getActiveSheet(); $sheet->setCellValue('A1',$x); $sheet->setCellValue('B1',$y);
所以你只能访问一次getActiveSheet()方法; 或利用stream畅的接口来设置多个单元格,只需要调用$ objPHPExcel-> getActiveSheet()
$objPHPExcel->getActiveSheet()->setCellValue('A1',$x) ->setCellValue('B1',$y);
您已经评论了将样式应用于单元格范围:
- 您还可以select使用applyFromArray()一次性设置各种样式设置。
- 如果您可以将样式应用于列或行而不是简单地应用于范围,则效率会更高
如果您在工作簿中使用公式,则在保存时:
-
使用
$objWriter->setPreCalculateFormulas(false)
禁用PHPExcel自身计算公式。
这些只是提高性能的一些提示,在论坛主题中还有很多build议。 他们不一定都会有所帮助,太依赖于你的具体工作手册给予任何绝对的,但是你应该能够改善这种缓慢的速度。 即使是我用于开发的小笔记本,也可以比生产服务器更快地写出3张工作表,20列,2000行Excel 2007文件。
编辑
如果简单地提高PHPExcel本身的速度是可能的,我早就这么做了。 事实上,我一直在进行性能testing,看看它的速度如何提高。 如果你想要比PHPExcel本身可以提供更快的速度,那么这里有一个备选库的列表 。
我遇到了这个问题。 因为这个问题得到了很多意见,所以我想扔两分钱。
设置单元格值
而不是分别设置每个单元格的值,请使用fromArray()
方法。 从维基采取和修改。
$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) );
造型细胞
静态的
对范围应用样式也比单独设置样式(注意模式)要快。
$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);
dynamic
我使用PHPExcel检查数据库中当前数据的电子表格中给出的数据。 由于每个单元格都是单独检查的,因此我将样式放在一个数组中(null表示没有样式),并使用下面的循环来获取应用样式的单元格区域。
/* * $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; } }
我遇到了同样的问题 – 有大约450行,有11列我想写的数据,而我一直在跑30秒的超时。 我可以将执行时间缩短到2秒或更less,方法是将所有新增的行批量添加,然后在事实之后通过并设置单元格内容。 换句话说,我在insertNewRowBefore()的一次调用中插入了450行,然后循环遍历并在后面的行中设置内容。
像这样:
$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++; }
我并不是使用PHPExcel的专家,但是OfficeOpenXML格式(* .xlsx文件的格式)本身就是一组打包成ZIP格式的扩展名为.xlsx的XML文件 。 如果你重视你的performance,并知道你将传递什么样的数据,也许build立自己的XLSX生成器 ,剥离最重要的function,可能在数据库层等计算,而不是parsing整个文件。
要做到这一点,您可以从分析使用较小数据集生成的文件开始(将* .xlsx的扩展名更改为* .zip,将其解压并浏览单个文件的内容)。 这样你就可以确定你真正需要的东西,并自己生成它(通过创build合适的XML文件并将其打包到ZIP存档中,然后重命名为* .xlsx扩展名)。
也有OfficeOpenXML规范,这是很大的(几千页),所以我不build议阅读它,除非你真的想。 创build文件以匹配它们由PHPExcel生成的方式应该足够了。
上面提到的解决scheme不包含任何PHPExcel相关的技巧,因为我不是专家。 我以前对OOXML标准化过程很感兴趣,如果有关这个标准的知识能够帮助你解决你的问题,我会很高兴的。
对于一个XLSX导出列a – amj(〜800),只有〜50行我也跑到了30秒的边界。 为了testing我的程序,我将处理的行数限制在7个,在25秒内工作。
-
从单独的$ objPHPExcel-> getActiveSheet()到$ sheet(第一个build议),它实际上将有限的行数从25秒增加到26秒。
-
真正帮助我的是用一个简单的$ column_nrvariablesreplace我所有的getHighestDataColumn(),这个variables在PHP中递增,我从26秒变为7秒。
之后,我能够在11秒内处理所有50行。
我有完全相同的问题。 有一个5000行,32列CSV文件,永远处理。 事实certificate,几乎所有花费在“处理”上的时间实际上是默认设置为将所有内容编码为UTF8的字符编码。 所以,如果你进入你的configuration\ excel.php文件并向下滚动到编码,只需将其设置为:
/* |-------------------------------------------------------------------------- | Import encoding |-------------------------------------------------------------------------- */ 'encoding' => array( 'input' => '', 'output' => '' ),
只有这一点 – 上面提到的文件需要大约8秒的时间来处理。 您可能要警告您的客户端正确保存CSV。
在我的情况下,我通过将caching存储方法更改为内存gzip cache_in_memory_gzip来提高了性能
$cm = \PHPExcel_CachedObjectStorageFactory::cache_in_memory_gzip; \PHPExcel_Settings::setCacheStorageMethod($cm);