cakephp: экспорт отфильтрованных данных в Excel - PullRequest
0 голосов
/ 25 июня 2018

, на мой взгляд, у меня есть 2 кнопки, одна в форме для фильтрации данных на основе раскрывающегося списка, а другая для экспорта отфильтрованных данных в Excel.

        <?php
            $options = array();
            $options[0] = 'All';
            $options[1] = 'Due last 6 months';
            $options[2] = 'Due current month';
            $options[3] = 'Due next 3 months';
            $options[4] = 'Due next 6 months';
            $options[5] = 'Due next 12 months';            
        ?>

        <div class="row">
            <?= $this->Form->create() ?>
                <fieldset>                
                    <div class="row">
                        <div class="col-xs-3"><?= $this->Form->input('select_period_id', ['options' => $options, 'empty' => false, 'label' => __('Select Period')]) ?></div>
                        <div class="col-sm-2" style="padding-top:25px;"><?= $this->Form->button(__('Search'), ['class' => 'btn btn-primary']) ?></div>
                    </div>
                </fieldset>
            <?= $this->Form->end() ?>                
        </div>
    <div class="timetables index large-9 medium-8 columns content">
        <?= $this->Html->link(__('Export to xlsx'), array_merge($this->request->query, ['_ext' => 'xlsx']), ['class' => 'btn btn-primary']) ?>
        </div>

Я предположил, что первая кнопкаэто ПОСТ, а второй - ПОЛУЧИТЬ.Я смог получить отфильтрованные данные с помощью первой кнопки, но не со второй:

$data = $this->request->data;
    $select_period = $this->request->data('select_period_id');
    $today = Time::now()->format('Y-m-d');
    $second_date = Time::now();
    $assetsAssignations = $this->AssetsAssignations->find()
        ->contain(['Assets']);

    if($this->request->is(['patch', 'post', 'put'])) 
    {
        if ($select_period == 0) {
            $second_date = $second_date->modify('-6 months');                
            $second_date = $second_date->format('Y-m-d');
        } elseif ($select_period == 1) {                
            $second_date = $second_date->modify('-6 months');                
            $second_date = $second_date->format('Y-m-d');
            $assetsAssignations->where([
                'end_date >=' => $second_date,
                'end_date <=' => $today
                    ]);
             // etc..

    } elseif($this->request->is(['get'])) 
    {
          ???
    }

    $_filename = "xls_report_replacement_" . date('Ymd');
    $this->set(compact('assetsAssignations', '_filename'));        
}       

Я не нашел, что следует указывать при нажатии кнопки экспорта в Excel (GET).

Любая помощь, пожалуйста?

_ обновление: я попробовал это, и я получил ошибку при открытии файла Excel

{
    $data = $this->request->data;
    $select_period = $this->request->data('select_period_id');
    $today = Time::now()->format('Y-m-d');
    $second_date = Time::now();
    $assetsAssignations = $this->AssetsAssignations->find()
        ->contain('Assets');

    debug($this->request->data);

    if (isset($this->request->data['btn1'])) 
    {
        if ($select_period == 0) {
            $second_date = $second_date->modify('-6 months');                
            $second_date = $second_date->format('Y-m-d');
        } elseif ($select_period == 1) {                
            $second_date = $second_date->modify('-6 months');                
            $second_date = $second_date->format('Y-m-d');
            $assetsAssignations->where([
                'Assets.life_end_date >=' => $second_date,
                'Assets.life_end_date <=' => $today
                    ]);
        } elseif ($select_period == 2) {
            $second_date = $second_date->modify('1 month');
            $second_date = $second_date->format('Y-m-d');
            $assetsAssignations->where([
                'Assets.life_end_date >=' => $today,
                'Assets.life_end_date <=' => $second_date
                    ]);

        } elseif ($select_period == 3) {
            $second_date = $second_date->modify('3 months');
            $second_date = $second_date->format('Y-m-d');
            $assetsAssignations->where([
                'Assets.life_end_date >=' => $today,
                'Assets.life_end_date <=' => $second_date
                    ]);
        } elseif ($select_period == 4) {
            $second_date = $second_date->modify('6 months');
            $second_date = $second_date->format('Y-m-d');
            $assetsAssignations->where([
                'Assets.life_end_date >=' => $today,
                'Assets.life_end_date <=' => $second_date
                    ]);
        } elseif ($select_period == 5) {
            $second_date = $second_date->modify('12 months');
            $second_date = $second_date->format('Y-m-d');
            $assetsAssignations->where([
                'Assets.life_end_date >=' => $today,
                'Assets.life_end_date <=' => $second_date
                    ]);
        }
    } elseif (isset($this->request->data['btn2'])) {
        if ($select_period == 0) {
            $second_date = $second_date->modify('-6 months');                
            $second_date = $second_date->format('Y-m-d');
        } elseif ($select_period == 1) {                
            $second_date = $second_date->modify('-6 months');                
            $second_date = $second_date->format('Y-m-d');
            $assetsAssignations->where([
                'Assets.life_end_date >=' => $second_date,
                'Assets.life_end_date <=' => $today
                    ]);
        } elseif ($select_period == 2) {
            $second_date = $second_date->modify('1 month');
            $second_date = $second_date->format('Y-m-d');
            $assetsAssignations->where([
                'Assets.life_end_date >=' => $today,
                'Assets.life_end_date <=' => $second_date
                    ]);

        } elseif ($select_period == 3) {
            $second_date = $second_date->modify('3 months');
            $second_date = $second_date->format('Y-m-d');
            $assetsAssignations->where([
                'Assets.life_end_date >=' => $today,
                'Assets.life_end_date <=' => $second_date
                    ]);
        } elseif ($select_period == 4) {
            $second_date = $second_date->modify('6 months');
            $second_date = $second_date->format('Y-m-d');
            $assetsAssignations->where([
                'Assets.life_end_date >=' => $today,
                'Assets.life_end_date <=' => $second_date
                    ]);
        } elseif ($select_period == 5) {
            $second_date = $second_date->modify('12 months');
            $second_date = $second_date->format('Y-m-d');
            $assetsAssignations->where([
                'Assets.life_end_date >=' => $today,
                'Assets.life_end_date <=' => $second_date
                    ]);
        }
        debug($select_period);
        die();
        return $this->redirect(['action' => 'test.xlsx']);
    }
    $_filename = "xls_report_replacement_" . date('Ymd');
    $this->set(compact('assetsAssignations', '_filename'));        

}   

На мой взгляд, я включил вторую кнопку вформа:

<div class="row">
            <?= $this->Form->create('form_name') ?>
                <fieldset>                
                    <div class="row">
                        <div class="col-xs-3"><?= $this->Form->input('select_period_id', ['options' => $options, 'empty' => false, 'label' => __('Select Period')]) ?></div>
                        <div class="col-sm-2" style="padding-top:25px;"><?php echo $this->Form->submit('Search', array('name'=>'btn1'))?></div>
                        <div class="col-sm-2" style="padding-top:25px;"><?php echo $this->Form->submit('Excel', array('name'=>'btn2'))?></div>

                    </div>
                </fieldset>
            <?= $this->Form->end() ?>

        </div>

Когда я отлаживаю с первой кнопкой:

[
    'select_period_id' => '1',
    'btn2' => 'Excel'
]

select_period_id = '1'

Отладка с помощью кнопки Excel:

[
    'select_period_id' => '2',
    'btn2' => 'Excel'
]
select_period_id = '2'

1 Ответ

0 голосов
/ 26 июня 2018

Включая операторы отладки при создании файла xlsx, вы портите вывод. И перенаправляя на test.xlsx без каких-либо параметров, вы теряете свои опубликованные данные. Вы можете возиться с чем-то вроде этого:

$this->redirect(['action' => 'test.xlsx', 'select_period_id' => $select_period])

Но это ужасно. Вместо перенаправления просто установите тип ответа так:

$this->RequestHandler->renderAs($this, 'xlsx');

Кроме того, у вас много дублированного кода; большая часть этого может быть устранена.

И вам не нужно форматировать даты перед передачей их в построитель запросов, переключившись с класса Time на Date.

Вот моя рекомендуемая версия:

{
    $data = $this->request->data;
    $select_period = $this->request->data('select_period_id');
    $today = FrozenDate::now();
    $assetsAssignations = $this->AssetsAssignations->find()
        ->contain('Assets');

    // This block could be done with a switch instead of if-elseif
    if ($select_period == 0) {
        $start_date = $end_date = null;
    } elseif ($select_period == 1) {                
        // Alternately, $start_date = $today->subMonths(6);
        $start_date = $today->modify('-6 months');
        $end_date = $today;
    } elseif ($select_period == 2) {
        $start_date = $today;
        // Alternately, $start_date = $today->addMonth();
        $end_date = $today->modify('1 month');
    } elseif ($select_period == 3) {
        $start_date = $today;
        // Alternately, $start_date = $today->addMonths(3);
        $end_date = $today->modify('3 months');
    } elseif ($select_period == 4) {
        $start_date = $today;
        $end_date = $today->modify('6 months');
    } elseif ($select_period == 5) {
        $start_date = $today;
        $end_date = $today->modify('12 months');
    }

    if ($start_date) {
        $assetsAssignations->where([
            'Assets.life_end_date >=' => $start_date,
            'Assets.life_end_date <=' => $end_date
        ]);
    }

    // Personally, I'd rename this from btn2 to something like xlsx, here and in the form template
    if (isset($this->request->data['btn2'])) {
        $this->RequestHandler->renderAs($this, 'xlsx');
    }

    $_filename = "xls_report_replacement_" . date('Ymd');
    $this->set(compact('assetsAssignations', '_filename'));
}

Как видите, код намного короче, и он должен быть функционально идентичен.

Обновление: добавьте сверху в контроллер:

use Cake\I18n\FrozenDate;
...