Импорт и экспорт данных с помощью PHPExcel

Несколько недель назад мне пришлось работать с файлами Excel в формате BIFF8 (Excel 97), т.к. заказчик не согласен был на экспорт данных в CSV. Spreadsheet_Excel_Writer вместе с Spreadsheet_Excel_Reader очень хорошо помогали мне раньше, но только с BIFF5. Поддержка таблиц BIFF8 долгое время была большой проблемой. поэтому я стал искать альтернативы.

После недолгих поисков, я наткнулся на PHPExcel, который поддерживает множество форматов чтения и записи с помощью одного API. Он распространяется по GNU Lesser General Public License? что дает вам право использовать его свободно в коммерческих продуктах. Форматы чтения и записи не ограничиваются файлами Excel. В этой статье я дам краткий обзор о того, что вы можете делать с помощью этой библиотеки.

Форматы чтения

  • Excel 2007 (SpreadsheetML)
  • BIFF5 (Excel 5.0/Excel 95)
  • BIFF8 (Excel 97 и более поздние)
  • PHPExcel Serialized Spreadsheet
  • Symbolic Link
  • CSV

Форматы записи

  • Excel 2007 (SpreadsheetML)
  • BIFF8 (Excel 97 и более поздние)
  • PHPExcel Serialized Spreadsheet
  • PDF
  • HTML
  • CSV

Установка PHPExcel

Убедитесь что на вашем сервере стоит PHP 5.2.0 или старше и установлены следующие расширения: php_zip, php_xml и php_gd2. Вs можете скачать архив с PHPExcel с сайта проекта. Можно так же установить PEAR-пакет.

Создание таблицы

После распаковки скачанного архива, вы найдете папку Tests, в которой содержатся несколько демонстрационных файлов. Когда вы захотите использовать эту библиотеку, взгляните на эти примеры, чтобы познакомиться методами работы с PHPExcel.

Теперь вы готовы к созданию вашего первого файла Excel. После создания экземпляра класса, устанавливаются некоторые метаданные:

  1. require_once 'PHPExcel.php';
  2. $objPHPExcel = new PHPExcel();
  3. // устанавливаем метаданные
  4. $objPHPExcel->getProperties()->setCreator("PHP")
  5. ->setLastModifiedBy("Алексей")
  6. ->setTitle("Office 2007 XLSX Тестируем")
  7. ->setSubject("Office 2007 XLSX Тестируем")
  8. ->setDescription("Тестовый файл Office 2007 XLSX, сгенерированный PHPExcel.")
  9. ->setKeywords("office 2007 openxml php")
  10. ->setCategory("Тестовый файл");
  11. $objPHPExcel->getActiveSheet()->setTitle('Демо');

Как вы можете видеть, практически везде в классе используется паттерн Fluent Interface (цепочка вызовов).

Имена методов говорят сами за себя. В результате выполнения этого кода создастся объект PHPExcel c метаданными, но без наполнения, кроме листа под названием "Демо". При создании объекта, первый лист создастся автоматически. Конечно, вы можете добавить еще листы, если это необходимо. Сейчас в качестве активного листа выбран первый. Этот лист Excel или Open Office покажут первым при открытии файла. Добавим "Привет, мир!" в таблицу:

  1. $objPHPExcel->setActiveSheetIndex(0)
  2. ->setCellValue('A1', 'Привет')
  3. ->setCellValue('B1', 'Мир!');

Обращаться к ячейкам можно через координаты Excel, например, "С3". Это не очень удобно, когда надо перебрать содержимое большого количества ячеек. К счастью есть другой метод для того чтобы обратиться к ячейке - с помощью координат X и Y:

  1. setCellValueByColumnAndRow($column, $row, $value)

Заметьте, что нумерация строк начинается с 1, то есть координаты ячейки "A1" будут (0,1). Последний шаг - сохраняем файл Excel на диск. Для этого надо создать объект для записи, используя PHPExcel_IOFactory. Второй параметр определяет формат файла.

  1. require_once 'PHPExcel/IOFactory.php';
  2. $objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
  3. // Если вы хотите, то можете сохранить в другом формате, например, PDF:
  4. //$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'PDF');
  5. $objWriter->save('MyExcel.xslx);

Есть методы для изменения стиля, формата, слияния и проверки ячеек. Для более подробной информации - смотрите документацию.

Чтение таблицы

PHPExcel так же способен читать данные из Excel файлов. В реальной программе это может быть использовано, например, для импорта списка продукции. Это может быть полезно, если вы хотите предложить клиенту загрузку непосредственно Excel файла, а не экспорт через CSV. Так как PHPExcel может открыть оба этих формата, вы можете предложить оба способа импорта, без особых усилий.

Чтение из файла так же просто как и запись в него. Вновь используется класс IOFactory для доступа к файлу:

  1. require_once 'PHPExcel/IOFactory.php';
  2. $objPHPExcel = PHPExcel_IOFactory::load("MyExcel.xlsx");

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

  1. require_once 'PHPExcel/IOFactory.php';
  2. $objPHPExcel = PHPExcel_IOFactory::load("MyExcel.xlsx");
  3. foreach ($objPHPExcel->getWorksheetIterator() as $worksheet)
  4. {
  5. $worksheetTitle = $worksheet->getTitle();
  6. $highestRow = $worksheet->getHighestRow(); // например, 10
  7. $highestColumn = $worksheet->getHighestColumn(); // например, 'F'
  8. $highestColumnIndex = PHPExcel_Cell::columnIndexFromString($highestColumn);
  9. $nrColumns = ord($highestColumn) - 64;
  10. echo "<br>В таблице ".$worksheetTitle." ";
  11. echo $nrColumns . ' колонок (A-' . $highestColumn . ') ';
  12. echo ' и ' . $highestRow . ' строк.';
  13. echo '<br>Данные: <table border="1"><tr>';
  14. for ($row = 1; $row <= $highestRow; ++ $row)
  15. {
  16. echo '<tr>';
  17. for ($col = 0; $col < $highestColumnIndex; ++ $col)
  18. {
  19. $cell = $worksheet->getCellByColumnAndRow($col, $row);
  20. $val = $cell->getValue();
  21. $dataType = PHPExcel_Cell_DataType::dataTypeForValue($val);
  22. echo '<td>' . $val . '<br>(Тип ' . $dataType . ')</td>';
  23. }
  24. echo '</tr>';
  25. }
  26. echo '</table>';
  27. }

Используя всего три строки кода можно легко конвертировать файлы из одного формата в другой:

  1. $objPHPExcel = PHPExcel_IOFactory::load("XMLTest.xml");
  2. $objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
  3. $objWriter->save('covertedXml2Xlsx.xlsx');

Другое интересное решение - использовать бизнес-логику из Excel файла. Вместо повторного создания кода, вы можете выполнить код сохраненный в Excel.

Так же возможно (а еще и быстрее, чем создание с нуля) загрузить файл Excel, а затем добавить в него данные. Базовый файл можно хранить как шаблон и использовать, заполняя нужными данными. А когда меняется макет - просто менять шаблон.

Небольшое замечание

PHPExcel очень требователен к памяти. Для одной ячейки надо около 1КБ памяти. При работе с большими таблицами, вы можете столкнуться с определенными трудностями. Тем не менее, разработчики позаботились об этом предоставив механизм кэширования: CachedObjectStorageFactory. Что говорит об этом руководство:

Механизм кэширования ячеек позволяет PHPExcel манипулировать объектами потреблять меньше памяти в PHP, используя жесткий диск, APC, memcache или Wincache. Это позволяет работать с большими таблицами используя небольшие объемы памяти, хоть и платя за это скоростью обращения к ячейкам.

В будущем

PHPExcel не умеет создавать диаграммы - пока что. Это пока в планах, но работа над ними уже ведется. Возможно в следующем релизе можно будет создавать диаграммы.

Заключение

PHPExcel имеет большой набор методов, по настоящему нужных программисту. Документация хорошо структурирована и большое число демонстрационных файлов позволяет легко найти как нужно использовать класс. Кроме этого файлы документированы с помощью PHPDocBlocks, так что при использовании IDE, таких как ZendStudio или NetBeans, вы будуте получать подсказки по использованию методов классов.

В заключение: на PHPExcel определенно стоит обратить внимание, т.к. он может работать со многими форматами.

11 Responses to Импорт и экспорт данных с помощью PHPExcel

  1. gravatar

    Ломал голову, как прочитать данные из Excel файла, в официальной доке не разобрался, здесь всё понял!
    Спасибо за статью!

  2. gravatar

    Как можно содержимое файла записать в MySQL, при этом не создавая файла?

  3. gravatar

    Скажите, что делать, если нужно импортировать более 1000 записей? Сервер выдаёт ошибку при попытке прочитать файл через
    $objPHPExcel = PHPExcel_IOFactory::load("MyExcel.xlsx");

  4. gravatar

    CachedObjectStorageFactory - в этой статье написано, что эта чтука поможет справиться с проблемой большого кол-ва записей, лично я до сего момента просто дробил вручную экселевский файл на мелкие, т.к. с большим фалом мне надо было работать только один раз в самом начале (забить исходную базу), дальше идет периодическая догрузка всякой мелкоты.

    P.S. разберусь до конца и может сюда кину;)

  5. gravatar

    есть несколько способов если файл слишком большой
    1. Кэшировать

    (я делаю так, в принципи в документации это есть)
    $cacheMethod = PHPExcel_CachedObjectStorageFactory:: cache_to_phpTemp;
    $cacheSettings = array( ' memoryCacheSize ' => '1024MB');
    PHPExcel_Settings::setCacheStorageMethod($cacheMethod, $cacheSettings);
    if (!PHPExcel_Settings::setCacheStorageMethod($cacheMethod,$cacheSettings))
    die('CACHEING ERROR');

    2. в php.ini сделать как у меня ниже

    memory_limit = 256M ; Maximum amount of memory a script may consume (128MB)

    3. их комбинирование

    а вообще на сайте http://phpexcel.codeplex.com все это интенсивно обсуждается и пока действительно хорошего решения ни кто не нашел

  6. gravatar

    Здравствуйте!
    А как объединить ячейки? В HTML таблицах это делаем с помощью colspan="" и rowspan="".

  7. gravatar

    Подскажите проблема в следующем - есть значения ячеек вида 037 (первый ноль, дальше цифры) как заставить ПХПэкзель возвращать строку "037" а не число 37?

  8. gravatar

    Объединение ячеек
    $objPHPExcel->getActiveSheet()->mergeCells('B6:F3');

    >Подскажите проблема в следующем - есть значения ячеек вида 037 (первый ноль, дальше цифры) как заставить ПХПэкзель возвращать строку "037" а не число 37?

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

  9. gravatar

    Здравствуйте. Я использовал Ваш пример по выводу данных из ексел документа. У меня проблема с тем что выводятся не русские символы, а какието иероглифы, хотя английский нормально показывает, что делать?

  10. gravatar

    @Юрий, покажите код

  11. gravatar

    Как xls файле числовой тип ячейки превратить текстовой? Ато выдает такую ерунду 1.89970281295E+12 (научный формат).

Leave a Reply