очень медленно конвертируйте phprecord в excel, используя Phpexcel - PullRequest
0 голосов
/ 23 мая 2018

У меня проблема с использованием phpexcel.Я должен конвертировать записи в Excel и скачать.Проблема в том, что процесс очень медленный.Я проверил 2000 - 3000 записей, установил ограничение по времени на 0 и ограничение памяти на 256M, но для обработки и загрузки требуется более 30 минут.Я видел других в Интернете, которые могут загрузить около 6000 записей всего за 10 секунд.

Пожалуйста, кто-нибудь, помогите мне.Что не так с кодом?

Это контроллер:

function download_aplikasi()
{
    $this->Weblog_m->save_log_m("Download aplikasi");
    $data_aplikasi = $this->Io_excel_m->get_aplikasi_m();
    // Create new PHPExcel object
    $objPHPExcel = new PHPExcel();

    $objPHPExcel->getActiveSheet()->getStyle('1:1')->getFont()->setBold(true);

    // Add some data
    $objPHPExcel->setActiveSheetIndex(0)
        ->setCellValue('A1', 'TGL_APLIKASI')
        ->setCellValue('B1', 'CD_CABANG')
        ->setCellValue('C1', 'NAMA_CABANG')
        ->setCellValue('D1', 'NIP')
        ->setCellValue('E1', 'NAMA_PEGAWAI')
        ->setCellValue('F1', 'JABATAN')
        ->setCellValue('G1', 'NAMA_NASABAH')
        ->setCellValue('H1', 'NO_REK')
        ->setCellValue('I1', 'NO_CIF')
        ->setCellValue('J1', 'DOB_NASABAH')
        ->setCellValue('K1', 'JNS_NASABAH')
        ->setCellValue('L1', 'NOMINAL')
        ->setCellValue('M1', 'ID_NASABAH')
        ->setCellValue('N1', 'PRODUK')
        ->setCellValue('O1', 'JNS_PINJAMAN')
        ->setCellValue('P1', 'JNS_USAHA')
        ->setCellValue('Q1', 'LAMA_USAHA')
        ->setCellValue('R1', 'JNS_JAMINAN')
        ->setCellValue('S1', 'PIC_NASABAH')
        ->setCellValue('T1', 'TELP_NASABAH')
        ->setCellValue('U1', 'NAMA_TOKO')
        ->setCellValue('V1', 'KATEGORI')
        ->setCellValue('W1', 'CATATAN')
        ->setCellValue('X1', 'KETERANGAN')
        ->setCellValue('Y1', 'PIC_UNIT')
        ->setCellValue('Z1', 'TELP_PIC')
        ->setCellValue('AA1', 'KAT_PRODUK')
        ->setCellValue('AB1', 'PROGRESS')
        ->setCellValue('AC1', 'PROGRESS_NOTE');

    $i = 1;
    if (count($data_aplikasi) > 0)
    {
        foreach ($data_aplikasi as $row_aplikasi)
        {
            $data_pic = $this->App_m->detilpic_m($row_aplikasi->idpic);
            $i = $i + 1;
            $objPHPExcel->setActiveSheetIndex(0)
                ->setCellValue('A'.$i, date("d/m/Y", strtotime($row_aplikasi->tglaplikasi)))
                ->setCellValue('B'.$i, $row_aplikasi->cdcabang)
                ->setCellValue('C'.$i, $row_aplikasi->namacabang)
                ->setCellValue('D'.$i, $row_aplikasi->nip)
                ->setCellValue('E'.$i, $row_aplikasi->nama_user)
                ->setCellValue('F'.$i, $row_aplikasi->namajabatan)
                ->setCellValue('G'.$i, $row_aplikasi->nama_nasabah)
                ->setCellValue('H'.$i, $row_aplikasi->norek)
                ->setCellValue('I'.$i, $row_aplikasi->nocif)
                ->setCellValue('J'.$i, $row_aplikasi->tgllahir)
                ->setCellValue('K'.$i, $row_aplikasi->jnsnasabah)
                ->setCellValue('L'.$i, $row_aplikasi->nominal_aplikasi)
                ->setCellValue('M'.$i, $row_aplikasi->ktpnasabah)
                ->setCellValue('N'.$i, $row_aplikasi->produk)
                ->setCellValue('O'.$i, $row_aplikasi->jnspinjaman)
                ->setCellValue('P'.$i, $row_aplikasi->jnsusaha)
                ->setCellValue('Q'.$i, $row_aplikasi->lamausaha)
                ->setCellValue('R'.$i, $row_aplikasi->jnsjaminan)
                ->setCellValue('S'.$i, $row_aplikasi->pic_nasabah)
                ->setCellValue('T'.$i, $row_aplikasi->telpnasabah)
                ->setCellValue('U'.$i, $row_aplikasi->namatoko)
                ->setCellValue('V'.$i, $row_aplikasi->kategori)
                ->setCellValue('W'.$i, $row_aplikasi->catatan)
                ->setCellValue('X'.$i, $row_aplikasi->keterangan)
                ->setCellValue('Y'.$i, $data_pic->nama_user)
                ->setCellValue('Z'.$i, $data_pic->nomorhp)
                ->setCellValue('AA'.$i, $row_aplikasi->namaproduct)
                ->setCellValue('AB'.$i, $row_aplikasi->progress)
                ->setCellValue('AC'.$i, $row_aplikasi->progress_note);
        }
    }
    else $objPHPExcel->setActiveSheetIndex(0)
            ->setCellValue('A2', 'No Record Found');

    // Rename worksheet
    $objPHPExcel->getActiveSheet()->setTitle('Aplikasi');


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

    header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
    header('Content-Disposition: attachment;filename="Aplikasi_'.$this->input->post("bulan_kinerja").'.xlsx"');
    header('Cache-Control: max-age=0');
    header('Cache-Control: max-age=1');
    header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); // Date in the past
    header('Cache-Control: cache, must-revalidate'); // HTTP/1.1
    header('Pragma: public'); // HTTP/1.0

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

Это модель:

function get_aplikasi_m()
{
    $periode = $this->input->post("bulan_kinerja");
    $idcabang = $this->input->post("id_cabang");
    $cek_cabang = $this->cek_cabang_m($idcabang);
    $this->db->select('*');
    $this->db->from("tbl_aplikasi");
    $this->db->join("tbl_user", "tbl_user.iduser = tbl_aplikasi.iduser", "Left");
    $this->db->join("tbl_product", "tbl_product.idproduct = tbl_aplikasi.idproduct", "Left");
    $this->db->join("tbl_jabatan", "tbl_user.idjabatan = tbl_jabatan.idjabatan", "Left");
    $this->db->join("tbl_unit", "tbl_product.idunit = tbl_unit.idunit", "Left");
    $this->db->join("tbl_cabang", "tbl_user.idcabang = tbl_cabang.idcabang", "Left");
    $this->db->where("tbl_aplikasi.statusapproval='approve'");
    $this->db->where("MONTH(tbl_aplikasi.tglaplikasi)", date("m", strtotime($periode)));
    $this->db->where("YEAR(tbl_aplikasi.tglaplikasi)", date("Y", strtotime($periode)));

    if ($cek_cabang->jnscabang != "area") $this->db->where("tbl_aplikasi.idcabang", $idcabang);

    $this->db->order_by("tbl_aplikasi.tglaplikasi", "desc");
    return $query = $this->db->get()->result();
}

function getpic_m($idunit)
{
    $this->db->select('*');
    $this->db->from("tbl_user");
    $this->db->join("tbl_jabatan", "tbl_user.idjabatan = tbl_jabatan.idjabatan", "Left");
    $this->db->join("tbl_cabang", "tbl_cabang.idcabang = tbl_user.idcabang", "Left");
    $this->db->where("tbl_user.idunit", $idunit);
    $this->db->where("tbl_user.accstat='active'");
    $this->db->order_by("tbl_user.nama_user", "asc");
    return $query = $this->db->get();
}

1 Ответ

0 голосов
/ 23 мая 2018

PHPExcel устарел и не поддерживается.Он был заменен новой версией под названием PHPSpreadsheet , и вы должны использовать эту версию.Для меня это было быстрее и надежнее.

Конвертировать легко, потому что большинство функций точно такие же.Там не будет много переписывания требуется.Основное изменение заключается в создании объектов чтения, записи, рабочих книг и листов.

Я останусь с PHPExcel для этого ответа.

Есть несколько вещей, которые вы можете сделать, чтобы оптимизировать код.Во-первых, перехватите активный объект листа для повторного использования вместо повторного вызова setActiveSheetIndex() и getActiveSheet().

// Create new PHPExcel object
$objPHPExcel = new PHPExcel();
// A new workbook always sets the active sheet index to the first sheet
// Capture the "active sheet" object for easy reuse.
$activeSheet = $objPHPExcel->getActiveSheet();

По возможности старайтесь устанавливать блоки значений ячеек, используя массив вместо нескольких вызовов setCellValue().Например:

// Add some data
$rowArray = ['TGL_APLIKASI', 'CD_CABANG', 'NAMA_CABANG', 'NIP',
    'NAMA_PEGAWAI', 'JABATAN', 'NAMA_NASABAH', 'NO_REK', 'NO_CIF',
    'DOB_NASABAH', 'JNS_NASABAH', 'NOMINAL', 'ID_NASABAH', 'PRODUK',
    'JNS_PINJAMAN', 'JNS_USAHA', 'LAMA_USAHA', 'JNS_JAMINAN',
    'PIC_NASABAH', 'TELP_NASABAH', 'NAMA_TOKO', 'KATEGORI',
    'CATATAN', 'KETERANGAN', 'PIC_UNIT', 'TELP_PIC', 'KAT_PRODUK', 
    'PROGRESS', 'PROGRESS_NOTE'];

//add the array to the activesheet
$activeSheet->fromArray($rowArray, NULL, 'A1');

Подробнее о Установка диапазона ячеек из массива

Вы можете использовать fromArray() для добавления результатов базы данных, но это потребуетизменение в модели.Ваша модель использует result(), который возвращает массив объектов.Если вы вернете result_array(), вместо этого будет легко использовать данные для применения всех строк одним вызовом.

Измените последнюю строку function get_aplikasi_m() на эту

return $this->db->get()->result_array();

Youхотя есть два осложнения.Во-первых, форматирование даты в первом столбце.Вы можете и, возможно, должны пересмотреть свой запрос, чтобы сделать это во время поиска данных.Но я не буду показывать, как это сделать.

Второе осложнение - добавление элементов $data_pic.Было бы проще, если бы App_m->detilpic_m() вернул result_array(), но я продолжу с этим как есть.

Добавление строк и столбцов из данных модели выглядит следующим образом.

$data_aplikasi = $this->Io_excel_m->get_aplikasi_m();
if (count($data_aplikasi) > 0)
{
    //walk through all records to format date and add pic data
    foreach ($data_aplikasi as $key => $row_aplikasi)
    {
        // format the date and make sure the 
        // main array is updated with the change
        $data_aplikasi[$key]['tglaplikasi'] = date("d/m/Y", strtotime($row_aplikasi['tglaplikasi']));

        $data_pic = $this->App_m->detilpic_m($row_aplikasi['idpic']);
        //make an array from $data_pic values
        $pic_data = [$data_pic->nama_user, $data_pic->nomorhp];
        //get the index where pic data should be inserted
        $index = array_search("keterangan", array_keys($row_aplikasi));
        // insert $pic_data into $row_aplikasi at the right place 
        // and update the model result at the same time
        $data_aplikasi[$key] = array_splice($row_aplikasi, $index, 0, $pic_data);
    }
    //add $data_aplikasi array to the activesheet with one call
    $activeSheet->fromArray($data_aplikasi, NULL, 'A2');
}
else
{
    $activeSheet->setCellValue('A2', 'No Record Found');
} 

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

public function download_aplikasi()
{
    $this->Weblog_m->save_log_m("Download aplikasi");
    // Create new PHPExcel object
    $objPHPExcel = new PHPExcel();
    // A new workbook always sets the active sheet index to the first sheet
    // Capture the "active sheet" object sheet
    $activeSheet = $objPHPExcel->getActiveSheet();

    // Name the worksheet
    $activeSheet->setTitle('Aplikasi');

    $activeSheet->getStyle('1:1')->getFont()->setBold(true);

    // Add some data
    $rowArray = ['TGL_APLIKASI', 'CD_CABANG', 'NAMA_CABANG', 'NIP',
        'NAMA_PEGAWAI', 'JABATAN', 'NAMA_NASABAH', 'NO_REK', 'NO_CIF',
        'DOB_NASABAH', 'JNS_NASABAH', 'NOMINAL', 'ID_NASABAH', 'PRODUK',
        'JNS_PINJAMAN', 'JNS_USAHA', 'LAMA_USAHA', 'JNS_JAMINAN',
        'PIC_NASABAH', 'TELP_NASABAH', 'NAMA_TOKO', 'KATEGORI',
        'CATATAN', 'KETERANGAN', 'PIC_UNIT', 'TELP_PIC', 'KAT_PRODUK',
        'PROGRESS', 'PROGRESS_NOTE'];

    //add the array to the activesheet
    $activeSheet->fromArray($rowArray, NULL, 'A1');


    $data_aplikasi = $this->Io_excel_m->get_aplikasi_m();
    if (count($data_aplikasi) > 0)
    {
        //walk through all records to format date and add pic data
        foreach ($data_aplikasi as $key => $row_aplikasi)
        {
            // format the date and make sure the 
            // main array is updated with the change
            $data_aplikasi[$key]['tglaplikasi'] = date("d/m/Y", strtotime($row_aplikasi['tglaplikasi']));

            $data_pic = $this->App_m->detilpic_m($row_aplikasi['idpic']);
            //make an array from $data_pic values
            $pic_data = [$data_pic->nama_user, $data_pic->nomorhp];
            //get the index where pic data should be inserted
            $index = array_search("keterangan", array_keys($row_aplikasi));
            // insert $pic_data into $row_aplikasi at the right place 
            // and update the model result at the same time
            $data_aplikasi[$key] = array_splice($row_aplikasi, $index, 0, $pic_data);
        }
        //add $data_aplikasi array to the activesheet with one call
        $activeSheet->fromArray($data_aplikasi, NULL, 'A2');
    }
    else
    {
        $activeSheet->setCellValue('A2', 'No Record Found');
    }

    header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
    header('Content-Disposition: attachment;filename="Aplikasi_'.$this->input->post("bulan_kinerja").'.xlsx"');
    header('Cache-Control: max-age=0');
    header('Cache-Control: max-age=1');
    header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); // Date in the past
    header('Cache-Control: cache, must-revalidate'); // HTTP/1.1
    header('Pragma: public'); // HTTP/1.0

    $objWriter = IOFactory::createWriter($objPHPExcel, 'Excel2007');
    $objWriter->save('php://output');
    //Don't use exit, let CI finish as designed by letting the controller return
    //exit;
}

Я предположил, что $this->Io_excel_m->get_aplikasi_m() возвращает поля в том порядке, в котором вы использовали их в исходном коде.Если поля расположены не в этом порядке, вам придется либо переставить $data_aplikasi, либо изменить запрос, чтобы поля находились в нужном вам порядке.Лично я бы сделал второе.

Трудно сказать наверняка, но похоже, что вы могли бы изменить запрос (используя JOIN), чтобы получить поля $data_pic во время вызова get_aplikasi_m(),

Поле даты может быть возвращено из запроса также в нужном вам формате.

Эти два изменения модели устранят цикл foreach, используемый для изменения data_aplikasi.Выполнение будет быстрее, потому что вы удалите тысячи вызовов базы данных, чтобы получить $data_pic.Как правило, лучше не делать запросы внутри цикла - это требует много системных ресурсов и времени.

Я не тестировал этот код (нет данных), поэтому вполне возможно, что есть логические и синтаксические ошибки.,Концепция звучит и является техникой, которую я успешно использовал.

...