Экспорт данных из таблицы ExtJS Grid в таблицу Excel

Как сделать экспорт данных из таблицы ExtJS Grid в таблицу Excel?

Данное решение экспериментальное и имеет место для небольших, одностраничных, таблиц типа xtype:'grid' с хранилищем типа xtype:'store'.

Для реализации функционала, нам понадобится:
  • Библиотека ExtJS — JavaScript фреймворк. Если вы слышите это впервые, статья не будет полезна.
  • PHP сервер весрии 5+
  • PHPExcel — библиотека для создание Excel документа. Ссылка на сайт производителя.


Grid таблица
Для примера берём простейшую таблицу с тремя колонками ID, Имя, Дата. В данном примера поля имеют тип string (текст).

Представляю полностью рабочий код, комментарии напишу к строкам, для его просмотра просто создайте файл следующего содержания:
<!DOCTYPE>
<html xmlns="http://www.w3.org/1999/html">
<head>
    <link href="http://cdn.sencha.com/ext/gpl/4.2.0/resources/css/ext-all.css" rel="stylesheet"/>
    <script src="http://cdn.sencha.com/ext/gpl/4.2.0/ext-all.js"></script>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title>Пример экпорта в Excel документ</title>
</head>
<body>
<script type="text/javascript">
    /* Всё пишем под обработчик события "всё загружено и готово" */
    Ext.onReady(function () {
        /* создаём хранилище данных */
        Ext.create('Ext.data.Store', {
            storeId: 'DataStore',
            fields: [
                {name: 'id', type: 'string'},
                {name: 'name', type: 'string'},
                {name: 'data', type: 'string'}
            ],
            data: [
                {
                    id: '1',
                    name: 'test1',
                    data: '29-12-2014'
                },
                {
                    id: '2',
                    name: 'test2',
                    data: '30-12-2014'
                },
                {
                    id: '3',
                    name: 'test3',
                    data: '31-12-2014'
                }
            ]
        });

        /* создание окна отчёта */
        Ext.create('Ext.container.Viewport', {
            layout: 'fit', // растянуть на весь экран
            items: [
                {
                    xtype: 'grid',
                    title: 'Таблица - пример', // заголовок таблицы, он будет первой строкой Excel документа
                    store: Ext.data.StoreManager.lookup('DataStore'), // указываем с какими данными работать таблице
                    columns: [ // массив колонок с привязкой к данным
                        {
                            text: 'ID',
                            dataIndex: 'id'
                        },
                        {
                            text: 'Имя',
                            dataIndex: 'name'
                        },
                        {
                            text: 'Дата',
                            dataIndex: 'data'
                        }
                    ],
                    dockedItems: [ // панель иконок и кнопок
                        {
                            xtype: 'toolbar',
                            dock: 'top',
                            items: [
                                '->', // вертикальный разделитель
                                {
                                    xtype: 'button',
                                    text: 'Експорт в Excel', // надпись на кнопке экспорта
                                    handler: function () {
                                        /* запрос всех объектов из Store */
                                        var elements = Ext.data.StoreManager.lookup('DataStore').getRange();

                                        /* создание массива объектов с данными */
                                        var jsonData = [];
                                        Ext.Array.each(elements, function (item, index) {
                                            jsonData.push(item.getData());
                                        });

                                        /*
                                         *   Отправка запроса на сервер для создания файла Excel
                                         *   jsonData - данные, подготовленные из Store в формате JSON
                                         *   reportName - название отчёта
                                         *   headersArray - названия заголовков, соблюдать порядок, в формате JSON
                                         *   
                                         *   Первый запрос формирует данные и сохраняет в сессии, второй генерирует сам excel файл.
                                         *   Второй запрос вызывается только после того, как первый сообщил о готовности данных
                                         * */
                                        Ext.Ajax.request({
                                            url: '/back.php', // url скрипта для отправки данных
                                            params: {
                                                jsonData: Ext.encode(jsonData),
                                                reportName: this.up('grid').title,
                                                headersArray: Ext.encode([ // таблица названий колонок в excel документе
                                                    'ID',
                                                    'Имя',
                                                    'Дата'
                                                ])
                                            },
                                            success: function (response) {
                                                // process server response here
                                                var rObj = Ext.decode(response.responseText);
                                                // загрузка файла с результатами
                                                window.location.href = '/back.php?fileKey=' + rObj.fileKey; // URL скрипта для скачивания файла
                                            }
                                        });
                                    }
                                }
                            ]
                        }
                    ]
                }
            ]
        });
    });
</script>

</body>
</html>

Серверная часть — файл back.php
Как я писал в начале статьи, нам понадобиться доступ к библиотеке PHPExcel (ссылка в начале статьи). Сама обработка запросов происходит в серверном скрипте, который находится в файле back.php. Вы можете сами выбирать имя и места расположения скрипта, главное, не забыть правильно указать пусть в клиентской части ExtJS.
<?php
/**
 * Класс предназначен для конвертации Grid Data Store в документ формата Excel
 * для конвертации используется PHPEXCEL
 */

/* подключение библиотеки PHPEXCEL */
include_once 'phpexcel.php'; // путь к библиотеке phpexcel

class Tools_Grid2Excel
{
    public function getExcelFile($storeData, $headerData = array(), $reportName = 'Exported Report')
    {
        // создание объекта Excell
        $php_excel = new PHPExcel();

        // установка базовых параметров
        $properties = $php_excel->getProperties();
        $php_excel->setProperties($properties);
        $rowDataInsertIndex = 1;

        // выбираем активны й лист
        $php_excel->setActiveSheetIndex(0);

        // определяем формат листа
        $php_excel->getActiveSheet()->getPageSetup()->setOrientation(
            PHPExcel_Worksheet_PageSetup::ORIENTATION_LANDSCAPE
        );
        $php_excel->getActiveSheet()->getPageSetup()->setPaperSize(
            PHPExcel_Worksheet_PageSetup::PAPERSIZE_A4
        );

        // заполнение листа данными
        $sheet = $php_excel->getActiveSheet();

        // параметры заголовка
        $sheet->getRowDimension(1)->setRowHeight(35);
        $sheet->setCellValue('A' . $rowDataInsertIndex, $reportName);
        $sheet->getStyle('A' . $rowDataInsertIndex)->getAlignment()->setWrapText(
            true
        ); // для использования перевода строки "\n"
        $rowDataInsertIndex++;

        // название листа
        $sheet->setTitle('Лист1');
        // параметры листа
        $sheet->getPageMargins()->setTop(0.5);
        $sheet->getPageMargins()->setRight(0.5);
        $sheet->getPageMargins()->setLeft(0.5);
        $sheet->getPageMargins()->setBottom(0.5);
        // параметры ячеек
        $sheet->getColumnDimension('A')->setWidth(15);
        $sheet->getColumnDimension('B')->setWidth(15);
        $sheet->getDefaultRowDimension()->setRowHeight(16);
        $sheet->getDefaultColumnDimension()->setWidth(16);

        /* вставляем заголовок в лист */
        if (!empty($headerData)) {
            $sheet->fromArray($headerData, null, 'A' . $rowDataInsertIndex, true);
            $rowDataInsertIndex++;
        }

        /* вставляем данные отчёта на лист */
        $sheet->fromArray($storeData, null, 'A' . $rowDataInsertIndex, true);

        /* уменьшение индекса вствки для использования в дальнейшем форматировании */
        $rowDataInsertIndex--;

        // определение максимальных размеров документа
        $max_col = $sheet->getHighestColumn();
        $max_row = $sheet->getHighestRow();
        $highestColumnIndex = PHPExcel_Cell::columnIndexFromString($max_col);

        // применение форматирование рамки
        $sheet->getStyle("A$rowDataInsertIndex:" . $max_col . $max_row)->applyFromArray(
            array(
                'borders' => array(
                    'allborders' => array(
                        'style' => PHPExcel_Style_Border::BORDER_THIN
                    )
                )
            )
        );
        // выравнивание по горизонтали и вертикали всех
        $sheet->getStyle("A$rowDataInsertIndex:" . $max_col . $max_row)->getAlignment()
            ->setVertical(
                PHPExcel_Style_Alignment::VERTICAL_CENTER
            );
        $sheet->getStyle("A$rowDataInsertIndex:" . $max_col . $max_row)->getAlignment()
            ->setHorizontal(
                PHPExcel_Style_Alignment::HORIZONTAL_LEFT
            );
        // заливка шапки сереньким (D8D8D8D8)
        $sheet->getStyle("A$rowDataInsertIndex:" . $max_col . $rowDataInsertIndex)->applyFromArray(
            array(
                'font' => array(
                    'bold' => true,
                ),
                'fill' => array(
                    'type'  => PHPExcel_Style_Fill::FILL_SOLID,
                    'color' => array(
                        'argb' => 'D8D8D8D8',
                    ),
                )
            )
        );

        // объединение ячеек заголовка
        $sheet->mergeCells("A1:" . $max_col . '1');
        // выравнивание по горизонтали и вертикали заголовка
        $sheet->getStyle("A1:" . $max_col . '1')->getAlignment()
            ->setVertical(
                PHPExcel_Style_Alignment::VERTICAL_CENTER
            );
        $sheet->getStyle("A1:" . $max_col . '1')->getAlignment()
            ->setHorizontal(
                PHPExcel_Style_Alignment::HORIZONTAL_CENTER
            );

        /* автоширина */
        for ($col = 'A'; $col <= $max_col; $col++) {
            $sheet->getColumnDimension($col)->setAutoSize(true);
        }


        // вывод файла
        $writer = PHPExcel_IOFactory::createWriter($php_excel, 'Excel5');
        ob_start();
        $writer->save('php://output');

        return ob_get_clean();
    }

}

/* обработка входящих параметров и создание файла */
if (!empty($_REQUEST['jsonData'])) {
    /* инициализация PHPEXCEL */
    $g2excel = new Tools_Grid2Excel();

    /* кодирование имени файла, для сохранения в сессии */
    $fileKey = md5($_REQUEST['jsonData']);

    /* сохранение имени файла в сессии */
    if (!empty($_REQUEST['reportName'])) {
        $_SESSION['gridDataExcelFile'][$fileKey]['name']
            = preg_replace('/\s/', '_', $_REQUEST['reportName'])
            . '.xls';
        $reportName = $_REQUEST['reportName'];
    } else {
        $_SESSION['gridDataExcelFile'][$fileKey]['name'] = 'Report.xls';
        $reportName = null;
    }

    /* проверка на наличие заголовка */
    if (!empty($_REQUEST['headersArray'])) {
        $headersArray = json_decode($_REQUEST['headersArray'], true);
    } else {
        $headersArray = array();
    }

    /* сохранение данных в сессии */
    $_SESSION['gridDataExcelFile'][$fileKey]['data'] = $g2excel->getExcelFile(
        json_decode($_REQUEST['jsonData'], true),
        $headersArray,
        $reportName
    );

    /* добавление в результаты работы скрипта поля с именем файла в сессии */
    header('Content-Type: application/json');
    echo json_encode(array('fileKey'=>$fileKey));
} elseif (!empty($_REQUEST['fileKey'])) {
    header('Content-Type: application/vnd.ms-excel');
    header(
        'Content-Disposition: attachment;filename="'
        . $_SESSION['gridDataExcelFile'][$_REQUEST['fileKey']]['name'] . '"'
    );
    header('Cache-Control: max-age=0');
    echo $_SESSION['gridDataExcelFile'][$_REQUEST['fileKey']]['data'];
    unset($_SESSION['gridDataExcelFile'][$_REQUEST['fileKey']]);
}

Если в скриптах нет ошибки и Вы всё сделали правильно, то при нажатии на кнопку «Экспорт в Excel» появится диалог сохранения файла.

Пример содержимого файла Excel:
Пример таблицы результатов
  • 0
  • 24 декабря 2014, 17:25
  • igorrius

Комментарии (0)

RSS свернуть / развернуть
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.
comments powered by Disqus