我已经构建了一个报告解决方案,可以将数据导出为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))))),"")
我读到SUMIFS
会导致问题,但我不知道如何按照建议将这些重构为SUMPRODUCT
(这些仪表板是由业务开发团队构建的)。此外,我们将列的范围设置为10000,因为A:A等范围也不起作用。它们在Excel中运行良好,所以如果我能让PHPExcel停止尝试验证所有内容并让它通过,我的生活将是光荣的!
进一步研究堆栈跟踪,它似乎在尝试编写图表时开始发生:
查看图表生成作为此问题的根源,只有一个图表,它的数据源为='Sales History'!$Y$4:$CR$5
,我可以看到它肯定会尝试处理,但不应该&# 39;引起问题,因为它是一个相对简单的参考。
答案 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))))))
,"")