【问题标题】:PHPExcel doesn't evaluate formulaPHPExcel 不计算公式
【发布时间】:2013-12-05 08:20:22
【问题描述】:

我正在尝试使用 PHPExcel 1.7.9 在我的 XSLX 工作簿中评估以下公式:=IF($H$7=1,$F$13,$H$227*$J$227)

在我必须更新工作簿中的一些单元格然后我使用这一行来计算值之前:

$sheet->getCell('L228')->getCalculatedValue();

但是,PHPExcel 似乎没有正确更新包含公式的单元格。它会抛出一些通知消息,如下所示,但不会更新单元格的计算值:

注意:未定义的偏移量:D:\my-path\hkc\Classes\PHPExcel\Calculation.php 第 2852 行中的 2

也不例外,getCalculatedValue() 似乎返回了 MS Excel 计算的旧缓存值。如下所述,我已经激活了计算引擎的调试日志,但它似乎是空的:

PHPExcel_CalcEngine_Logger Object
(
    [_writeDebugLog:PHPExcel_CalcEngine_Logger:private] => 
    [_echoDebugLog:PHPExcel_CalcEngine_Logger:private] => 
    [_debugLog:PHPExcel_CalcEngine_Logger:private] => Array
        (
        )

    [_cellStack:PHPExcel_CalcEngine_Logger:private] => PHPExcel_CalcEngine_CyclicReferenceStack Object
        (
            [_stack:PHPExcel_CalcEngine_CyclicReferenceStack:private] => Array
                (
                )

        )

)

我已经尝试了以下步骤来解决问题:

  1. 停用计算缓存:PHPExcel_Calculation::getInstance()->setCalculationCacheEnabled(FALSE);
  2. 激活计算引擎的调试模式:这在How to handle exception with PhpExcel? 尤其是http://phpexcel.codeplex.com/discussions/233047 中有描述
    但是,我不得不稍微修改引用页面的代码 - 也许 PHPExcel 1.7.9 中发生了一些变化?
    激活调试:PHPExcel_Calculation::getInstance()->writeDebugLog = true;
    获取调试日志:print_r(PHPExcel_Calculation::getInstance()->getDebugLog());

我不明白为什么引擎的实际日志是空的?引擎在写出任何条目之前停止工作,或者我的调试配置有问题?

但是,我尝试使用 Java 和 Apache POI 评估相同的公式 - 它奏效了!不幸的是,我必须在当前项目中使用 PHP。

请帮帮我!也许有人知道公式评估有什么问题,或者至少可以给我一些提示如何正确激活调试?

谢谢!

【问题讨论】:

    标签: php phpexcel


    【解决方案1】:

    还没有答案,但写评论太长了:

    PHPExcel 1.7.9 将计算引擎从单例修改为多例(在同时处理多个工作簿时需要避免冲突)。因此,每个工作簿都运行自己的计算引擎实例,并且在调用时

    PHPExcel_Calculation::getInstance()
    

    您现在必须指定需要访问的实例。每个 PHPExcel 实例都有一个 ID 值,保存在用于此目的的 PHPExcel 对象中,您需要将 PHPExcel 对象本身传递给 getInstance() 方法。所以,如果你的 PHPExcel 工作簿是 $objPHPExcel,你需要使用

    PHPExcel_Calculation::getInstance($objPHPExcel)
    

    在刷新缓存、启用记录器或读取日志时引用正确的计算引擎实例。

    重新。您的错误的细节:您的 IF 公式单元格引用的任何单元格是否引用了其他包含 CUBE 函数或 SUMIFS 函数的公式?这些是我知道的唯一可能触发此特定错误的功能

    编辑

    重构 SUMIFS() 函数的示例

    =SUMIFS(A2:A3, B2:B3, E1, C2:C3, F1)
    

    如果 B2:B3 符合 E1 标准,并且 C2:C3 符合 F1 标准,则对 A2:A3 求和。

    这可以重构为

    =SUMPRODUCT(A2:A3 * (B2:B3=E1) * (C2:C3=F1))
    

    【讨论】:

    • 我的计算引擎调试要点可以在gist.github.com/MarkBaker/5908357找到
    • 当我使用以下 PHPExcel_Calculation::getInstance($objPHPExcel->getID())->writeDebugLog = true; - 我收到此错误:Catchable fatal error: Argument 1 passed to PHPExcel_Calculation::getInstance() must be an instance of PHPExcel, string given 关于您的假设:是的,工作表确实包含大量 SUMIF 函数...
    • 过失,是的,你需要传递PHPExcel对象,而不是简单的ID; getInstance 函数将其自身提取出来......相应地进行编辑
    • Excel SUMIF() 函数应该没有问题:SUMIFS() 会在代码中的那个点产生问题
    • SUMIFS() 公式通常可以使用SUMPRODUCT() 重构
    【解决方案2】:

    我已经将一些 SUMIFS 重构为 SUMPRODUCT,它似乎可以工作。我目前正在寻找一种通过自动化方式进行重构的方法,因为工作表中有 50 多个 SUMIFS 公式。

    【讨论】:

      猜你喜欢
      • 2018-02-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多