PHPExcel需要很长时间才能读取Excel文件

时间:2013-05-24 19:53:24

标签: php phpexcel

我正在使用PHPExcel 1.7.8,PHP 5.4.14,Windows 7和Excel 2007电子表格。电子表格由750行(A列到B列)组成,大小约为600KB。这是我打开电子表格的代码 - 相当标准:

//Include PHPExcel_IOFactory
include 'PHPExcel/IOFactory.php';
include 'PHPExcel.php';

$inputFileName = 'C:\xls\lspimport\GetLSP1.xlsx';

//  Read your Excel workbook
try {
    $inputFileType = PHPExcel_IOFactory::identify($inputFileName);
    $objReader = PHPExcel_IOFactory::createReader($inputFileType);
    $objReader->setReadDataOnly(true);
    $objPHPExcel = $objReader->load($inputFileName);
} catch(Exception $e) {
    die('Error loading file "'.pathinfo($inputFileName,PATHINFO_BASENAME).'": '.$e->getMessage());
}

//set active worksheet
$objWorksheet = $objPHPExcel->setActiveSheetIndexbyName('Sheet1');

$j = 0;

for($i = 2; $i < 3; $i++)
{
...
}

最后,我最终想要遍历电子表格中的每一行,但是在我完善脚本的过程中,我只是循环遍历一行。问题是,这个脚本需要30分钟才能执行。我在每段代码之后发送echo个消息,这样我就可以看到正在处理的内容以及何时处理,并且我的脚本在此部分基本上等待了30分钟:

$objPHPExcel = $objReader->load($inputFileName);

配置错误了吗?我无法弄清楚为什么加载电子表格需要30分钟。我感谢任何帮助。

4 个答案:

答案 0 :(得分:4)

PHPExcel在识别excel文件末尾的位置时遇到问题。或者更确切地说,Excel很难知道自己的结局在哪里。如果你触摸A:1000000处的一个单元格,它认为它需要读取那么远。

我过去做了两件事来解决这个问题:

1)将您需要的数据剪切并传递到新的Excel文件中。 2)指定要阅读的确切尺寸。

编辑如何执行选项2

public function readExcelDataToArray($excelFilePath, $maxRowNumber=-1, $maxColumnNumber=-1)
{
    $objPHPExcel = PHPExcel_IOFactory::load($excelFilePath);
    $objWorksheet = $objPHPExcel->getActiveSheet();

    //Get last row and column that have data
    if ($maxRowNumber == -1){
    $lastRow = $objWorksheet->getHighestDataRow();
    } else {
        $lastRow = $maxRowNumber;
    }

    if ($maxColumnNumber == -1){
        $lastCol = $objWorksheet->getHighestDataColumn();
        //Change Column letter to column number
        $lastCol = PHPExcel_Cell::columnIndexFromString($lastCol);      
    } else {
        $lastCol = $maxColumnNumber;
    }   

    //Get Data Array
    $dataArray = array();

    for ($currentRow = 1; $currentRow <= $lastRow; $currentRow++){
        for ($currentCol = 0; $currentCol <= $lastCol; $currentCol++){
            $dataArray[$currentRow][$currentCol] = $objWorksheet->getCellByColumnAndRow($currentCol,, $currentRow)->getValue();
        }
    }
    return $dataArray;
}

不幸的是,这些解决方案并不是很有活力。

请注意,现代excel文件实际上只是一个带有xlsx扩展名的zip。我已经编写了PHPExcel的扩展,解压缩它们,并修改某些xml文件以获得我想要的各种行为。

第三个建议是监控每一行的内容,当你得到一行时停止。

答案 1 :(得分:2)

已解决(对我而言) - 请参阅此帖子底部的注释

我正在尝试在具有16GB RAM的专用四核服务器上使用几乎完全相同的代码,同样运行类似版本 - PHPExcel 1.7.9和PHP 5.4.16

只需创建一个空的阅读器需要50秒!

// $inputFileType is 'Excel5';
$objReader = PHPExcel_IOFactory::createReader($inputFileType);

加载电子表格(1张,2000行,25列)我想处理(只读)然后需要1802秒。

$objReader->setReadDataOnly(true);
$objPHPExcel = $objReader->load($inputFileName);

在各种类型的阅读器中,我一直得到实例化的时间,如下所示

foreach(array(
  'Excel2007',     // 350 seconds
  'Excel5',        //  50 seconds
  'Excel2003XML',  //  50 seconds
  'OOCalc',        //  50 seconds
  'SYLK',          //  50 seconds
  'Gnumeric',      //  50 seconds
  'HTML',          // 250 seconds
  'CSV'            //  50 seconds
  ) as $inputFileType) {
  $objReader = PHPExcel_IOFactory::createReader($inputFileType);
}

峰值内存使用量约为8MB ......远远低于脚本可用的250MB。

我怀疑PHPExcel_IOFactory::createReader($inputFileType)是否在PHP 5.4.x下的循环中调用了一些东西?

然而过多的时间是由于PHPExcel如何命名其类名和相应的文件结构。它有一个自动加载器,可以将类名称* PHPExcel_abc_def *转换为 PHPExcel / abc / def.php 以获取require语句。虽然我们在include路径中定义了PHPExcel的类目录,但是我们自己的(已经定义的)自动加载器无法处理从类名到需要文件名的操作(它正在寻找* PHPExcel_abc_def.php *)。当无法包含类文件时,我们的自动加载器将循环5次,延迟10秒,以查看文件是否正在更新,因此可能变得可用。因此,对于需要加载的每个PHPExcel类,我们在使用PHPExcel自己的自动加载器之前引入了50秒的延迟,这需要该文件很好。

现在我已经解决了PHPExcel,证明它真的很棒。

答案 2 :(得分:0)

我在Symfony项目中使用最新版本的PHPExcel(1.8.1),并且在使用$ objReader-&gt; load($ file)方法时也遇到了时间延迟。时间延迟不是由自动加载器引起的,而是由加载方法本身引起的。此方法实际上读取每个工作表中的每个单元格。由于我的数据工作表是30列宽,5000行,所以在我的古老工作计算机上阅读所有这些信息花了大约90秒。

我认为单元格值的实际加载/读取会在我请求的时候动态发生,但看起来好像缺少PHPExcel代码的重要重写,这个初始加载时间没有真正的方法延迟。

答案 3 :(得分:0)

如果您知道您的文件是一个非常简单的Excel文件,您可以进行手动阅读。 .xslx文件只是一个zip存档,电子表格值和结构存储在xml文件中。这个脚本让我从PHPExcel上使用的60秒减少到0.18秒。

$zip = new ZipArchive();
$zip->open('path_to/file.xlsx');
$sheet_xml = simplexml_load_string($zip->getFromName('xl/worksheets/sheet1.xml'));
$sheet_array = json_decode(json_encode($xml), true);
$values = simplexml_load_string($zip->getFromName('xl/sharedStrings.xml'));
$values_array = json_decode(json_encode($values), true);

$end_result = array();
if ($sheet_array['sheetData']) {
    foreach ($sheet_array['sheetData']['row'] as $r => $row) {
        $end_result[$r] = array();
        foreach ($row['c'] as $c => $cell) {
            if (isset($cell['@attributes']['t'])) {
                if ($cell['@attributes']['t'] == 's') {
                    $end_result[$r][] = $values_array['si'][$cell['v']]['t'];
                } else if ($cell['@attributes']['t'] == 'e') {
                    $end_result[$r][] = '';
                }
            } else {
                $end_result[$r][] = $cell['v'];
            }
        }
    }
}

结果:

Array
(
    [0] => Array
        (
            [0] => A1
            [1] => B1
            [2] => C1
        )

    [1] => Array
        (
            [0] => A2
            [1] => B2
            [2] => C2
        )
)

这很容易出错而且没有优化,但它有效并说明了基本概念。如果你知道你的文件,那么你可以非常快速地阅读。如果您允许用户输入文件,那么您应该避免使用它 - 或者至少进行必要的检查。