Прочитать файл Xlsx в PhpSpreadsheet

Я хочу прочитать файл xlsx, созданный в Microsoft Excel, но когда я запускаю следующий код ...

$Source_File = "test.xlsx";
$Spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($Source_File);

... Я получаю следующую ошибку:

Fatal error: Uncaught PhpOffice\PhpSpreadsheet\Reader\Exception: Unable to identify a reader for this file in /var/www/html/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/IOFactory.php:163
Stack trace:
  #0 /var/www/html/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/IOFactory.php(93): PhpOffice\PhpSpreadsheet\IOFactory::createReaderForFile('file:///home/ar...')
  #1 /var/www/html/Function_Spreadsheet.php(480): PhpOffice\PhpSpreadsheet\IOFactory::load('file:///home/ar...')
  #2 /var/www/html/Function_Home.php(3747): Spreadsheet_Reader_1('/var/www/html/F...', 3745, Array, Array)
  #3 {main} thrown in /var/www/html/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/IOFactory.php on line 163

Я получаю ту же ошибку, если вместо этого использую $Spreadsheet = IOFactory::load($Source_File);

Я получаю следующую ошибку, если вместо этого использую $Spreadsheet = $reader->load($Source_File);

Warning: ZipArchive::getFromName(): Invalid or uninitialized Zip object in /var/www/html/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx.php on line 311

Warning: ZipArchive::getFromName(): Invalid or uninitialized Zip object in /var/www/html/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx.php on line 313

Notice: Trying to get property 'Relationship' of non-object in /var/www/html/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx.php on line 350

Warning: Invalid argument supplied for foreach() in /var/www/html/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx.php on line 350

Warning: ZipArchive::getFromName(): Invalid or uninitialized Zip object in /var/www/html/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx.php on line 311

Warning: ZipArchive::getFromName(): Invalid or uninitialized Zip object in /var/www/html/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx.php on line 313

Notice: Trying to get property 'Relationship' of non-object in /var/www/html/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx.php on line 397

Warning: Invalid argument supplied for foreach() in /var/www/html/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx.php on line 397

Warning: ZipArchive::getFromName(): Invalid or uninitialized Zip object in /var/www/html/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx.php on line 311

Warning: ZipArchive::getFromName(): Invalid or uninitialized Zip object in /var/www/html/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx.php on line 313

Notice: Trying to get property 'Override' of non-object in /var/www/html/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx.php on line 1855

Warning: Invalid argument supplied for foreach() in /var/www/html/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx.php on line 1855

Warning: ZipArchive::close(): Invalid or uninitialized Zip object in /var/www/html/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx.php on line 1883

Файл доступен для чтения и открытия моим сценарием PHP v7.2 в Apache на Ubuntu 18.04. Я прочитал несколько сообщений на форуме, в которых предлагалось следующее, что я и сделал:

Я попытался открыть файл в LibreOffice и сохранить его там как xlsx, но возникла та же ошибка (нет ошибки, если я сохраню как xls).

Я могу создать ридер $reader = new \PhpOffice\PhpSpreadsheet\Reader\Xlsx();, но когда я делаю $Spreadsheet = $reader->load($Source_File); или $Spreadsheet = IOFactory::load($Source_File);, я получаю ту же ошибку.

Кроме того, я могу создать программу для чтения xls, которая может читать файлы xls. Я также могу создать читалку xlsx, но она не будет читать файл xlsx, выдает ту же ошибку при попытке прочитать файл xlsx. Итак, почему возникает ошибка с файлом xlsx?

Кроме того, я прочитал исходный код, на который указывает сообщение об ошибке (IOFactory.php), и нашел следующее место (рядом со строкой № 139), где возникает ошибка ...

//Let's see if we are lucky
if (isset($reader) && $reader->canRead($filename))
{
    return $reader;
}

... и я искал определение canRead, но нигде не нашел его в /vendor/phpoffice/phpspreadsheet/. Где определяется canRead? Думаю, если бы я мог прочитать определение canRead, то, может быть, я пойму, в чем основная причина проблемы.

ОБНОВИТЬ:

Из комментариев и обсуждений я узнал, что canRead() определен в \PhpSpreadsheet\Reader\Xlsx.php, начиная со строки 65. В canRead()$zip->open($pFilename) возвращает код ошибки ZipArchive::ER_NOENT, что означает «Файл не найден». Однако файл существует. Итак, почему возникает эта ошибка?

ОБНОВЛЕНИЕ - 2018-12-18

Эта веб-страница предполагает, что существует несколько типов файлов xlsx. Итак, я запустил file test.xlsx, который отобразил Microsoft Excel 2007+. Затем я открыл электронную таблицу в LibreOffice Calc и сохранил ее как файл xlsx типа OOXML и повторно запустил file test.xlsx, который отобразил Microsoft OOXML. Затем я повторно запустил PHP-скрипт, но получил ту же ошибку. Итак, похоже, проблема не в моем типе файла xlsx.

Итак, я решил использовать PHPExcel (хотя он устарел), чтобы выполнить некоторую необходимую работу. Когда я запустил скрипт с помощью PHPExcel, я получил аналогичную ошибку о том, что canRead() не может обнаружить файл xlsx.

Итак, я продолжил читать эта веб-страница и последовал последнему предложению wesood, которое было получено из принятого ответа на эта веб-страница. Это решение сработало для меня: в файле /PHPExcel/IOFactory.php я добавил PHPExcel_Settings::setZipClass(\PHPExcel_Settings::PCLZIP); непосредственно перед if (isset($reader) && $reader->canRead($filename)).

Однако я все еще хочу знать, как решить эту проблему в PhpSpreadsheet. Кажется, мне нужно больше узнать о том, как работает pclzip, и нужно ли выполнить аналогичное действие с PhpSpreadsheet.

ОБНОВЛЕНИЕ 2019-02-10:

Я попробовал запустить сценарий сегодня, и кажется, что добавление PHPExcel_Settings::setZipClass(\PHPExcel_Settings::PCLZIP); больше не работает. Итак, я снова застрял ...

Что я делаю неправильно? Любая помощь приветствуется!

ОБНОВЛЕНИЕ 2019-02-18:

Следуя рекомендациям из комментариев, я протестировал скрипт с использованием случайных файлов XLSX, найденных в результатах поиска Google (например, этот файл), которые были либо типами Excel 2007+, либо Microsoft OOXML, и такая же ошибка отображается для PhpSpreadsheet:

Fatal error: Uncaught PhpOffice\PhpSpreadsheet\Reader\Exception: Unable to identify a reader for this file in /var/www/html/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/IOFactory.php:176 Stack trace: #0 /var/www/html/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/IOFactory.php(113): PhpOffice\PhpSpreadsheet\IOFactory::createReaderForFile('file:///var/www...') #1 /var/www/html/Function_Spreadsheet.php(798): PhpOffice\PhpSpreadsheet\IOFactory::identify('file:///var/www...') #2 /var/www/html/Function_Home.php(3748): Spreadsheet_Reader_1('/var/www/html/F...', 3746, Array, Array) #3 {main} thrown in /var/www/html/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/IOFactory.php on line 176

Код, который вы ищете: github.com/PHPOffice/PhpSpreadsheet/blob/develop/src/…

Martin 17.12.2018 22:49

Я могу только предположить, исходя из того, что вы сказали, и глядя на код GitHub, что файл, который вы пытаетесь загрузить, не имеет формат xlsx, который, по мнению phpsreadsheet, должен быть

Martin 17.12.2018 22:52

Можете ли вы открыть свой тестовый файл Test.xlsx с помощью 7-zip, чтобы убедиться, что это архив ZIP? Вы ищете файл с именем workbook.xml внутри архива.

Martin 17.12.2018 22:53

@MartinParkin - какой еще формат xlsx есть? Кроме того, да, я могу открыть файл xlsx как zip. Если я изменю расширение на .zip, то смогу извлечь его и увидеть xml-код.

Arya 17.12.2018 22:54

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

Martin 17.12.2018 23:03

Тогда мне нужно уточнить свой пост: я могу создать читалку xlsx сам, но он не может читать файл xlsx, он дает ту же ошибку. Кроме того, я сам могу создать программу для чтения xls, и я могу читать файл xls без ошибок.

Arya 17.12.2018 23:07

Он не может выдать ту же ошибку - он не использует тот же код. Функция load находится в строке 389 того же файла, на который я ссылался ранее. Не могли бы вы еще раз проверить, какую ошибку выдает функция load?

Martin 17.12.2018 23:09

Да, я только что обновил свое сообщение, чтобы показать другое сообщение об ошибке, которое я получаю. Если я использую IOFactory::load($Source_File); или \PhpOffice\PhpSpreadsheet\IOFactory::load($Source_File);, я получаю ту же ошибку, но если я использую $reader->load($Source_File);, я получаю другое сообщение об ошибке.

Arya 17.12.2018 23:18

Позвольте нам продолжить обсуждение в чате.

Martin 17.12.2018 23:30

Пожалуйста, добавляйте главный тег к вопросу всякий раз, когда вы его задаете. Обычно люди смотрят основные теги. Я добавил тег php. Если бы вы добавили его раньше, я бы увидел его раньше. Одна из причин, по которой ваш вопрос не был виден должным образом, - это отсутствие тега php.

shazyriver 18.02.2019 09:10

@shazyriver: Хорошо. Я тоже просто добавил xlsx в качестве тега.

Arya 18.02.2019 23:13

Я получаю ту же ошибку при чтении файла xlsx. Пришел сюда в надежде найти ответ, надеюсь, скоро ....

dmikester1 29.03.2019 18:36

@ dmikester1 Как настроен ваш компьютер? Возможно, это поможет нам сузить причину проблемы, такую ​​как ОС, версия PHP, одна из zip-библиотек и т. д.

Arya 29.03.2019 22:48

Хорошо, ответ на мой был очень прост. Возможно, для вас это будет не так просто. Но я вручную брал расширение из файла как xlxs. Я узнал, что если я переключил его на Xlxs, он работал нормально.

dmikester1 30.03.2019 03:30

@ dmikester1 Не могли бы вы объяснить больше о «захвате расширения из файла»? Например, вы изменили расширение файла с xlsx на Xlsx, прежде чем читать из него, или вы использовали $reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader("Xlsx"); (который не работал у меня) или что-то еще? Возможно, вы сможете уточнить свое решение в качестве ответа.

Arya 30.03.2019 07:59
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
10
15
25 823
5

Ответы 5

Насколько я понимаю, вам не хватает части. Почему бы вам сначала не создать читалку, а потом загрузить файл.

Попробуйте следующий код. Он может идентифицировать расширение и соответственно создавать читателя этого типа.

$inputFileName = "Text.xlsx";

/**  Identify the type of $inputFileName  **/
$inputFileType = \PhpOffice\PhpSpreadsheet\IOFactory::identify($inputFileName);

/**  Create a new Reader of the type that has been identified  **/
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader($inputFileType);

/**  Load $inputFileName to a Spreadsheet Object  **/
$spreadsheet = $reader->load($inputFileName);

/**  Convert Spreadsheet Object to an Array for ease of use  **/
$schdeules = $spreadsheet->getActiveSheet()->toArray();

Теперь вы можете просто запустить цикл foreach для массива результатов.

foreach( $schdeules as $single_schedule )
{               
    echo '<div class = "row">';
    foreach( $single_schedule as $single_item )
    {
        echo '<p class = "item">' . $single_item . '</p>';
    }
    echo '</div>';
}

Это проверенный и рабочий код.

Я получаю следующую ошибку с $inputFileType = \PhpOffice\PhpSpreadsheet\IOFactory::identify($inputFileName‌​);: Fatal error: Uncaught PhpOffice\PhpSpreadsheet\Reader\Exception: Unable to identify a reader for this file Есть ли у вас какие-либо мысли о том, почему возникает эта ошибка? Я использую входной файл XLSX типа Microsoft Excel 2007+.

Arya 18.02.2019 09:01

Тогда, вероятно, в вашем файле есть ошибка. Почему бы вам не попробовать с образцом файла? Вот ссылка на github стандартных образцов github.com/PHPOffice/PhpSpreadsheet/tree/master/samples/Read‌ er /…

shazyriver 18.02.2019 09:05

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

shazyriver 18.02.2019 09:06

Ни один из примеров по ссылке на github, которую вы предоставили, не является файлом XLSX, я вижу только файлы CSV, TSV и XLS. Есть ли файл XLSX, который я не замечаю?

Arya 18.02.2019 20:15

Я загрузил пару других файлов XLSX [file-examples.com/wp-content/uploads/2017/02/…, которые были либо Excel 2007+, либо Microsoft OOXML, и одна и та же ошибка по-прежнему отображается для всех из них. Итак, похоже, проблема не в файле XLSX. Возможно, это конфигурация моей системы, но что это может быть?

Arya 18.02.2019 20:24

Я столкнулся с той же самой ошибкой при попытке загрузить файл XLSX. Лично я обнаружил очень простое решение, которое устранило мою проблему. Я вручную взял расширение имени файла как xlsx. Я заметил, что какой-то другой мой код, использующий старую библиотеку PHP Spreadsheet, принимает расширение Xls. Я попробовал загрузить Xlsx, и он отлично сработал.

Вот код, который я использую для правильной загрузки расширения. Он просто захватывает все символы после последней точки, а затем записывает первый символ этой подстроки. ucfirst просто вводит в верхний регистр первую букву переданной в него строки. substr возвращает подстроку, где первый параметр - это строка, из которой нужно извлечь, а второй параметр - с какого индекса начинать подстроку в данной строке. И, наконец, strrpos находит последнее вхождение подстроки в заданной строке.

https://www.php.net/manual/en/function.ucfirst.php

https://www.php.net/manual/en/function.strrpos

https://www.php.net/manual/en/function.substr.php

$inputFileType = ucfirst(substr($cccFile, strrpos($cccFile, '.') + 1));

/**  Create a new Reader of the type defined in $inputFileType  **/
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader($inputFileType);

Однажды я добавил команду ucfirst, и она решила проблему для меня.

Пожалуйста, объясните, что делает первая строка.

Jimmy Adaro 11.02.2020 21:12

Я объяснил это довольно ясно во втором абзаце.

dmikester1 11.02.2020 21:15

Я понимаю код, но тот, кто не понимает, что означает strrpos, substr + 1 и / или ucfirst в коде, может запутаться.

Jimmy Adaro 11.02.2020 21:50

Честно говоря, я постараюсь добавить поясняющий текст.

dmikester1 11.02.2020 21:53

У меня была такая же проблема после добавления файлов .xlsx в репозиторий git на моем Mac. Проблема заключалась в том, что git автоматически конвертировал окончания строк.

Решением было добавить эти строки в файл .gitattributes:

*.xls   binary
*.xlsx  binary

Использовать это. Он покажет .xlsx

   $inputFileName = public_path('asset/docs/Filename.xlsx');
    
   /** Load $inputFileName to a Spreadsheet Object  **/
   $spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($inputFileName);
   $writer = IOFactory::createWriter($spreadsheet, 'Html');
   $message = $writer->save('php://output');

У меня возникла аналогичная проблема на моей странице Drupal, где я использовал "private: // ..." в качестве пути к файлу. getFromZipArchive в PHPExcel (должно быть аналогично в PhpSpreadsheet) не может читать схему пути к файлу, такую ​​как "private: // ...". После перевода на локальный путь он работает.

В вашем случае у вас есть схема пути, такая как «file: /// home / ar ...». Так что используйте вместо этого "/ home / ar ...".

Другие вопросы по теме