PHP скрипт, генерирующий файл Excel, занимающий слишком много памяти

У меня есть скрипт PHP, работающий с использованием инфраструктуры YII, который проходит через базу данных и создает лист Excel для экспорта. Количество данных в базе данных составляет около 15 тыс. Записей и увеличивается. Проблема в том, что скрипт потребляет много памяти, а размер файла Excel составляет около 45 МБ. Я могу попытаться сжать файл, чтобы сжать его до размера, который, я не думаю, будет проблемой, но сценарий, использующий больше памяти, - моя забота.

Один из способов решить эту проблему - обработать только 5 тыс. Записей за один раз, а затем добавить их все для создания файла Excel. Я не уверен, что так будет.

    public function actionExport() {

        Yii::import('ext.phpexcel.XPHPExcel');
        XPHPExcel::init();


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



// Adding data
        $objPHPExcel->setActiveSheetIndex(0)
                ->setCellValue('A1', 'SN')
                ->setCellValue('B1', 'Full Name')
                ->setCellValue('C1', 'Gender')
                ->setCellValue('D1', 'Date Of Birth')
                ->setCellValue('E1', 'Products')


        $merchantModels = Merchant::model()->findAll();
        $i = 2; //starting after the header row
        foreach ($merchantModels as $model) {
            $merchantPModels = MerchantProducts::model()->findAll(array(
                'condition' => 'merchantID = :merchantID',
                'params' => array(':merchantID' => $model->id),
            ));
            $productStr= "";
            $pStr ="";
            $x = 0; // counter for the merchnat product Loop 

            foreach ($merchantModels as $MPmodel) {
                if($MPmodel->product !== null){
                    $pStr = $MPmodel->product->productName;
                }else{
                    $pStr = "";
                }


                if ($x == 0) { // First Object
                    $productStr = $pStr;
                }else{
                   $productStr = $productStr . "," . $pStr; 
                }

                $x++;
            }
             * 
             */


            $objPHPExcel->setActiveSheetIndex(0)
                    ->setCellValue('A' . $i, $i - 1)
                    ->setCellValue('B' . $i, $model->fullName)
                    ->setCellValue('C' . $i, $model->gender)
                    ->setCellValue('D' . $i, $model->dateOfBirth)                        
                    ->setCellValue('E' . $i, $productStr);
            $i++;
        }
// Rename worksheet
        $objPHPExcel->getActiveSheet()->setTitle('Merchants');


// Set active sheet index to the first sheet, so Excel opens this as the first sheet
        $objPHPExcel->setActiveSheetIndex(0);
        $date = new DateTime('NOW');
        $date = $date->format('Y-m-d H:i:s'); // for example

        $this->render('export', array(
            'excelModel' => $objPHPExcel,
            'date' => $date,
        ));
    }

2 ответа

Вместо Merchant::model()->findAll() Вы должны использовать CDbDataReader, Вы потеряете удобство ActiveRecord, но он не будет загружать все записи в память, как вы это делали раньше.

Читатель данных возвращается из CDbCommand::query(), Таким образом, вы можете сделать что-то вроде:

$command   = Yii::app()->db->createCommand();
$merchants = $command->query('SELECT * FROM merchants');
foreach($merchants as $merchant) {
    // Add to excel here
}

Я также работал над проектом по экспорту данных из MySQL, чтобы преуспеть. В моем сгенерированном листе XL у меня есть около 30 вкладок, и они представляют собой некоторые сложные формулы для разных ячеек. Я использую PHPExcel для этого. Но в моем случае я генерировал excel как работу cron, потому что это занимало много времени.

Здесь, если у вас есть какой-то сложный шаблон Excel, вы также можете сохранить созданный шаблон на сервере, а затем с помощью класса PHPExcel для чтения и записи вы можете прочитать этот шаблон, записать в него данные и сохранить его в новом файле.

Я думаю, что эта информация поможет вам. Пожалуйста, дайте мне знать, если вы хотите получить дополнительные разъяснения.

Другие вопросы по тегам