Реализация быстрого импорта из Excel на PHP

Мы продолжаем рассказывать о технологиях, используемых на нашем сервисе email-маркетинга Pechkin-mail.ru. Одной из ключевых задач любого сервиса, связанного с данными клиентов, является загрузка этих данных на сервис. Для Печкина очень важно быстро и без проблем для пользователя загружать адресные базы, содержащие email-адреса, имена, фамилии и другие дополнительные данные.436074132316c50f7fa3e000d50458ee.jpgЧто использовать в качестве инструмента? В качестве базового стандарта, используемого при импорте адресных баз, мы взяли Microsoft Excel. Объясняется это просто: это стандартный инструмент, которым на базовом уровне владеют 100% пользователей компьютеров. Более того, в бизнесе — это де-факто корпоративный стандарт и используется даже, если на рабочих компьютерах Mac или Linux. Практически все CRM-, CMS-, облачные или десктопные системы имеют экспорт в Excel или CSV, который простым пересохранением приводится к формату XLS или XLSX. Известно также, что »90% ошибок ПО сидит в полуметре от монитора». Не в обиду будет сказано рядовым пользователям, но мы должны учитывать самый базовый уровень подготовки и тех. поддержке для объяснения достаточно сказать «Загрузите Excel-файл», а не объяснять процедуру подготовки файла в нужном формате. Проблему пользователей при импорте адресных баз сняли. Но тут возникает уже проблема непосредственно разработки.

Наша боль, как разработчиков Excel — это не open-source разработка, а проприетарное решение. Формат данных, особенно в новых версиях после 2007 года (xlsx), нетривиален. На Печкине используется PHP, поэтому мы начали поиск библиотек, которые позволят нам решить данную задачу. Но тут столкнулись с проблемой, что целый ряд библиотек, не позволяют читать xlsx: php-spreadsheetreader reads a variety of formats (.xls, .ods AND .csv) PHP-ExcelReader (xls only) PHP_Excel_Reader (xls only) PHP_Excel_Reader2 (xls only) XLS File Reader Коммерческая и xls only SimpleXLSX Из описания способен читать xlsx, однако, автор ссылается только на xls PHP Excel Explorer Коммерческая и xls only Обратила на себя наше внимание библиотека PHPExcel. Ее мы использовали еще несколько лет назад в сервисе sms-рассылок SMS24×7.ru. Петя Соколов (Petr_Sokolov), наш талантливый разработчик, написал обертку для этой библиотеки, исправляющую ряд ее недостатков и багов.

Библиотека, безусловно, интересная и развитая. Но для Печкина ее использовать стало невозможно уже через пару лет, когда выросли и мы и наши клиенты — ее катастрофическая требовательность к ресурсам и огромное время парсинга файлов. Например, нередки случаи загрузки на сервис адресных баз > 100 000 строк со сложной структурой. А если файл уже 500 000 строк и «весит» больше 30Мб?

И тут нас отпустило… В процессе поисков мы наткнулись на коммерческую библиотеку libxl, увидев результаты «кустарного benchmark» на Stackoverflow.Библиотека написана на C++, а благодаря великолепному объектно-ориентированному расширению для PHP от Ilia Alshanetsky, легка в освоении и интеграции (например, переписать наше текущее решение на PHPExcel на LibXL заняло около 3 часов). Что очень классно, учитывая, что, к сожалению, документации от разработчика расширения нет и необходимо пользоваться расширением Reflection.

Процесс установки очень прост.

cd /usr/local/src/

wget http://libxl.com/download/libxl.tar.gz tar zxfv libxl.tar.gz

cd libxl-3.5.4.1/ ln -s include_c include cd …/

wget https://github.com/iliaal/php_excel/archive/master.zip unzip master.zip

cd php_excel-master/ ./configure --with-excel --with-libxl-libdir=…/libxl-3.5.4.1/lib64 --with-libxl-incdir=…/libxl-3.5.4.1/include_c make make test make install В результате компиляции вы получите файл excel.so в папке /usr/lib/php5/20090626/. Теперь достаточно создать файл /etc/php5/conf.d/excel.ini с содержимым.

extension=excel.so Проверим установился ли модуль и перезагрузим веб-сервер.

php -m | grep excel service lighttpd restart В коде все тоже очень просто. Подгружаете файл и читаете необходимые ячейки. Например, вот так:

$doc = new ExcelBook (); $doc→loadFile («example.xls»); for ($r=$sheet→firstRow ();$r<=$sheet->lastRow ();$r++){ for ($c=$sheet→ firstCol ();$c<=$sheet-> lastCol ();$c++){ echo «Строка:».$r.» Столбец:».$c.» Значение:».$sheet→read ($r,$c).»
»; } } Полученные результаты производительности Отсутствие потребности в оперативной памяти (в процессе загрузки файла и его чтения) приятно порадовало.06cbbe1e4598038cb5b16350059aa079.pngА вот и прирост скорости загрузки excel-файла и его чтения на различных размерах адресных баз.c549159dbbee487c12bef0eb5eaa0ae0.png

Данные тесты проводились на xlsx-файлах с N подписчиками в один стоблец с email. Реальные же адресные базы еще больше и сложнее и преимущество в скорости и потреблении памяти выглядит еще значительнее.

Стоимость библиотеки 199$ за девелоперскую лицензию, но, поверьте, это того стоит. Безусловно рекомендуем всем, кто сталкивается с проблемой импорта Excel-файлов на свой сервис.

© Habrahabr.ru