导出到Excel时,将公式视为任何其他文本值

时间:2015-11-05 20:26:03

标签: php excel phpexcel

我已经构建了一个报告解决方案,可以将数据导出为Excel。使用PHPExcel,这项工作非常精彩。但是,我们需要构建仪表板样式模板表并在运行时将它们插入到输出中,包括公式。我的所有工作都很好,我的问题是,有时这些仪表板模板相当复杂,并且PHPExcel在尝试输出时会对公式产生影响。

我花了相当多的时间找到解决方法,甚至到了forking my own branch并添加了一种禁用计算的方法,试图阻止公式被处理,但是无法得到它上班。我也试过禁用计算缓存。

@MarkBaker在这个库中做得非常出色,我已经多次看到他提到这不是为修改文件而设计的,但如果做得非常仔细,它似乎有用。

我的问题是,如何告诉PHPExcel 停止尝试计算公式?我希望它像对待任何其他文本值一样对待它们,让Excel本身处理验证。这可能吗?

例如,这是一个PHPExcel似乎不喜欢的公式:

=IFERROR(IF($L$3="UNITS",COUNTIF('K1_Current_Accounts'!$M$2:$M$10000,'Snapshot Summary'!H5)+COUNTIF('K1_Current_Available'!$M$2:$M$10000,'Snapshot Summary'!H5),IF($L$3="Cost Basis",SUMIF('K1_Current_Accounts'!$M$2:$M$10000,'Snapshot Summary'!H5,'K1_Current_Accounts'!$E$2:$E$10000)+SUMIF('K1_Current_Available'!$M$2:$M$10000,'Snapshot Summary'!H5,'K1_Current_Available'!$E$2:$E$10000),IF($L$3="Notes",SUMIFS('K1_Current_Accounts'!$AA$2:$AA$10000,'K1_Current_Accounts'!$M$2:$M$10000,'Snapshot Summary'!H5,'K1_Current_Accounts'!$R$2:$R$10000,'Snapshot Summary'!$A$7)+SUMIFS('K1_Current_Accounts'!$AA$2:$AA$10000,'K1_Current_Accounts'!$M$2:$M$10000,'Snapshot Summary'!H5,'K1_Current_Accounts'!$R$2:$R$10000,'Snapshot Summary'!$A$8)+SUMIFS('K1_Current_Accounts'!$AA$2:$AA$10000,'K1_Current_Accounts'!$M$2:$M$10000,'Snapshot Summary'!H5,'K1_Current_Accounts'!$R$2:$R$10000,'Snapshot Summary'!$A$9),IF($L$3="Cash",SUMIFS('K1_Historical_Accounts'!$AC$2:$AC$10000,'K1_Historical_Accounts'!$M$2:$M$10000,'Snapshot Summary'!H5,'K1_Historical_Accounts'!$R$2:$R$10000,'Snapshot Summary'!$A$10))))),"")

enter image description here

我读到SUMIFS会导致问题,但我不知道如何按照建议将这些重构为SUMPRODUCT(这些仪表板是由业务开发团队构建的)。此外,我们将列的范围设置为10000,因为A:A等范围也不起作用。它们在Excel中运行良好,所以如果我能让PHPExcel停止尝试验证所有内容并让它通过,我的生活将是光荣的!

修改

进一步研究堆栈跟踪,它似乎在尝试编写图表时开始发生:

enter image description here

编辑2

查看图表生成作为此问题的根源,只有一个图表,它的数据源为='Sales History'!$Y$4:$CR$5,我可以看到它肯定会尝试处理,但不应该&# 39;引起问题,因为它是一个相对简单的参考。

2 个答案:

答案 0 :(得分:0)

您可以通过使用

将Writer的preCalculateFormulas标志设置为false来阻止PHPExcel在编写时计算公式
$objWriter->setPreCalculateFormulas(false);

修改

我已对Excel2007 Writer进行了一些实验性更改,以禁用图表的单元格计算:

/PHPExcel/Writer/Excel2007/Chart.php我添加了一个新属性

protected $calculateCellValues;

并修改了writeChart()方法以接受另一个参数:

public function writeChart(PHPExcel_Chart $pChart = null, $calculateCellValues = true)
{
    $this->calculateCellValues = $calculateCellValues;

并修改了对$pChart->refresh()

的后续调用
//    Ensure that data series values are up-to-date before we save
if ($this->calculateCellValues) {
    $pChart->refresh();
}

save()的{​​{1}}方法中,我将第300行周围的/PHPExcel/Writer/Excel2007.php调用修改为:

writeChart()

(即我已将$objZip->addFromString( 'xl/charts/chart' . ($chartCount + 1) . '.xml', $this->getWriterPart('Chart') ->writeChart($chart, $this->preCalculateFormulas) ); 注入图表编写器。)

临时测试显示MS Excel将在打开生成的xlsx文件时触发重新计算....但这不是一个完整的测试

答案 1 :(得分:0)

我从未使用过PHPExcel,但我可以将SUMIF / S()中的公式重新编写为SUMPRODUCTS。您可以使用Alt + Enter使这些大型公式具有一定的可读性。

为了了解sumproduct,当应用任何数学运算时,Excel将TRUE / FALSE视为1/0,因此您可以{TRUE,TRUE,FALSE} x {FALSE,TRUE,TRUE}得到{0 ,1,0}。然后SUMPRODUCT获取{0,1,0}并将其乘以您尝试过滤的行/列总计,然后对这些值求和。

=IFERROR(
IF($L$3="UNITS",
COUNTIF('K1_Current_Accounts'!$M$2:$M$10000,'Snapshot Summary'!H5)
+COUNTIF('K1_Current_Available'!$M$2:$M$10000,'Snapshot Summary'!H5),
IF($L$3="Cost Basis",
SUMPRODUCT(--('K1_Current_Accounts'!$M$2:$M$10000='Snapshot Summary'!H5),'K1_Current_Accounts'!$E$2:$E$10000)
+SUMPRODUCT(--('K1_Current_Available'!$M$2:$M$10000='Snapshot Summary'!H5),'K1_Current_Available'!$E$2:$E$10000),
IF($L$3="Notes",
SUMPRODUCT('K1_Current_Accounts'!$AA$2:$AA$10000,--('K1_Current_Accounts'!$M$2:$M$10000='Snapshot Summary'!H5),--('K1_Current_Accounts'!$R$2:$R$10000='Snapshot Summary'!$A$7))
+SUMPRODUCT('K1_Current_Accounts'!$AA$2:$AA$10000,--('K1_Current_Accounts'!$M$2:$M$10000='Snapshot Summary'!H5),--('K1_Current_Accounts'!$R$2:$R$10000='Snapshot Summary'!$A$8))
+SUMPRODUCT('K1_Current_Accounts'!$AA$2:$AA$10000,--('K1_Current_Accounts'!$M$2:$M$10000='Snapshot Summary'!H5),--('K1_Current_Accounts'!$R$2:$R$10000='Snapshot Summary'!$A$9)),
IF($L$3="Cash",
SUMPRODUCT('K1_Historical_Accounts'!$AC$2:$AC$10000,--('K1_Historical_Accounts'!$M$2:$M$10000='Snapshot Summary'!H5),--('K1_Historical_Accounts'!$R$2:$R$10000='Snapshot Summary'!$A$10))))))
,"")