【问题标题】:Computing output of an excel formula with PHPExcel使用 PHPExcel 计算 excel 公式的输出
【发布时间】:2013-04-23 01:24:13
【问题描述】:

我有一个包含公式的 Excel 电子表格。我想知道使用公式并根据给定输入计算输出的最佳方法是什么。

我的第一个想法是将展开加载到 PHPExcel 对象中,并将公式中涉及的每个单元格的值设置为给定的输入,然后最终读取结果。

编辑:我尝试通过以下方式获取公式的计算值:

getCalculatedValue()

我在应该包含“原样”传播的计算值的单元格上运行此方法,但它会吐出 Excel5.php 和 MathTrig.php 的未定义偏移错误以及不正确的结果:

Notice: Undefined offset: 437 in /Applications/MAMP/htdocs/bang/Classes/PHPExcel/Reader/Excel5.php on line 5679

Notice: Undefined offset: 438 in /Applications/MAMP/htdocs/bang/Classes/PHPExcel/Reader/Excel5.php on line 5679

Notice: Undefined offset: 439 in /Applications/MAMP/htdocs/bang/Classes/PHPExcel/Reader/Excel5.php on line 5679

Notice: Undefined offset: 9 in /Applications/MAMP/htdocs/bang/Classes/PHPExcel/Calculation/MathTrig.php on line 1171

在 PHPExcel 中调试的公式和堆栈跟踪是:

Value is =SUMIF(Sheet3!A1:H530,"=212410000",Sheet3!H1:H530)
Parser Stack :-
Array
(
    [0] => Array
        (
            [type] => Cell Reference
            [value] => Sheet3!A1
            [reference] => Sheet3!A1
        )

    [1] => Array
        (
            [type] => Cell Reference
            [value] => Sheet3!H530
            [reference] => Sheet3!H530
        )

    [2] => Array
        (
            [type] => Binary Operator
            [value] => :
            [reference] => 
        )

    [3] => Array
        (
            [type] => Value
            [value] => "=212410000"
            [reference] => 
        )

    [4] => Array
        (
            [type] => Cell Reference
            [value] => Sheet3!H1
            [reference] => Sheet3!H1
        )

    [5] => Array
        (
            [type] => Cell Reference
            [value] => Sheet3!H530
            [reference] => Sheet3!H530
        )

    [6] => Array
        (
            [type] => Binary Operator
            [value] => :
            [reference] => 
        )

    [7] => Array
        (
            [type] => Operand Count for Function SUMIF()
            [value] => 3
            [reference] => 
        )

    [8] => Array
        (
            [type] => Function
            [value] => SUMIF(
            [reference] => 
        )

)

Excel5.php 中触发错误的行是:

    // offset: 1; size: 2; one-based index to definedname record
                $definedNameIndex = self::_GetInt2d($formulaData, 1) - 1;
                // offset: 2; size: 2; not used
                $data = $this->_definedname[$definedNameIndex]['name']; // errors here

【问题讨论】:

    标签: php phpexcel


    【解决方案1】:

    您可以在调试模式下运行计算引擎,以获得更多关于它正在做什么来帮助诊断此类问题的详细信息:

    $cell = 'C3';
    //  enable debugging
    PHPExcel_Calculation::getInstance()->writeDebugLog = true;
    
    $sheet = $objPHPExcel->getActiveSheet();
    $formulaValue = $sheet->getCell($cell)->getValue();
    echo '<b>'.$cell.' Value is </b>'.$formulaValue."<br />\n";
    
    $calculate = false;
    try {
        $tokens = PHPExcel_Calculation::getInstance()->parseFormula($formulaValue,$sheet->getCell($cell));
        echo '<b>Parser Stack :-</b><pre>';
        print_r($tokens);
        echo '</pre>';
        $calculate = true;
    } catch (Exception $e) {
        echo "PARSER ERROR: ".$e->getMessage()."<br />\n";
    
        echo '<b>Parser Stack :-</b><pre>';
        print_r($tokens);
        echo '</pre>';
    }
    
    if ($calculate) {
        //  calculate
        try {
            $cellValue = $sheet->getCell($cell)->getCalculatedValue();
        } catch (Exception $e) {
            echo "CALCULATION ENGINE ERROR: ".$e->getMessage()."<br />\n";
    
            echo '<h3>Evaluation Log:</h3><pre>';
            print_r(PHPExcel_Calculation::getInstance()->debugLog);
            echo '</pre>';
        }
    }
    

    编辑

    不保证,因为我需要对其进行更多测试,但修改 Classes/PHPExcel/Calculation/MathTrig.php 文件中的第 1171 行

    这一行当前为

    $returnValue += $sumArgs[$key];
    

    改成

    $returnValue += $sumArgs[$key % count($sumArgs)];
    

    假设条件范围内的单元格数(在您的情况下为 Sheet3!A1:H530)与总和范围内的单元格数(Sheet3!H1:H530)相匹配,这显然不是条件时的情况引用 8 列和 530 行,而求和范围仅引用单列中的 530 行。

    编辑#2

    虽然上面的编辑建议会修复错误,但它会返回错误的结果。如果您将 A1:H530 指定为条件,但在 MS Excel 中仅将 H1:H530 指定为求和值,则它仅测试第一列(以匹配求和结果的潜在数量)并忽略条件中的 B-H 列。

    一个快速的解决方法可能是修改第 1161 行:

    if (empty($sumArgs)) {
        $sumArgs = $aArgs;
    }
    

    if (empty($sumArgs)) {
        $sumArgs = $aArgs;
    } elseif (count($aArgs) > count($sumArgs)) {
        $aArgs = array_slice($aArgs,0,count($sumArgs));
    }
    

    并将第 1171 行(现在为 1173)恢复为

    $returnValue += $sumArgs[$key];
    

    我仍然需要检查 flattenArray 是否正确地对单元格进行排序,但这将是一个更接近的修复

    编辑#3

    修复 PHPExcel 的计算引擎以处理不匹配的标准/求和数组需要更长的时间(我上面的修复不起作用,因为 PHPExcel 按行展平,而这需要按列展平) - 但作为临时修复更改您的公式仅使用条件范围中的一列

    【讨论】:

    • 您好,感谢您的指点。不幸的是,在“计算”块中捕获的错误是相同的,没有更具体的。注意:/Applications/MAMP/htdocs/bang/Classes/PHPExcel/Calculation/MathTrig.php 第 1171 行中未定义的偏移量。此外,Excel5.php 的读取器错误总是在将文件加载到内存时打印出来。
    • 它没有触发计算单元格值的catch块。
    • 听起来更像是读者问题而不是公式问题。此代码是否正在转储公式和堆栈?
    • 那么 MathTrig.php 中的错误是指 SUMIF 函数中的一行,这是我使用的公式。这是。已编辑答案以包含此内容。
    • 我担心 SUMIF 公式正试图对导致这些读取错误的任何原因未正确读取的单元格执行某些操作 - 但我想验证 SUMIF 公式是否正在正确解析
    【解决方案2】:

    如果你使用 toArray,你可以:

    $objWorksheet = $objPHPExcel->setActiveSheetIndex($index);
    $arrExcelObject = $objPHPExcel->getActiveSheet()->toArray(null,true,true,true);
    

    toArray 函数记录在代码中:

    public function toArray($nullValue = null, $calculateFormulas = true, $formatData = true, $returnColumnRef = false)
    

    所以第二个参数表示你想从公式中计算,默认设置为true。

    【讨论】:

    • 嗨,这就像 getCalculateValue,只是它返回一个包含所有单元格及其各自公式计算值的数组,对吗?但是,当我运行它时出现以下错误:未定义的偏移量:PHPExcel/Calculation/MathTrig.php 未定义的偏移量:PHPExcel/Reader/Excel5.php
    • 它将从您的 xls 返回一个行数组。在没有任何信息的情况下不确定错误。但我建议你先试试 xls 文件而不是 xlsx。
    • 当前输入为.xls。除了错误的位置之外,我不确定我可以提供哪些信息。未定义的偏移量是指 PHPExcel 中的以下行:[Excel5.php - 5679] 和 [MathTrig.php - 1171] 是否有帮助?我知道 PHPExcel 计算引擎有一些限制。
    • calc 不能做自定义 excel 宏。 PHPExcel calc 真的很差,但您可能想检查 xls 中的数据/公式。我每周运行 PHPExcel,简单的计算没有问题。如果一切都失败了,我认为你必须将值复制到新行。
    • 我在 MathTrig.php 中找到了触发错误的公式部分。它是一个“SUMIF”,它尝试匹配格式为:=SUMIF(Sheet2!RANGE,"STRING",Sheet2!RANGE) 的字符串。所有值都在 excel 中正确计算。
    猜你喜欢
    • 1970-01-01
    • 2018-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多