3

我正在使用 PHPExcel 1.7.8、PHP 5.4.14、Windows 7 和 Excel 2007 电子表格。该电子表格由 750 行、A 到 BW 列组成,大小约为 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

4 回答 4

5

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 文件以获得我想要的行为类型。

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

于 2013-05-24T19:57:35.623 回答
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 语句使用。尽管我们在包含路径中定义了 PHPExcel 的类目录,但我们自己的(已经定义的)自动加载器无法处理从类名到所需文件名的操作(它正在寻找 *PHPExcel_abc_def.php*)。当无法包含类文件时,我们的自动加载器将循环 5 次,延迟 10 秒,以查看文件是否正在更新以及是否可用。因此,对于每个需要加载的 PHPExcel 类,我们都引入了 50 秒的延迟,然后才点击 PHPExcel 自己的自动加载器,该自动加载器需要文件正常。

现在我已经解决了 PHPExcel 被证明是非常棒的。

于 2013-08-22T15:04:28.193 回答
0

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

我假设单元格值的真正加载/读取将在我请求它们时即时发生,但看起来没有对 PHPExcel 代码进行相当大的重写,没有真正解决这个初始加载时间延迟的方法。

于 2015-06-30T00:25:22.870 回答
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
        )
)

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

于 2017-02-16T15:25:32.063 回答