在 PhpSpreadsheet 中读取 Xlsx 文件

Ary*_*rya 10 php excel xlsx ziparchive phpspreadsheet

我想读取xlsx在 Microsoft Excel 中创建的文件,但是当我运行以下代码时...

$Source_File = "test.xlsx";
$Spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($Source_File);
Run Code Online (Sandbox Code Playgroud)

...我收到以下错误:

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
Run Code Online (Sandbox Code Playgroud)

如果我改为使用,我会得到同样的错误 $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
Run Code Online (Sandbox Code Playgroud)

该文件可由我的 PHP v7.2 脚本在 Ubuntu 18.04 上的 Apache 中读取和打开。我阅读了几篇论坛帖子,其中提出了以下建议,我已经完成了:

我尝试在 LibreOffice 中打开文件并将其另存为xlsx那里,但发生了同样的错误(如果我另存为,则没有错误xls)。

我可以创建一个 reader $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;
}
Run Code Online (Sandbox Code Playgroud)

...我搜索了 的定义canRead,但在/vendor/phpoffice/phpspreadsheet/. 在哪里canRead定义? 我想如果我能读懂 的定义canRead,那么也许我会明白问题的根本原因是什么。

更新:

我从第 65 行开始canRead()定义的评论和讨论中了解到\PhpSpreadsheet\Reader\Xlsx.php。在 中canRead()$zip->open($pFilename)返回错误代码 ,ZipArchive::ER_NOENT表示“没有这样的文件”。但是,该文件存在。 那么,为什么会发生此错误

更新 - 2018-12-18

此网页表明有多种类型的 xlsx 文件。所以,我跑了file test.xlsx,它显示Microsoft Excel 2007+. 然后我在 LibreOffice Calc 中打开电子表格并将其保存为 OOXML 类型的 xlsx 文件并重新运行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脚本通过谷歌搜索结果(例如,找到的文件这个文件),它要么Excel 2007+Microsoft OOXML类型和错误显示为PhpSpreadsheet相同:

致命错误:未捕获的 PhpOffice\PhpSpreadsheet\Reader\Exception:无法在 /var/www/html/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/IOFactory.php:176 中识别此文件的阅读器:#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} 扔在 /var/www/html/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/IOFactory.php 上第 176 行

sha*_*ver 9

根据我的理解,你少了一块。为什么不先创建一个阅读器,然后加载文件。

试试下面的代码。它可以识别扩展并相应地创建该类型的阅读器。

$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();
Run Code Online (Sandbox Code Playgroud)

现在您可以简单地在结果数组上运行 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>';
}
Run Code Online (Sandbox Code Playgroud)

这是经过测试和工作的代码。