我试图将一些记录从我的MySQL(网络服务器)导出到excel,当查询返回> 4k记录时,脚本会挂起网络浏览器,暂时挂起网络托管。
我的PHP_version
是5.2.13-pl1-gentoo,而memory_limit
中配置的php.ini
是128M
结果excel只有一列和N行。有了100或200行,php脚本运行正常。
这是php脚本
<? session_start();
ini_set('memory_limit', '1024M');
set_time_limit(0);
include("include/conexion.php");
require_once 'include/PHPExcel/Classes/PHPExcel.php';
require_once 'include/PHPExcel/Classes/PHPExcel/IOFactory.php';
$objPHPExcel = new PHPExcel();
$objPHPExcel->getProperties()->setCreator("Name")
->setLastModifiedBy("Name")
->setTitle("Listado")
->setSubject("Listado")
->setDescription("Listado.")
->setKeywords("Listado")
->setCategory("Listado");
$query = explode("|",stripcslashes($_POST['query']));
$objPHPExcel->getActiveSheet()->setTitle('List');
$resEmp = mysql_query ($query, $conexion ) or die(mysql_error());
$tot = mysql_num_rows($resEmp);
$num_fields = mysql_num_fields($resEmp);
$fistIndex = $objPHPExcel->getActiveSheet()->getCellByColumnAndRow(0, 1)->getColumn();
$lastIndex = $objPHPExcel->getActiveSheet()->getCellByColumnAndRow($num_campos - 1, 1)->getColumn();
//tittles
for ($e=0;$e < $num_fields;$e++){
$objPHPExcel->getActiveSheet()->setCellValueByColumnAndRow($e, 2, utf8_decode(ucwords(mysql_field_name($resEmp,$e))));
$objPHPExcel->getActiveSheet()->getColumnDimension($objPHPExcel->getActiveSheet()->getCellByColumnAndRow($e, 2)->getColumn())->setAutoSize(true);
}
//color tittles
$objPHPExcel->getActiveSheet()->getStyle( $fistIndex.'1:'.$lastIndex.'2' )->getFill()->setFillType(PHPExcel_Style_Fill::FILL_SOLID)->getStartColor()->setRGB('c5c5c7');
$objPHPExcel->getActiveSheet()->getStyle( $fistIndex.'1:'.$lastIndex.'2' )->getFont()->setBold(true);
if(isset ( $_POST ['mail'] )){
$objPHPExcel->getActiveSheet()->setCellValueByColumnAndRow(0, 2, "Email");
$emails = array();
for ($row = 0; $row < $totEmp; $row++) {
//more than one mail in field separated by ";"
$aux = explode(";", mysql_result($resEmp,$row,$col));
for($i=0; $i<count($aux); $i++){
$cleaned = utf8_encode(strtolower(trim($aux[$i])));
//filter repeated mails
if(!in_array($cleaned, $emails) && $aux[$i] != ""){
$num_rows = $objPHPExcel->getActiveSheet()->getHighestRow();
$objPHPExcel->getActiveSheet()->insertNewRowBefore($num_rows + 1, 1);
array_push($emails, $cleaned);
$objPHPExcel->getActiveSheet()->setCellValueByColumnAndRow(0, $num_rows + 1, $cleaned);
}
}
}
}
$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
header('Content-type: application/vnd.ms-excel');
header("Content-Disposition: attachment; filename=".$nom_archivo.".xlsx");
// Write file to the browser
$objWriter->save('php://output');
exit();
?>
当输入脚本运行mysql查询然后,迭代结果以获取邮件字段,如果获取的邮件不存在于数组中,则此邮件将插入excel中
我试图设置
ini_set('memory_limit', '1024M');
set_time_limit(0);
但问题仍然存在。
有什么想法解决问题吗?
非常感谢
编辑1
我已经使用建议更新了代码,现在工作正常。
无论如何,如果在挂起之前发生任何错误或内存使用,我怎么能得到?
如何使用ini_set('memory_limit', '2048M');
设置max memory_limit?
<? session_start();
ini_set('memory_limit', '2048M');
set_time_limit(0);
include("include/conexion.php");
require_once 'include/PHPExcel/Classes/PHPExcel.php';
require_once 'include/PHPExcel/Classes/PHPExcel/IOFactory.php';
$objPHPExcel = new PHPExcel();
$objPHPExcel->getProperties()->setCreator("Name")
->setLastModifiedBy("Name")
->setTitle("Listado")
->setSubject("Listado")
->setDescription("Listado.")
->setKeywords("Listado")
->setCategory("Listado");
$activeSheet = $objPHPExcel->getActiveSheet();
$query = explode("|",stripcslashes($_POST['query']));
$activeSheet->setTitle('List');
$resEmp = mysql_query ($query, $conexion ) or die(mysql_error());
$tot = mysql_num_rows($resEmp);
$num_fields = mysql_num_fields($resEmp);
$fistIndex = $activeSheet->getCellByColumnAndRow(0, 1)->getColumn();
$lastIndex = $activeSheet->getCellByColumnAndRow($num_campos - 1, 1)->getColumn();
//tittles
for ($e=0;$e < $num_fields;$e++){
$activeSheet->setCellValueByColumnAndRow($e, 2, utf8_decode(ucwords(mysql_field_name($resEmp,$e))));
$activeSheet->getColumnDimension($activeSheet->getCellByColumnAndRow($e, 2)->getColumn())->setAutoSize(true);
}
//color tittles
$activeSheet->getStyle( $fistIndex.'1:'.$lastIndex.'2' )->getFill()->setFillType(PHPExcel_Style_Fill::FILL_SOLID)->getStartColor()->setRGB('c5c5c7');
$activeSheet->getStyle( $fistIndex.'1:'.$lastIndex.'2' )->getFont()->setBold(true);
if(isset ( $_POST ['mail'] )){
$activeSheet->setCellValueByColumnAndRow(0, 2, "Email");
$emails = array();
for ($row = 0; $row < $totEmp; $row++) {
//more than one mail in field separated by ";"
$aux = explode(";", mysql_result($resEmp,$row,$col));
for($i=0; $i<count($aux); $i++){
$cleaned = utf8_encode(strtolower(trim($aux[$i])));
//filter repeated mails
if(!in_array($cleaned, $emails) && $aux[$i] != ""){
array_push($emails, $cleaned);
}
}
}
for ($row = 0; $row < count($emails); $row++) {
$activeSheet->setCellValueByColumnAndRow(0, $row + 3, $emails[$row]);
}
}
$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
header('Content-type: application/vnd.ms-excel');
header("Content-Disposition: attachment; filename=".$nom_archivo.".xlsx");
// Write file to the browser
$objWriter->save('php://output');
exit();
?>
答案 0 :(得分:0)
似乎这个库在解析大型excel电子表格方面存在严重问题,我已经发现了这个问题。我找不到合适的解决方案。我想这是正常的行为,因为这个库完全用PHP编写,导致大量的解析开销 我强烈建议您使用excel解析PHP扩展,如Jersey documentation - Defining Custom Injection Annotation 作为另一个可以想象的解决方案[如果可能],你可以将你的大文件分解为几个较小的文件(例如通过表格),否则我猜你应该使用更快的CPU或使用另一个库或编程语言来解析你的exel文件(例如java中的this one,可能带有apache-poi)。
答案 1 :(得分:0)
不幸的是,PHPExcel不适合使用大数据执行,因为PHP实际上并不是一个好的二进制文件处理语言。
有些人将他们的数据导出为excel(http://en.wikipedia.org/wiki/Microsoft_Office_XML_formats)的XML格式,并且它可以很好地运行。但是,xml格式没有excel二进制文件的完整功能,当然它的文件大小也会更大。
为了处理大数据(导入/导出到二进制excel文件),我们的系统现在使用libxl,这将花费199美元的许可证,php_excel是libxl的包装器。实际上,我们的系统现在使用libxl在大约几秒钟内导出一个行数超过5k的excel文件,我认为它是迄今为止使用二进制excel的唯一解决方案。
P / s:$ objPHPExcel-&gt; getActiveSheet()也有成本,因此您可以将其值存储到变量中以便稍后重用,这将有助于您加快代码的速度。