PHPExcel内存耗尽

3

我正在使用PHPExcell导出包含20列的4000行数据。我想要在工作表中将每隔一行颜色区分开来,于是我写了一个循环,但返回给我的结果是“

FAtal Error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 24 bytes) in D:\Data\xampp\htdocs\Classes\PHPExcel\Style\Supervisor.php(致命错误:内存大小限制为134217728字节,尝试在D:\Data\xampp\htdocs\Classes\PHPExcel\Style\Supervisor.php文件中分配24字节)

我已经花费了2个小时来解决这个问题,但我失败了。我找到的每个主题都相当古老,2010年或更早。我已经尝试过使用缓存,类似于以下内容:

$cacheMethod = PHPExcel_CachedObjectStorageFactory:: cache_to_phpTemp;
$cacheSettings = array( ' memoryCacheSize ' => '8MB');
PHPExcel_Settings::setCacheStorageMethod($cacheMethod, $cacheSettings);   

但这并没有帮助。你有什么想法可以解决这个问题吗?

在我的循环结束时,我使用的是生成 xlsx 并格式化单元格的循环:

$i = 2;
    foreach($table as $row){
    $objPHPExcel->getActiveSheet()
                ->setCellValue('A'.$i, $row[1])
                ->setCellValue('B'.$i, $row[2])
                ->setCellValue('C'.$i, $row[3])
                ->setCellValue('D'.$i, $row[4])
                ->setCellValue('E'.$i, $row[5])
                ->setCellValue('F'.$i, $row[6])
                ->setCellValue('G'.$i, $row[7])
                ->setCellValue('H'.$i, $row[8])
                ->setCellValue('I'.$i, $row[9])
                ->setCellValue('J'.$i, $row[10])
                ->setCellValue('K'.$i, $row[11])
                ->setCellValue('L'.$i, $row[12])
                ->setCellValue('M'.$i, $row[13])
                ->setCellValue('N'.$i, $row[14])
                ->setCellValue('O'.$i, $row[15])
                ->setCellValue('P'.$i, $row[16])
                ->setCellValue('Q'.$i, $row[17])
                ->setCellValue('R'.$i, $row[20])
                ->setCellValue('S'.$i, $row[21])
                ->setCellValue('T'.$i, $row[22]);
        // Color every second row
    if($i%2!=0){
    $objPHPExcel->getActiveSheet()->getStyle('A'.$i.':T'.$i)->getFill()->applyFromArray(
    array(
    'type'       => PHPExcel_Style_Fill::FILL_SOLID,
    'startcolor' => array('rgb' => 'e8f4ff')
    ));
    }

    //color column "O"
    if($i%2==0){
    $objPHPExcel->getActiveSheet()->getStyle('O'.$i)->getFill()->applyFromArray(
    array(
    'type'       => PHPExcel_Style_Fill::FILL_SOLID,
    'startcolor' => array('rgb' => 'fffacd')
    ));
    }
    else{
    $objPHPExcel->getActiveSheet()->getStyle('O'.$i)->getFill()->applyFromArray(
    array(
    'type'       => PHPExcel_Style_Fill::FILL_SOLID,
    'startcolor' => array('rgb' => 'fff9bd')
    ));
    }

    // color column "N"
    if($i%2==0){
    $objPHPExcel->getActiveSheet()->getStyle('N'.$i)->getFill()->applyFromArray(
    array(
    'type'       => PHPExcel_Style_Fill::FILL_SOLID,
    'startcolor' => array('rgb' => 'eaffee')
    ));
    }
    else{
    $objPHPExcel->getActiveSheet()->getStyle('N'.$i)->getFill()->applyFromArray(
    array(
    'type'       => PHPExcel_Style_Fill::FILL_SOLID,
    'startcolor' => array('rgb' => 'ccffcc')
    ));
    }           


    $i++;
    }

编辑:: 我贴出完整代码,因为我不知道还能做什么。我创建了一个新的phpexcel对象,然后导入只有第一行作为标题和列名的空模板。其余单元格完全为空,并带有预设样式。我为10000行设置了样式。但它仍然返回相同的错误。下面是代码:

            error_reporting(E_ALL);
    ini_set('display_errors', TRUE);
    ini_set('display_startup_errors', TRUE);
    date_default_timezone_set('Europe/London');

    if (PHP_SAPI == 'cli')
        die('This example should only be run from a Web Browser');

    /** Include PHPExcel */
    require_once '../Classes/PHPExcel.php';



    // Create new PHPExcel object
    $objPHPExcel = new PHPExcel();

    $objReader = PHPExcel_IOFactory::createReader('Excel2007');
    $objReader = $objReader->load('components/com_uhlist/Classes/template.xlsx');
    $template = $objReader->getActiveSheet();

    $objPHPExcel->addExternalSheet($template);
    $objPHPExcel->setActiveSheetIndex(1);

    $user = JFactory::getUser();
    $username = $user->get('username');
    // Set document properties
    $objPHPExcel->getProperties()->setCreator($username)
                                 ->setLastModifiedBy($username)
                                 ->setTitle("User & Host List");



    // Add some data
    // Aktywowanie arkusza
    //$objPHPExcel->setActiveSheetIndex(-0);


    // Export danych
    $db = JFactory::getDBO();
    $query = 'SELECT * FROM '.$db->getPrefix().'users_n_hosts';
    $db->setQuery($query);
    $table = $db->loadRowList();

    $i = 2;
    foreach($table as $row){
    $objPHPExcel->getActiveSheet()
                ->setCellValue('A'.$i, $row[1])
                ->setCellValue('B'.$i, $row[2])
                ->setCellValue('C'.$i, $row[3])
                ->setCellValue('D'.$i, $row[4])
                ->setCellValue('E'.$i, $row[5])
                ->setCellValue('F'.$i, $row[6])
                ->setCellValue('G'.$i, $row[7])
                ->setCellValue('H'.$i, $row[8])
                ->setCellValue('I'.$i, $row[9])
                ->setCellValue('J'.$i, $row[10])
                ->setCellValue('K'.$i, $row[11])
                ->setCellValue('L'.$i, $row[12])
                ->setCellValue('M'.$i, $row[13])
                ->setCellValue('N'.$i, $row[14])
                ->setCellValue('O'.$i, $row[15])
                ->setCellValue('P'.$i, $row[16])
                ->setCellValue('Q'.$i, $row[17])
                ->setCellValue('R'.$i, $row[20])
                ->setCellValue('S'.$i, $row[21])
                ->setCellValue('T'.$i, $row[22]);       
    $i++;
    }



    // Nazwa arkusza
    $objPHPExcel->getActiveSheet()->setTitle('User & Host');


    // Set active sheet index to the first sheet, so Excel opens this as the first sheet
    $objPHPExcel->setActiveSheetIndex(0);


    // Redirect output to a client’s web browser (Excel2007)
    header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
    header('Content-Disposition: attachment;filename="User&Host_'.date('d-m-Y').'.xlsx"');
    header('Cache-Control: max-age=0');

    $objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
    $objWriter->save('php://output');
    exit;

    }

最新代码::将数据插入模板:

            $objPHPExcel = PHPExcel_IOFactory::createReader('Excel2007');
    $objPHPExcel = $objPHPExcel->load('components/com_uhlist/Classes/template.xlsx');
    $objPHPExcel->setActiveSheetIndex(0);

    $user = JFactory::getUser();
    $username = $user->get('username');
    // Set document properties
    $objPHPExcel->getProperties()->setCreator($username)
                                 ->setLastModifiedBy($username)
                                 ->setTitle("User & Host List");

    // Export danych
    $db = JFactory::getDBO();
    $query = 'SELECT * FROM '.$db->getPrefix().'autocad_users_n_hosts';
    $db->setQuery($query);
    $table = $db->loadRowList();

    $i = 2;
    foreach($table as $row){
    $objPHPExcel->getActiveSheet()
                ->setCellValue('A'.$i, $row[1])
                ->setCellValue('B'.$i, $row[2])
                ->setCellValue('C'.$i, $row[3])
                ->setCellValue('D'.$i, $row[4])
                ->setCellValue('E'.$i, $row[5])
                ->setCellValue('F'.$i, $row[6])
                ->setCellValue('G'.$i, $row[7])
                ->setCellValue('H'.$i, $row[8])
                ->setCellValue('I'.$i, $row[9])
                ->setCellValue('J'.$i, $row[10])
                ->setCellValue('K'.$i, $row[11])
                ->setCellValue('L'.$i, $row[12])
                ->setCellValue('M'.$i, $row[13])
                ->setCellValue('N'.$i, $row[14])
                ->setCellValue('O'.$i, $row[15])
                ->setCellValue('P'.$i, $row[16])
                ->setCellValue('Q'.$i, $row[17])
                ->setCellValue('R'.$i, $row[20])
                ->setCellValue('S'.$i, $row[21])
                ->setCellValue('T'.$i, $row[22]);       
    $i++;
    }

    // Redirect output to a client’s web browser (Excel2007)
    header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
    header('Content-Disposition: attachment;filename="User&Host_'.date('d-m-Y').'.xlsx"');
    header('Cache-Control: max-age=0');

    $objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
    $objWriter->save('php://output');
    exit;

注意:应该是memoryCacheSize而不是 memoryCacheSize(前面不需要空格)。 - Aistis
2个回答

1
尝试使用PHP XLSXWriter。它很轻便,并在写入xml表格时将其保存到磁盘,因此据我的经验,它的内存使用率要低得多。它无法以任何方式读取电子表格,因此虽然不像phpexcel那样强大,但它能很好地完成写作任务。 phpexcel库在将所有内容写出之前都将其存储在内存中,并且根据设计具有高内存使用率。

1

你是否尝试过其他缓存方法?SQLite或SQLite 3是最节省内存的,因为所有其他方法都保留了内存中的单元索引。

在可能的情况下,将样式应用于一系列单元格而不是每个单独的单元格。范围样式更加节省内存,并且是推荐的方法。这是因为它只为指定的范围创建一个样式对象;而对单个单元格进行样式设置会为每个单独使用创建一个样式记录。

这些是两个最大的减少内存的因素。

通过已定义样式的初始模板,并使用工作表的duplicateStyle()或duplicateStyleArray()方法,也可能有所帮助-特别是您可以将其复制到备选行的一系列单元格中-因为这不会创建新的样式对象,而是重用现有定义的样式对象。

如果所有这些都失败了,您可能仍然需要增加php内存设置。


嗨,马克,感谢回复。我编辑了我的答案并添加了完整的代码。我创建了一个模板,然后将该表格导入到新对象中,但仍然出现错误。如果您能看一下,我将不胜感激。 - Sheryf
我目前没有使用任何缓存,但是认为模板可能会有所帮助。我应该尝试一下吗?如果我的代码有误,请纠正它,因为我不确定它是否正确。 $cacheMethod = PHPExcel_CachedObjectStorageFactory::cache_in_sqlite; PHPExcel_Settings::setCacheStorageMethod($cacheMethod); - Sheryf
$cacheMethod = PHPExcel_CachedObjectStorageFactory::cache_to_sqlite3; PHPExcel_Settings::setCacheStorageMethod($cacheMethod); - Mark Baker
已经测试了将缓存存储到sqlite3中,但不起作用。也许有一种方法可以样式化范围行,我的意思是每隔一行,而不使用循环?就像CSS的:nth-child()伪类一样? - Sheryf
那个错误的文件里面写着:Allowed memory size of 134217728 bytes exhausted (tried to allocate 24 bytes) in <b>D:\Data\xampp\htdocs\Classes\PHPExcel\CachedObjectStorage\CacheBase.php'。好吧,我想我会放弃为每个单元格设置样式了。这不是必须的,而且占用了我很多时间。我放弃了 ;) 谢谢你的帮助。 - Sheryf
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接