Export records base on FilterScope to csv, json

Hi,
I want to share my latest plugin creation work. The client needs to export records based on a filter from the list of records to csv. It needs to export the total records, based on the filter and based on the filter the given page of records.

My springboard for this issue was topic Select all record on filtered list [resolved] - October CMS. Thanks to the author of the solution. I needed to extend it with a few options. I also added an option to export only records that are checked.

The first thing you need to do is create a plugin with models, a controller, and also a model for export. Then add the following function to the controller for the list of records, name it as you wish.

path: AuthorPlugin\NamePlugin\Controllers\ExampleController.php

# add new function
public function onGetFilteredRecords(){   
        $this->makeLists();

        # get ListWidget 
        $listWidget = $this->asExtension('ListController')->listGetWidget();

        # query params - page number
        $page = get('page');
        
        # get filename from data attribute
        $filename = post('filename');

        # post payload data - list of checked records
        $checked = post('checked');

        # how many records on page
        $recordsPerPage = $listWidget->recordsPerPage;

        # prepare query FilterScope from listWidget
        $query = $listWidget->prepareQuery();

        # need visible columns on list
        $columns = $listWidget->getVisibleColumns();
        
        # prepare simple columns array column_key => column_label to export
        $columnList = [];
        foreach ($columns as $attribute => $column) {
            $columnList[$attribute] = $column->label;
        }

        # if specific records are selected 
        if(isset($checked)) {
            $query->whereIn('id', $checked);
            # then no need query GET param Page
            $page = null;
        }
        
        # if only query GET param Page
        if(isset($page) && !empty($page)) {
            $query->forPage($page, $recordsPerPage);
        }

        # get all records
        $records = $query->get();

        # using Export model
        $modelExport = new \AuthorPlugin\NamePlugin\Models\ExampleExport();

        # set records to process export
        $modelExport->setModelRecords($records);

        # need know file extension
        $ext = pathinfo($filename, PATHINFO_EXTENSION);

        # set extension to model Export
        $exportOptions['fileFormat'] = $ext;

        # set file format
        $modelExport->file_format = $exportOptions['fileFormat'];

        # need create file reference to download
        $reference = $modelExport->export($columnList, $exportOptions);

        # create download full link to file
        $fileUrl = $this->actionUrl('download',$reference.'/'.$filename);

        return [
            'fileUrl' => $fileUrl
        ];       
    }

The second thing what you need is edit your model ExampleExport to add custom function to set your model records to process.

path: AuthorPlugin\NamePlugin\Models\ExampleExport.php

class ExampleExport extends \Backend\Models\ExportModel
{
    protected $_records;

    # new function
    public function setModelRecords($records) 
    {
        $this->_records = $records;
    }

    public function exportData($columns, $sessionKey = null)    
    {   
        # edit this line
        $records = (isset($this->_records)) ? $this->_records : Example::all();

        $records->each(function($record) use ($columns) {
            $record->addVisible($columns);
        });
        return $records->toArray();
    }
}

The third thing what you need add button to list toolbar.

path: AuthorPlugin\NamePlugin\Controllers\example\_list_toolbar.php

..buttons before...

<button
        class="btn btn-default"
        data-request-data="{filename:'export.csv'}"
        data-list-checked-request
        data-request-success="window.location = data.fileUrl; setTimeout(function(){ window.location.reload() },500)"
        data-stripe-load-indicator
        data-request="onGetFilteredRecords">
        Get Filtered Records
    </button>

..buttons after...

Data attributes:
data-request-data=“{filename:‘export.csv’}” - this defines the filename with the extension, if you want to change the format to json, rewrite the extension
data-request-success=“window.location = data.fileUrl; setTimeout(function(){ window.location.reload() },500)” - function onGetFilteredRecords return object with fileUrl to download file, setTimeout needed because if some records is checked we need to reset table after download file

Change path: AuthorPlugin\NamePlugin to your path to plugin, also name of ListController and ExampleExport model

I will be very happy if you send any suggestions on how to make even better use of the original export model for exporting filtered records.

3 Likes

thanks for this code.

I am trying to use it in my project but can’t make it work.
I have an error 404 after clicking on the button.
Any idea what I missed please?

Can you share the code?

exactly same code as yours

I’ve tried the code and everything works fine, 404 indicates incorrect URL. i’d like to help but I don’t know how.