在PhpSpreadsheet中读取Xlsx文件

时间:2018-12-17 21:28:19

标签: php excel xlsx ziparchive phpspreadsheet

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

$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

在Ubuntu 18.04上的Apache中,我的PHP v7.2脚本可读取并打开该文件。我阅读了一些论坛帖子,其中提出了以下建议:

我尝试在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 ,意思是“ No such file”。但是,该文件存在。 那么,为什么会发生此错误

更新-2018-12-18

This web page建议存在多种类型的xlsx文件。因此,我运行了file test.xlsx,它显示了Microsoft Excel 2007+。然后,我在LibreOffice Calc中打开了电子表格,并将其保存为OOXML类型的xlsx文件,然后重新运行file test.xlsx,显示为Microsoft OOXML。然后我重新运行了PHP脚本,但是遇到了同样的错误。因此,看来我的xlsx文件类型不是问题。

因此,我决定使用PHPExcel(即使已弃用)完成一些必要的工作。当我使用PHPExcel运行脚本时,收到类似的错误消息,关于canRead()无法检测到xlsx文件。

因此,我继续阅读this web page,并遵循wesood的最新建议,该建议来自对this web page的公认答案。此解决方案对我有用:在文件/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:

根据评论的建议,我使用了通过Google搜索结果(例如Excel 2007+Microsoft OOXML类型且具有相同错误的随机XLSX文件(例如this file)对脚本进行了测试显示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,数组,数组)#3   {main}在第176行的/var/www/html/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/IOFactory.php中抛出

4 个答案:

答案 0 :(得分:2)

将.xlsx文件添加到Mac上的git存储库后,我遇到了同样的问题。
问题是git自动转换了行尾。

解决方案是将这些行添加到.gitattributes文件中:

*.xls   binary
*.xlsx  binary

答案 1 :(得分:0)

据我了解,您缺少了一块。为什么不先创建阅读器,然后加载文件。

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

$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>';
}

这是从我的一个项目中经过测试和选择的所有工作代码。干杯。

答案 2 :(得分:0)

尝试加载XLSX文件时遇到了同样的错误。就我个人而言,我发现了一个非常简单的修复程序,可以修复我的问题。我是从文件名xlsx中手动获取扩展名。我注意到使用旧的PHP Spreadsheet库的其他代码正在扩展Xls中。因此,我尝试在Xlsx中加载,效果很好。

这是我用来正确加载扩展中的代码。它只是在最后一个句点之后抓取所有字符,然后捕获该子字符串的第一个字符。

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

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

有一次,我添加了ucfirst命令,它为我解决了这个问题。

答案 3 :(得分:0)

使用它。它将显示 .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');