2

我有一个包含公式的 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
4

2 回答 2

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 作为标准,但仅 H1:H530 作为 MS Excel 中的总和值,则它仅测试第一列(以匹配潜在的总和结果数)并忽略标准中的列 BH。

一个快速的解决方法可能是修改第 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 按行展平,而这需要按列展平) - 但作为临时修复,将您的公式更改为仅使用条件范围中的一列

于 2013-04-23T06:36:23.580 回答
0

如果你做 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。

于 2013-04-23T01:47:20.523 回答