Статьи

Создание файлов Excel и диаграмм с PHPExcel

После моей статьи « Как создавать документы Microsoft Word с помощью PHP » (с использованием возможностей взаимодействия в Windows) было довольно много комментариев, призывающих к чистой реализации PHP, то есть к использованию только файлов универсальной библиотеки PHP для управления файлами Office.

В этой статье мы увидим, как использовать библиотеку PHPExcel для предоставления функции «Экспорт в Excel» в веб-приложении, чтобы пользователь мог экспортировать данные в файл Excel 2007/2013 для дальнейшего анализа.

ПРИМЕЧАНИЕ. Существует несколько библиотек PHP, которые могут обеспечивать манипуляции с файлами в Excel (и Office). Используемая здесь библиотека называется PHPExcel, подмножество PHPOffice, которое можно клонировать здесь .

Цели

После этого урока мы получим:

  • Лист с информацией об игре (дата игры, команды, счет, статус победа / поражение) моей любимой команды НБА — LA Lakers в сезоне 2013-14.
  • Кнопка, которая будет экспортировать данные в файл Excel 2013.
  • Этот файл Excel будет заполнен некоторыми дополнительными аналитическими данными и диаграммой, также сгенерированной PHP и Excel.

Давайте начнем.

подготовка

Чтобы использовать PHPExcel, мы должны иметь версию PHP выше 5.2.0. Также необходимо включить 3 расширения PHP: php_zip (который необходим для работы с форматами Office 2007), php_xml и php_gd2 (необязательно, но требуется для автоматического расчета ширины столбца).

Далее установите библиотеку через Composer .

Конечно, мы должны иметь нашу базу данных и работать. Дамп данных для этого урока ( lakers.sql ) был загружен в lakers.sql связанный с этой статьей . Данные извлекаются с помощью простого оператора SQL: « select * from lakers » (всего 90 записей, в том числе 8 предсезонных и 82 игр регулярного сезона).

Кроме того, эта демонстрация использует Silex в качестве инфраструктуры MVC. Twig будет использоваться в качестве шаблонного движка. Убедитесь, что необходимые зависимости правильно указаны в вашем файле composer.json .

Индексный файл

index.php будет точкой входа для нашего приложения Silex. Будет определено два маршрута:

 $app->get('/', function () use ($app) { $c=new trExcel\Excel(); return $c->index($app); }); $app->post('/export', function () use ($app) { $c=new trExcel\Excel(); return $c->export($app); }); 

Маршрут '/' будет нашей точкой входа и отображает данные и кнопку «Экспорт». Маршрут '/export' будет выполнять процесс обработки, который фактически экспортируется в Excel. Обе функции заключены в пользовательский класс ( classExcel.php ). В оставшейся части этой статьи мы сосредоточимся на этом файле — или, точнее, на функции export и связанных с ней функциях, определенных в этом файле, и обсудим несколько важных аспектов манипулирования Excel с использованием библиотеки PHPExcel.

Приложение Excel и его метаданные

Когда мы нажимаем значок, чтобы запустить Excel, приложение Excel запускается. В обычных условиях он также будет содержать рабочую книгу с 3 (в Excel 2013, только 1) рабочими листами. Рабочий лист — это «холст», с которым мы играем. Это два самых важных термина в Excel. Другие важные термины могут включать в себя: ячейка, диапазон и т. Д.

Чтобы создать экземпляр файла Excel, мы используем:

 $ea = new \PHPExcel(); // ea is short for Excel Application 

Экземпляр приложения Excel обычно сопоставляется с физическим файлом Excel. У него есть собственные метаданные для описания файла, который мы создаем. Метаданные отображаются, когда мы «Alt-Enter» файл Excel (или щелкните правой кнопкой мыши на этом файле и выберите «Свойства»):

Свойства, показанные в диалоговом окне выше, будут иметь соответствующие методы setXXXX для установки этих свойств, где XXXX практически идентичен именам свойств, перечисленным в диалоговом окне:

 $ea->getProperties() ->setCreator() ->setTitle('PHPExcel Demo') ->setLastModifiedBy() ->setDescription('A demo to show how to use PHPExcel to manipulate an Excel file') ->setSubject('PHP Excel manipulation') ->setKeywords('excel php office phpexcel lakers') ->setCategory('programming') ; 

Методы ( setXXXX ) достаточно setXXXX и довольно хорошо отображаются в диалоге «Свойства». Есть некоторые несоответствия в отображении, но они не слишком сложны для нас, чтобы установить соединение (например, «Авторы» будут сопоставлены с setCreator ).

Рабочий лист и популяция клеток

Рабочий лист — это, вероятно, объект, которым мы будем больше всего манипулировать: заполнение ячеек данными или формулами, применение стилей, выполнение фильтрации данных, вставка диаграммы и т. Д.

Чтобы получить ссылку на рабочий лист, мы используем:

 $ews = $ea->getSheet(0); $ews->setTitle('Data'); 

Листы в рабочей книге всегда индексируются 0. Таким образом, 1-й (и до сих пор единственный) лист будет Sheet Zero. Имя этого листа по умолчанию всегда «Рабочий лист», и мы можем изменить его с setTitle метода setTitle .

Для заполнения ячейки / ячеек у нас есть как минимум два варианта:

  1. Для этих заголовков, заголовков и других описательных элементов мы будем заполнять их один за другим, используя метод setCellValue .
  2. Для структурированных данных, большая часть которых поступает из оператора select SQL, мы будем использовать метод fromArray .
 $ews->setCellValue('a1', 'ID'); // Sets cell 'a1' to value 'ID $ews->setCellValue('b1', 'Season'); ... //Fill data $ews->fromArray($data, ' ', 'A2'); 

Метод fromArray принимает 3 параметра:
1. источник данных в виде массива;
2. значение «заполнитель», если данные равны NULL;
3. ссылка на ячейку, чтобы начать заполнение (слева направо, затем вверх).

ПРИМЕЧАНИЕ. Когда мы используем PDO для извлечения данных, просто $res = $q->fetchAll(\PDO::FETCH_ASSOC); вызов заставит возвращенный набор данных результата содержать только связанный массив, без индекса. Если fetchall вызывается без опции PDO::FETCH_ASSOC , результирующий набор будет фактически содержать два набора идентичных данных, один в связанной форме массива, другой в индексированной форме, и будет создавать дубликаты в файле Excel при использовании fromArray .

Мы также можем захотеть стилизовать строку заголовка ( ID , сезон и т. Д.). Для этого у нас также есть два способа:

 $header = 'a1:h1'; $ews->getStyle($header)->getFill()->setFillType(\PHPExcel_Style_Fill::FILL_SOLID)->getStartColor()->setARGB('00ffff00'); $style = array( 'font' => array('bold' => true,), 'alignment' => array('horizontal' => \PHPExcel_Style_Alignment::HORIZONTAL_CENTER,), ); $ews->getStyle($header)->applyFromArray($style); 

Одним из способов является использование некоторых методов get для извлечения объекта стиля, который мы хотим изменить, и его изменения. Мы делаем это для стиля «фоновой заливки».

Другой заключается в объявлении массива «style» и указании стилей, которые мы хотим изменить, и на что их изменить. Затем мы используем applyFromArray для применения стилей в пакете. Здесь мы изменили шрифт и выравнивание.

Оба метода поддерживают диапазон как свой параметр ( $header='a1:h1'; ), что очень удобно.

Наконец, мы можем захотеть отрегулировать ширину столбца, чтобы они соответствовали максимальной отображаемой длине в каждом столбце:

 for ($col = ord('a'); $col <= ord('h'); $col++) { $ews->getColumnDimension(chr($col))->setAutoSize(true); } 

К сожалению, это не поддерживает параметр диапазона, поэтому мы используем цикл for чтобы это произошло.

Если мы сохраним файл сейчас — мы обсудим сохранение позже — мы увидим, что файл XLSX заполнен данными и правильно отформатирован:

Добавление другого листа и вставка формул

Я всегда использую отдельный лист для хранения исходных данных и как минимум еще один лист для отображения сводной и / или аналитической информации.

Чтобы вставить новый лист, мы делаем:

 $ews2 = new \PHPExcel_Worksheet($ea, 'Summary'); $ea->addSheet($ews2, 0); $ews2->setTitle('Summary'); 

Метод addSheet принимает два параметра.

  • $ews2 : экземпляр листа Excel, который мы должны вставить;
  • $location : индекс этой таблицы. Таким образом, 0 означает, что он должен стать первым. -1 означает, что он должен быть последним.

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

 $ews2->setCellValue('b2', '=COUNTIF(Data!G2:G91, "W")-COUNTIF(Data!G2:G9, "W")'); $ews2->setCellValue('b3', '=COUNTIF(Data!G2:G91, "L")-COUNTIF(Data!G2:G9, "L")'); $ews2->setCellValue('b4', '=b2/(b2+b3)'); 

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

ПРИМЕЧАНИЕ. Обратите особое внимание на ссылку на ячейку ( G2:G91 ). Ленивый способ написания этой формулы — использовать такой диапазон, как G:G Это прекрасно работает, когда на листе нет графика. Если есть диаграмма, нотация G:G потерпит неудачу, выдав исключение.

Этот «сводный» лист выглядит так:

Показанный в ячейке B4 устанавливается с помощью следующего кода:

 $ews->getStyle('b4')->getNumberFormat()->setFormatCode(\PHPExcel_Style_NumberFormat::FORMAT_PERCENTAGE); 

Пожалуйста, обратите внимание на некоторые проблемы с дизайном здесь. Для A1 я применил следующий стиль:

 $ews2->setCellValue('a1', 'Lakers 2013-2014 Season'); $style = array( 'font' => array('bold' => true, 'size' => 20,), 'alignment' => array('horizontal' => \PHPExcel_Style_Alignment::HORIZONTAL_LEFT,), ); $ews2->mergeCells('a1:b1'); $ews2->getStyle('a1')->applyFromArray($style); $ews2->getColumnDimension('a')->setAutoSize(true); 

Результат показывает, что вес шрифта, размер шрифта и выравнивание применяются правильно. Слияние A1 и B1 в A1 также сделано правильно. Но метод setAutoSize терпит неудачу в этой объединенной ячейке. В результате эта ячейка ( A1 ) все еще сжата. Это означает, что автоматический расчет ширины не всегда будет работать. Ну, в общем, ничего страшного.

Картинка стоит тысячи слов

Всегда приятно иметь визуальное представление наших данных, поэтому диаграмма пригодится. В Excel есть богатый набор встроенных диаграмм, из которых мы можем выбирать. PHPExcel может использовать почти все из них. Первый график, который мы должны создать, это линейный график, показывающий взлеты и падения очков в каждой игре команды Лейкерс и ее противника.

Создание диаграммы — это длительная работа по кодированию, даже при поддержке библиотеки. Полный код этого процесса можно найти в addChart1 и addChart2 которые находятся в нашем файле classExcel.php . Я просто объясню ключевые шаги.

  • Метки серии данных

Метка ряда данных идентифицирует ряд данных, присваивая ему имя (метку). В нашем случае, если мы хотим показать результаты «Лейкерс» и их оппонента, мы смотрим на две метки: « Self Score и « Opponent Score . Их метки можно найти в D1 и E1 соответственно:

 $dsl=array( new \PHPExcel_Chart_DataSeriesValues('String', 'Data!$D$1', NULL, 1), new \PHPExcel_Chart_DataSeriesValues('String', 'Data!$E$1', NULL, 1), ); 

Метка серии данных на самом деле является экземпляром \PHPExcel_Chart_DataSeriesValues . Конструктор содержит четыре параметра:

  1. Тип. Для метки, без сомнения, это должно быть «String»;
  2. Источник. Это в D1 или E1 ;
  3. Формат. Обычно достаточно указать NULL, и будет использоваться формат по умолчанию;
  4. Граф. Сколько данных в источнике. Обычно должно быть 1.

  • Метка значения оси X

Это идентифицирует метку для оси X. Например, в «2013-11-15» Лейкерс набрал 86, а их соперник — 89. « 2013-11-15 » — это метка для этих двух результатов. В нашем случае мы будем использовать столбец «Дата воспроизведения» от строки 2 до строки 91:

 $xal=array( new \PHPExcel_Chart_DataSeriesValues('String', 'Data!$F$2:$F$91', NULL, 90), ); 

Конструктор такой же, как и параметры.

  • Значения ряда данных

Мы будем использовать «Self Score» (столбец D) и «Opponent Score» (столбец E). Оба из ряда 2 в ряд 91.

 $dsv=array( new \PHPExcel_Chart_DataSeriesValues('Number', 'Data!$D$2:$D$91', NULL, 90), new \PHPExcel_Chart_DataSeriesValues('Number', 'Data!$E$2:$E$91', NULL, 90), ); 

После того, как у нас есть 3 вышеупомянутых критических переменных, мы можем установить Ряд данных. В Excel ряд данных содержит следующую информацию, необходимую для создания диаграммы:

  • Тип диаграммы
  • Группировка
  • Количество значений ряда данных
  • Метка серии данных
  • Метка значения оси X
  • Значения ряда данных

И конструктор вызывается просто передачей всех этих параметров:

 $ds=new \PHPExcel_Chart_DataSeries( \PHPExcel_Chart_DataSeries::TYPE_LINECHART, \PHPExcel_Chart_DataSeries::GROUPING_STANDARD, range(0, count($dsv)-1), $dsl, $xal, $dsv ); глубинный $ds=new \PHPExcel_Chart_DataSeries( \PHPExcel_Chart_DataSeries::TYPE_LINECHART, \PHPExcel_Chart_DataSeries::GROUPING_STANDARD, range(0, count($dsv)-1), $dsl, $xal, $dsv ); 

Далее мы создадим область сюжета и легенду:

 $pa=new \PHPExcel_Chart_PlotArea(NULL, array($ds)); $legend=new \PHPExcel_Chart_Legend(\PHPExcel_Chart_Legend::POSITION_RIGHT, NULL, false); 

Область графика содержит макет диаграммы и ряд данных. В макете можно указать, будут ли диаграммы отображать значения, проценты и т. Д. Мы можем использовать NULL, чтобы использовать макет по умолчанию.

Легенда используется для визуального представления групп данных.

И вот, наконец, мы можем создать график:

 $chart= new \PHPExcel_Chart( 'chart1', $title, $legend, $pa, true, 0, NULL, NULL ); $chart->setTopLeftPosition('K1'); $chart->setBottomRightPosition('M5'); $ews->addChart($chart); в $chart= new \PHPExcel_Chart( 'chart1', $title, $legend, $pa, true, 0, NULL, NULL ); $chart->setTopLeftPosition('K1'); $chart->setBottomRightPosition('M5'); $ews->addChart($chart); - $chart= new \PHPExcel_Chart( 'chart1', $title, $legend, $pa, true, 0, NULL, NULL ); $chart->setTopLeftPosition('K1'); $chart->setBottomRightPosition('M5'); $ews->addChart($chart); - $chart= new \PHPExcel_Chart( 'chart1', $title, $legend, $pa, true, 0, NULL, NULL ); $chart->setTopLeftPosition('K1'); $chart->setBottomRightPosition('M5'); $ews->addChart($chart); 

Единственный новый параметр в этом конструкторе — это name диаграммы. «Chart1» будет достаточно хорош. Название диаграммы может быть создано с помощью:

 $title=new \PHPExcel_Chart_Title('Any literal string'); 

После того, как диаграмма создана, мы устанавливаем ее положение и размер, устанавливая координаты ее левого верхнего и нижнего правого углов и вставляя ее в лист.

ПРИМЕЧАНИЕ. В большинстве случаев ссылка на ячейку не чувствительна к регистру, но, пожалуйста, используйте ЗАГЛАВНУЮ букву + число, если на листе есть диаграмма.

Сохранить файл

В качестве последнего шага мы сохраняем файл, чтобы пользователь мог его скачать:

 $writer = \PHPExcel_IOFactory::createWriter($ea, 'Excel2007'); $writer->setIncludeCharts(true); $writer->save('output.xlsx'); - $writer = \PHPExcel_IOFactory::createWriter($ea, 'Excel2007'); $writer->setIncludeCharts(true); $writer->save('output.xlsx'); 

Он использует фабричный шаблон для создания объекта записи для сохранения файла. Будет указан формат (в нашем случае мы используем формат «Excel2007»).

Убедитесь, что мы установили setIncludeCharts(true) в процессе сохранения, иначе диаграммы там не будет.

Помните, когда я говорил, что PHPExcel может использовать почти все типы графиков? Единственное исключение, которое эта библиотека не может сделать хорошо в Excel 2013, — то, что она не производит пригодную круговую диаграмму. В нашем output.xlsx и нашем коде мы фактически создали addChart1 диаграмму (сделано в addChart1 ), но при открытии output.xlsx Excel 2013 выдаст сообщение об ошибке. Если мы выберем продолжить, круговая диаграмма будет потеряна, и будет сохранена только линейная диаграмма (выполненная в addChart2 ). Отчет об ошибке уже внесен в репозиторий Git.

Теперь лист данных будет выглядеть так:

и увеличенный вид диаграммы. Он правильно расположен и имеет размеры:

Вывод

В этой статье мы продемонстрировали, как использовать чистый PHP и чистую PHP-библиотеку (PHPExcel) для управления Excel. Мы создали новый файл, заполнили данные, добавили новый лист и аналитические данные, вставили диаграмму и, наконец, сохранили файл для загрузки.

В общем, я нашел этот PHPExcel lib достойным внимания и легким в освоении. Его понимание кода в IDE может очень помочь нам при программировании.

Мы не рассмотрели другие общие функции в файле Excel — мы напишем дополнительную статью о них, если интерес будет достаточно высоким. Дайте нам знать!

Его официальная документация и примеры — хорошее место, где можно найти подробные объяснения использования API и рабочие фрагменты кода для общих задач. Прочитайте их полностью. Их можно найти в клонированном репо. Попробуйте эту библиотеку и дайте нам знать о ваших собственных случаях использования!