silverstripemodeladmin

How to export all rows as CSV in ModelAdmin (SilverStripe 3.1)?


Apparently the GridFieldExportButton only exports the currently visible data-set (paginated). Is there a way to make it export all the rows from a model?

Or alternatively: Is there a way to show all rows (eg. bypass pagination), so that the user can perform an export after showing all the rows? I don't want to show all rows all the time (which would probably be possible by setting ModelAdmin::set_page_length(<ridiculouslyHighNumber>);) but only on demand.


Solution

  • Solved it by creating a custom subclass of the GridFieldExportButton and using this for my models. The key is to use $gridField->getList(); instead of $gridField->getManipulatedList(); in the generateExportFileData method.

    Here's the complete class for anybody interested:

    class GridFieldExportAllButton extends GridFieldExportButton {
        /**
         * Generate export fields for CSV.
         *
         * @param GridField $gridField
         * @return array
         */
        public function generateExportFileData($gridField) {
            $separator = $this->csvSeparator;
            $csvColumns = ($this->exportColumns)
                ? $this->exportColumns
                : singleton($gridField->getModelClass())->summaryFields();
            $fileData = '';
            $columnData = array();
            $fieldItems = new ArrayList();
    
            if($this->csvHasHeader) {
                $headers = array();
    
                // determine the CSV headers. If a field is callable (e.g. anonymous function) then use the
                // source name as the header instead
                foreach($csvColumns as $columnSource => $columnHeader) {
                    $headers[] = (!is_string($columnHeader) && is_callable($columnHeader)) ? $columnSource : $columnHeader;
                }
    
                $fileData .= "\"" . implode("\"{$separator}\"", array_values($headers)) . "\"";
                $fileData .= "\n";
            }
    
            $items = $gridField->getList();
    
            foreach($items as $item) {
                $columnData = array();
                foreach($csvColumns as $columnSource => $columnHeader) {
                    if(!is_string($columnHeader) && is_callable($columnHeader)) {
                        if($item->hasMethod($columnSource)) {
                            $relObj = $item->{$columnSource}();
                        } else {
                            $relObj = $item->relObject($columnSource);
                        }
    
                        $value = $columnHeader($relObj);
                    } else {
                        $value = $gridField->getDataFieldValue($item, $columnSource);
                    }
    
                    $value = str_replace(array("\r", "\n"), "\n", $value);
                    $columnData[] = '"' . str_replace('"', '\"', $value) . '"';
                }
                $fileData .= implode($separator, $columnData);
                $fileData .= "\n";
    
                $item->destroy();
            }
    
            return $fileData;
        }
    }