Чтение файлов xls и xlsx в PHP4

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

Я не в первый раз сталкиваюсь с такой задачей, однако в этот раз присутствовал ряд интересных ограничений — PHP версии 4.

Пооблизывавшись немного на PHPExcel, сего требованием PHP 5.2.0 (а судя по комментам 5.2.5) я стал искать решения по-проще.

Первый скрипт PHP-ExcelReader умел читать только xls — бинарную версию формата, что вполне устраивало, но он все время выдавал ошибку «file is not readable». После недолгого дебага выяснилось, что она возникает по результатом сверки сигнатуры — первых 8 байт файла. Ручная сверка показала, что с файлом все хорошо. Проблема обнаружилась в модуле mbstring — строка извлекаемая из файла функцией substr была несколько длинее, чем просили. Помогла установка

mb_internal_encoding('cp1251');

Перед вызовом конструктора. Так как сайт на кодировке UTF-8, данные, извлеченные классом приходилось также обрабатывать функцией iconv(). Класс работал в PHP4 и PHP5, так что дополнительных «допилов» не потребовалось.

Для чтения xlsx пришлось немного покопаться — был найден наиболее простой парсер SimpleXLSX, написанный Sergey Shuchkin. 

Его пришлось доработать, так как он использовал расширение SimpleXML, которого нет в php4, ну объектная модель использовалась тоже от php5. Переписал все обращения к XML-дереву используя DOMXml и немного поправил извлечение гиперссылок из документа. Что получилось, можно скачать: xlsx-reader.

Кстати, для работы этого скрипта также пришлось установить mb_internal_encoding(), хотя данные преобразовывать к utf8-виду не потребовалось.

  • Dmnkdm

    Здравствуйте!

    подскажите, куда писать

    mb_internal_encoding ('cp1251');

    пытаюсь засунуть в Jooml'у php-excel reader, упорно выдает not readable :(

    • Если мне не изменяет память, я вставлял перед вызовом 

      $data->read ('jxlrwtest.xls'); в моем коде. 

      Но вообще проблема кроется в строке 61 вот этого файла: http://phpexcelreader.svn.sourceforge.net/viewvc/phpexcelreader/trunk/base/Excel/oleread.inc?revision=14&view=markup, там где сравнивается маркер файла mb_substr извлекает неверное количество символов — этот баг видимо сильно зависит от конфигурации сервера — для проверки можете вывести результат этого substr-а в хексах и посмотреть какой он длинны — если 8 символов, то у вас проблема в чем-то другом.

      • Dmnkdm

        Спасибо, проблема и правда в чем-то другом 

    • Goqflash

       Naverno u tebya xls (Excel) file ne < 2005 goda...

    • Goqflash

       Eshe na oleread.php zameni stroku

      substr ($this->data, 0, 8) != IDENTIFIER_OLE

      na

      mb_substr ($this->data, 0, 8, 'windows-1251') != IDENTIFIER_OLE

  • У меня ошибку выдаёт

    Fatal error: Call to undefined function domxml_open_mem () in Z:homeimagecmsshopapplicationlibrariesReadXls.php on line 397Что делать?

    • Аноним

      Определенно, нужно установить расширение DOMXML на основе которого работает библиотека при чтении xlsx. Подробнее смотри http://www.php.net/manual/ru/domxml.installation.php