【发布时间】:2014-09-09 14:12:41
【问题描述】:
我正在使用 PHPExcel 1.8.0
我已阅读有关循环引用的帖子,例如 this one,但我仍然遇到问题。
- 如果电子表格包含一个循环引用。公式,PHPExcel 的计算与 MS Excel 不匹配。
- 如果电子表格包含多个循环引用,则 PHPExcel 将进入无限循环。
这里是我到目前为止所做的详细信息。
假设一个电子表格,其中 A1 = B1 和 B1 = A1+1,并且 Excel 设置为 100 次迭代。这是我的代码:
// create reader
$objReader = PHPExcel_IOFactory::createReader('Excel2007');
$objReader->setReadDataOnly(true);
// load workbook
$objPHPExcel = $objReader->load($this->_path);
// set iterative calculations max count
PHPExcel_Calculation::getInstance($objPHPExcel)->cyclicFormulaCount = 100;
// calculate
$objWorksheet = $objPHPExcel->getSheetByName('Testing');
$data = $objWorksheet->rangeToArray('A1:B1');
echo '<pre>';
print_r ($data);
echo '</pre>';
// release resources
$objPHPExcel->disconnectWorksheets();
unset($objPHPExcel);
MSExcel 的结果是 A1 = 99,B1 = 100。我的代码会产生这样的结果:
Array
(
[0] => Array
(
[0] => #VALUE!
[1] => #VALUE!
)
)
此外,如果我添加 A2 = B2 和 B2 = A2+1,并尝试计算 (A1:B2),它会进入无限循环并最终崩溃:
致命错误:第 2837 行 C:\xampp\htdocs\cgc\bulldog\application\third_party\PHPExcel\Calculation.php 中允许的内存大小为 134217728 字节已用尽(尝试分配 24 字节)
这是我到目前为止所做的。在 Calculation.php 中的 _calculateFormulaValue 中:
第 2383 行:$cellValue = ''; - 这是#Value 的原因!错误。我把它改成了$cellValue = 0;
第 2400 行:
} elseif ($this->_cyclicFormulaCell == '') {
$this->_cyclicFormulaCell = $wsTitle.'!'.$cellID;
这就是无限循环的原因。 $this->_cyclicFormulaCell 不会在第 1 行中的公式完成后重新设置为 '',因此此条件不适用于第 2 行中的公式。
从第 2389 行开始,我将其修复如下:
if (($wsTitle{0} !== "\x00") && ($this->_cyclicReferenceStack->onStack($wsTitle.'!'.$cellID))) {
if ($this->cyclicFormulaCount <= 0) {
return $this->_raiseFormulaError('Cyclic Reference in Formula');
} elseif (($this->_cyclicFormulaCount >= $this->cyclicFormulaCount) &&
($this->_cyclicFormulaCell == $wsTitle.'!'.$cellID)) {
// Olga - reset for next formula
$this->_cyclicFormulaCell = '';
return $cellValue;
} elseif ($this->_cyclicFormulaCell == $wsTitle.'!'.$cellID) {
++$this->_cyclicFormulaCount;
if ($this->_cyclicFormulaCount >= $this->cyclicFormulaCount) {
// Olga - reset for next formula
$this->_cyclicFormulaCell = '';
return $cellValue;
}
} elseif ($this->_cyclicFormulaCell == '') {
$this->_cyclicFormulaCell = $wsTitle.'!'.$cellID;
if ($this->_cyclicFormulaCount >= $this->cyclicFormulaCount) {
// Olga - reset for next formula
$this->_cyclicFormulaCell = '';
return $cellValue;
}
}
在这些修复之后,如果我运行$data = $objWorksheet->rangeToArray('A1:B2');,我会得到以下结果:
Array
(
[0] => Array
(
[0] => 100 // should be 99
[1] => 100
)
[1] => Array
(
[0] => 100 // should be 99
[1] => 100
)
)
如您所见,PHPExcel 的结果与 MS Excel 不一致。为什么会发生这种情况,我该如何解决?
【问题讨论】:
-
为什么会这样?因为开发人员不是机器,而且会犯错误。你怎么能绕过它?确定确切原因(例如,检查应该是
$this->_cyclicFormulaCount > $this->cyclicFormulaCount而不是$this->_cyclicFormulaCount >= $this->cyclicFormulaCount,测试并证明它,然后向github提交PR -
同时,我自己去看看....
$cellValue = ''确实应该依赖于单元格样式,而不是总是设置为 0 -
附言。感谢您的详细分析......大多数遇到问题的人只是说“它不起作用”(通常不会说到底是什么不起作用......只是希望我为他们解决它
-
看起来我需要存储循环中每个单独单元格的迭代计数,所以比我最初想象的要复杂一些
-
马克,非常感谢您的回复。对不起,当我问“为什么会发生这种情况”时,我并没有冒犯的意思——只是想澄清一下算法。不管怎样,我修好了,我在下面发布答案。
标签: phpexcel