PHPExcel Writer对象最终会占用大量内存和超时

时间:2015-04-15 09:33:23

标签: php codeigniter-2 phpexcel

我正在使用以下方式创建Excel工作表:

  1. Codeigniter 2.2.1
  2. PHP 5.4.25
  3. Apache 2.4.7
  4. XAMPP 1.8.2
  5. PHPExcel 1.8.0
  6. 我从数据库中获取 35000行(大部分为空) 79列并写入excel文件(Excel5)。

    适用于30000行,峰值内存使用量为 1.44GB ,文件大小为24MB。但是当我去35000时,它说出来了,

    致命错误:第144行的E:\ XAMPP \ htdocs \ ProjectName \ application \ libraries \ PHPExcel \ Writer \ Excel5 \ BIFFwriter.php内存不足(已分配1780219904)(尝试分配17301483字节)< /强>

    当我创建PHPExcel对象时,它最终会占用大量内存和超时。我在php.ini文件中设置了“ memory_limit = -1 ”和“ max_execution_time = 1000 ”,并在PHPExcel中尝试了不同的缓存存储方法。

    我在控制器中的算法看起来像这样

    public function write_controller() {    
        error_reporting(E_ALL);
        ini_set("display_errors", 1);
        ini_set('memory_limit', '-1'); //-1 for unlimited memory
        $dir = "assets/output/";
    
        //FIRST CHECK IF PREVIOUS FILE EXISTS OR NOT
        $this->clear_directory($dir);
    
        // Loading PHPExcel library
        $this->load->library('PHPExcel');
        $this->load->library('PHPExcel/IOFactory');
    
        $cacheMethod = PHPExcel_CachedObjectStorageFactory::cache_to_phpTemp;
        $cacheSettings = array('memoryCacheSize' => '5000MB', 'cacheTime' => '1000'); 
    
        PHPExcel_Settings::setCacheStorageMethod($cacheMethod, $cacheSettings);
    
        //First Create the xls file and then insert rest of the data
        $objPHPExcel = new PHPExcel();
        $objPHPExcel->getProperties()->setTitle("export")->setDescription("none");
    
        //activate sheet number 1
        $objPHPExcel->setActiveSheetIndex(0);
    
        //Setting font styles
        $objPHPExcel->getActiveSheet()->getDefaultStyle()->getFont()->setName('Arial')->setSize(8)->setBold(false);
    
        //Setting number format as TEXT
        $objPHPExcel->getActiveSheet()->getDefaultStyle()->getNumberFormat()->setFormatCode(PHPExcel_Style_NumberFormat::FORMAT_TEXT);
    
        //Freezing first top row
        $objPHPExcel->getActiveSheet()->freezePane('A2');
    
    
        $objWorksheet = $objPHPExcel->getActiveSheet();
    
        $row1 = 1;
    
        $objWorksheet->setCellValueByColumnAndRow(0, $row1, "Site name");
        $objWorksheet->setCellValueByColumnAndRow(1, $row1, "Vendor_1");
        $objWorksheet->setCellValueByColumnAndRow(2, $row1, "Status");
        $objWorksheet->setCellValueByColumnAndRow(3, $row1, "Easting");
        $objWorksheet->setCellValueByColumnAndRow(4, $row1, "Northing");
        $objWorksheet->setCellValueByColumnAndRow(5, $row1, "Sector_1");
        .
        .
        .
        //Rest of the 74 columns
    
        $style = array(
            'alignment' => array(
                'horizontal' => PHPExcel_Style_Alignment::HORIZONTAL_CENTER, 
                'vertical' => PHPExcel_Style_Alignment::VERTICAL_CENTER)
        );
    
        $objWorksheet->getDefaultStyle()->applyFromArray($style);
    
        $objWriter = IOFactory::createWriter($objPHPExcel, 'Excel5');
    
        $saved_location ='assets/output/Piano11.xls'; 
        $objWriter->save($saved_location); 
    
        //Now reading the saved xls file
        $objReader = new PHPExcel_Reader_Excel5();
    
        $newPHPExcel = $objReader->load($saved_location); 
    
        $newWorksheet = $newPHPExcel->getActiveSheet();
    
        //Now insert rest of the data from Piano table which will come from database
        $table_name = 'piano_test';
    
        $query = $this->db->get('tbl_piano');
    
        if (!$query) {
            return false;
        }
    
        // Fetching the data from table
        $fields = $query->list_fields();
    
        $row = 2;
        foreach ($query->result() as $data) {
            set_time_limit(0);
            $col = 0;
            foreach ($fields as $field) {
                $newWorksheet->setCellValueByColumnAndRow($col, $row, $data->$field); //<- This skips leading 0s
                $col++;
            }
            $row++;
        }
    
        $newobjWriter = IOFactory::createWriter($newPHPExcel, 'Excel5');
        $newobjWriter->save('assets/output/Piano11.xls');
    
        echo 'Memory peak usage: <b>'.$this->convert(memory_get_peak_usage(true)).'</b><br/>';
        gc_collect_cycles();//garbage collector
        echo 'inserted.';
    }
    

    任何解决方案如何最大限度地减少内存使用量?执行时间处理时间?或任何其他替代解决方案?或者我应该改变我的算法吗?

1 个答案:

答案 0 :(得分:1)

您使用phptemp进行缓存,但使用设置

$cacheSettings = array('memoryCacheSize' => '5000MB', 'cacheTime' => '1000'); 

这意味着PHPExcel在开始使用phptemp进行缓存之前会使用5000MB(5GB)的PHP内存.....如果你有php.ini最大内存设置允许PHP使用,我会感到惊讶那么多记忆

你应该为memoryCacheSize使用更低的值,也许是512MB,这意味着PHPExcel在切换到使用php:// temp <之前只会使用512MB的PHP内存来缓存单元格数据/ p>